comparison src/http/ngx_http_spdy.c @ 5923:2c10db908b8c

SPDY: push pending data while closing a stream as with keepalive. This helps to avoid delays in sending the last chunk of data because of bad interaction between Nagle's algorithm on nginx side and delayed ACK on the client side. Delays could also be caused by TCP_CORK/TCP_NOPUSH if SPDY was working without SSL and sendfile() was used.
author Valentin Bartenev <vbart@nginx.com>
date Fri, 21 Nov 2014 22:51:49 +0300
parents abb466a57a22
children 199c0dd313ea
comparison
equal deleted inserted replaced
5922:68f64bc17fa4 5923:2c10db908b8c
3315 3315
3316 3316
3317 void 3317 void
3318 ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) 3318 ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc)
3319 { 3319 {
3320 int tcp_nodelay;
3320 ngx_event_t *ev; 3321 ngx_event_t *ev;
3321 ngx_connection_t *fc; 3322 ngx_connection_t *c, *fc;
3323 ngx_http_core_loc_conf_t *clcf;
3322 ngx_http_spdy_stream_t **index, *s; 3324 ngx_http_spdy_stream_t **index, *s;
3323 ngx_http_spdy_srv_conf_t *sscf; 3325 ngx_http_spdy_srv_conf_t *sscf;
3324 ngx_http_spdy_connection_t *sc; 3326 ngx_http_spdy_connection_t *sc;
3325 3327
3326 sc = stream->connection; 3328 sc = stream->connection;
3341 NGX_SPDY_INTERNAL_ERROR, 3343 NGX_SPDY_INTERNAL_ERROR,
3342 stream->priority) 3344 stream->priority)
3343 != NGX_OK) 3345 != NGX_OK)
3344 { 3346 {
3345 sc->connection->error = 1; 3347 sc->connection->error = 1;
3348 }
3349
3350 } else {
3351 c = sc->connection;
3352
3353 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
3354 if (ngx_tcp_push(c->fd) == -1) {
3355 ngx_connection_error(c, ngx_socket_errno,
3356 ngx_tcp_push_n " failed");
3357 c->error = 1;
3358 tcp_nodelay = 0;
3359
3360 } else {
3361 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
3362 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
3363 }
3364
3365 } else {
3366 tcp_nodelay = 1;
3367 }
3368
3369 clcf = ngx_http_get_module_loc_conf(stream->request,
3370 ngx_http_core_module);
3371
3372 if (tcp_nodelay
3373 && clcf->tcp_nodelay
3374 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
3375 {
3376 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
3377
3378 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
3379 (const void *) &tcp_nodelay, sizeof(int))
3380 == -1)
3381 {
3382 #if (NGX_SOLARIS)
3383 /* Solaris returns EINVAL if a socket has been shut down */
3384 c->log_error = NGX_ERROR_IGNORE_EINVAL;
3385 #endif
3386
3387 ngx_connection_error(c, ngx_socket_errno,
3388 "setsockopt(TCP_NODELAY) failed");
3389
3390 c->log_error = NGX_ERROR_INFO;
3391 c->error = 1;
3392
3393 } else {
3394 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
3395 }
3346 } 3396 }
3347 } 3397 }
3348 3398
3349 if (sc->stream == stream) { 3399 if (sc->stream == stream) {
3350 sc->stream = NULL; 3400 sc->stream = NULL;