@@ -47,6 +47,8 @@ static void ngx_ssl_write_handler(ngx_event_t *wev);
47
47
static ssize_t ngx_ssl_write_early (ngx_connection_t * c , u_char * data ,
48
48
size_t size );
49
49
#endif
50
+ static ssize_t ngx_ssl_sendfile (ngx_connection_t * c , ngx_buf_t * file ,
51
+ size_t size );
50
52
static void ngx_ssl_read_handler (ngx_event_t * rev );
51
53
static void ngx_ssl_shutdown_handler (ngx_event_t * ev );
52
54
static void ngx_ssl_connection_error (ngx_connection_t * c , int sslerr ,
@@ -1762,6 +1764,16 @@ ngx_ssl_handshake(ngx_connection_t *c)
1762
1764
1763
1765
#endif
1764
1766
#endif
1767
+ #endif
1768
+
1769
+ #ifdef BIO_get_ktls_send
1770
+
1771
+ if (BIO_get_ktls_send (SSL_get_wbio (c -> ssl -> connection )) == 1 ) {
1772
+ ngx_log_debug0 (NGX_LOG_DEBUG_EVENT , c -> log , 0 ,
1773
+ "BIO_get_ktls_send(): 1" );
1774
+ c -> ssl -> sendfile = 1 ;
1775
+ }
1776
+
1765
1777
#endif
1766
1778
1767
1779
rc = ngx_ssl_ocsp_validate (c );
@@ -1899,6 +1911,16 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
1899
1911
c -> read -> ready = 1 ;
1900
1912
c -> write -> ready = 1 ;
1901
1913
1914
+ #ifdef BIO_get_ktls_send
1915
+
1916
+ if (BIO_get_ktls_send (SSL_get_wbio (c -> ssl -> connection )) == 1 ) {
1917
+ ngx_log_debug0 (NGX_LOG_DEBUG_EVENT , c -> log , 0 ,
1918
+ "BIO_get_ktls_send(): 1" );
1919
+ c -> ssl -> sendfile = 1 ;
1920
+ }
1921
+
1922
+ #endif
1923
+
1902
1924
rc = ngx_ssl_ocsp_validate (c );
1903
1925
1904
1926
if (rc == NGX_ERROR ) {
@@ -2502,10 +2524,11 @@ ngx_ssl_write_handler(ngx_event_t *wev)
2502
2524
ngx_chain_t *
2503
2525
ngx_ssl_send_chain (ngx_connection_t * c , ngx_chain_t * in , off_t limit )
2504
2526
{
2505
- int n ;
2506
- ngx_uint_t flush ;
2507
- ssize_t send , size ;
2508
- ngx_buf_t * buf ;
2527
+ int n ;
2528
+ ngx_uint_t flush ;
2529
+ ssize_t send , size , file_size ;
2530
+ ngx_buf_t * buf ;
2531
+ ngx_chain_t * cl ;
2509
2532
2510
2533
if (!c -> ssl -> buffer ) {
2511
2534
@@ -2579,6 +2602,11 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
2579
2602
continue ;
2580
2603
}
2581
2604
2605
+ if (in -> buf -> in_file && c -> ssl -> sendfile ) {
2606
+ flush = 1 ;
2607
+ break ;
2608
+ }
2609
+
2582
2610
size = in -> buf -> last - in -> buf -> pos ;
2583
2611
2584
2612
if (size > buf -> end - buf -> last ) {
@@ -2610,8 +2638,35 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
2610
2638
size = buf -> last - buf -> pos ;
2611
2639
2612
2640
if (size == 0 ) {
2641
+
2642
+ if (in && in -> buf -> in_file && send < limit ) {
2643
+
2644
+ /* coalesce the neighbouring file bufs */
2645
+
2646
+ cl = in ;
2647
+ file_size = (size_t ) ngx_chain_coalesce_file (& cl , limit - send );
2648
+
2649
+ n = ngx_ssl_sendfile (c , in -> buf , file_size );
2650
+
2651
+ if (n == NGX_ERROR ) {
2652
+ return NGX_CHAIN_ERROR ;
2653
+ }
2654
+
2655
+ if (n == NGX_AGAIN ) {
2656
+ break ;
2657
+ }
2658
+
2659
+ in = ngx_chain_update_sent (in , n );
2660
+
2661
+ send += n ;
2662
+ flush = 0 ;
2663
+
2664
+ continue ;
2665
+ }
2666
+
2613
2667
buf -> flush = 0 ;
2614
2668
c -> buffered &= ~NGX_SSL_BUFFERED ;
2669
+
2615
2670
return in ;
2616
2671
}
2617
2672
@@ -2636,7 +2691,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
2636
2691
buf -> pos = buf -> start ;
2637
2692
buf -> last = buf -> start ;
2638
2693
2639
- if (in == NULL || send = = limit ) {
2694
+ if (in == NULL || send > = limit ) {
2640
2695
break ;
2641
2696
}
2642
2697
}
@@ -2882,6 +2937,150 @@ ngx_ssl_write_early(ngx_connection_t *c, u_char *data, size_t size)
2882
2937
#endif
2883
2938
2884
2939
2940
+ static ssize_t
2941
+ ngx_ssl_sendfile (ngx_connection_t * c , ngx_buf_t * file , size_t size )
2942
+ {
2943
+ #ifdef BIO_get_ktls_send
2944
+
2945
+ int sslerr ;
2946
+ ssize_t n ;
2947
+ ngx_err_t err ;
2948
+
2949
+ ngx_ssl_clear_error (c -> log );
2950
+
2951
+ ngx_log_debug2 (NGX_LOG_DEBUG_EVENT , c -> log , 0 ,
2952
+ "SSL to sendfile: @%O %uz" ,
2953
+ file -> file_pos , size );
2954
+
2955
+ ngx_set_errno (0 );
2956
+
2957
+ n = SSL_sendfile (c -> ssl -> connection , file -> file -> fd , file -> file_pos ,
2958
+ size , 0 );
2959
+
2960
+ ngx_log_debug1 (NGX_LOG_DEBUG_EVENT , c -> log , 0 , "SSL_sendfile: %d" , n );
2961
+
2962
+ if (n > 0 ) {
2963
+
2964
+ if (c -> ssl -> saved_read_handler ) {
2965
+
2966
+ c -> read -> handler = c -> ssl -> saved_read_handler ;
2967
+ c -> ssl -> saved_read_handler = NULL ;
2968
+ c -> read -> ready = 1 ;
2969
+
2970
+ if (ngx_handle_read_event (c -> read , 0 ) != NGX_OK ) {
2971
+ return NGX_ERROR ;
2972
+ }
2973
+
2974
+ ngx_post_event (c -> read , & ngx_posted_events );
2975
+ }
2976
+
2977
+ c -> sent += n ;
2978
+
2979
+ return n ;
2980
+ }
2981
+
2982
+ if (n == 0 ) {
2983
+
2984
+ /*
2985
+ * if sendfile returns zero, then someone has truncated the file,
2986
+ * so the offset became beyond the end of the file
2987
+ */
2988
+
2989
+ ngx_log_error (NGX_LOG_ALERT , c -> log , 0 ,
2990
+ "SSL_sendfile() reported that \"%s\" was truncated at %O" ,
2991
+ file -> file -> name .data , file -> file_pos );
2992
+
2993
+ return NGX_ERROR ;
2994
+ }
2995
+
2996
+ sslerr = SSL_get_error (c -> ssl -> connection , n );
2997
+
2998
+ if (sslerr == SSL_ERROR_ZERO_RETURN ) {
2999
+
3000
+ /*
3001
+ * OpenSSL fails to return SSL_ERROR_SYSCALL if an error
3002
+ * happens during writing after close_notify alert from the
3003
+ * peer, and returns SSL_ERROR_ZERO_RETURN instead
3004
+ */
3005
+
3006
+ sslerr = SSL_ERROR_SYSCALL ;
3007
+ }
3008
+
3009
+ if (sslerr == SSL_ERROR_SSL
3010
+ && ERR_GET_REASON (ERR_peek_error ()) == SSL_R_UNINITIALIZED
3011
+ && ngx_errno != 0 )
3012
+ {
3013
+ /*
3014
+ * OpenSSL fails to return SSL_ERROR_SYSCALL if an error
3015
+ * happens in sendfile(), and returns SSL_ERROR_SSL with
3016
+ * SSL_R_UNINITIALIZED reason instead
3017
+ */
3018
+
3019
+ sslerr = SSL_ERROR_SYSCALL ;
3020
+ }
3021
+
3022
+ err = (sslerr == SSL_ERROR_SYSCALL ) ? ngx_errno : 0 ;
3023
+
3024
+ ngx_log_debug1 (NGX_LOG_DEBUG_EVENT , c -> log , 0 , "SSL_get_error: %d" , sslerr );
3025
+
3026
+ if (sslerr == SSL_ERROR_WANT_WRITE ) {
3027
+
3028
+ if (c -> ssl -> saved_read_handler ) {
3029
+
3030
+ c -> read -> handler = c -> ssl -> saved_read_handler ;
3031
+ c -> ssl -> saved_read_handler = NULL ;
3032
+ c -> read -> ready = 1 ;
3033
+
3034
+ if (ngx_handle_read_event (c -> read , 0 ) != NGX_OK ) {
3035
+ return NGX_ERROR ;
3036
+ }
3037
+
3038
+ ngx_post_event (c -> read , & ngx_posted_events );
3039
+ }
3040
+
3041
+ c -> write -> ready = 0 ;
3042
+ return NGX_AGAIN ;
3043
+ }
3044
+
3045
+ if (sslerr == SSL_ERROR_WANT_READ ) {
3046
+
3047
+ ngx_log_debug0 (NGX_LOG_DEBUG_EVENT , c -> log , 0 ,
3048
+ "SSL_sendfile: want read" );
3049
+
3050
+ c -> read -> ready = 0 ;
3051
+
3052
+ if (ngx_handle_read_event (c -> read , 0 ) != NGX_OK ) {
3053
+ return NGX_ERROR ;
3054
+ }
3055
+
3056
+ /*
3057
+ * we do not set the timer because there is already
3058
+ * the write event timer
3059
+ */
3060
+
3061
+ if (c -> ssl -> saved_read_handler == NULL ) {
3062
+ c -> ssl -> saved_read_handler = c -> read -> handler ;
3063
+ c -> read -> handler = ngx_ssl_read_handler ;
3064
+ }
3065
+
3066
+ return NGX_AGAIN ;
3067
+ }
3068
+
3069
+ c -> ssl -> no_wait_shutdown = 1 ;
3070
+ c -> ssl -> no_send_shutdown = 1 ;
3071
+ c -> write -> error = 1 ;
3072
+
3073
+ ngx_ssl_connection_error (c , sslerr , err , "SSL_sendfile() failed" );
3074
+
3075
+ #else
3076
+ ngx_log_error (NGX_LOG_ALERT , c -> log , 0 ,
3077
+ "SSL_sendfile() not available" );
3078
+ #endif
3079
+
3080
+ return NGX_ERROR ;
3081
+ }
3082
+
3083
+
2885
3084
static void
2886
3085
ngx_ssl_read_handler (ngx_event_t * rev )
2887
3086
{
0 commit comments