Ticket #1298: udp_session_reuse.diff

File udp_session_reuse.diff, 14.0 KB (added by cheng0201@…, 9 years ago)

udp session reuse diff

  • nginx-1.12.0/src/core/ngx_buf.c

    diff --git a/nginx-1.12.0/src/core/ngx_buf.c b/nginx-1.12.0/src/core/ngx_buf.c
    old mode 100644
    new mode 100755
    index 1862a06..100e5ca
    a b ngx_create_temp_buf(ngx_pool_t *pool, size_t size)  
    4343    return b;
    4444}
    4545
     46ngx_buf_t *
     47ngx_recreate_temp_buf(ngx_buf_t *b, ngx_pool_t *pool, size_t size)
     48{
     49    if (b == NULL) {
     50        return NULL;
     51    }
     52
     53    if (b->start != NULL && ngx_pfree(pool, b->start) != NGX_OK) {
     54        return NULL;
     55    }
     56
     57    ngx_memzero(b, sizeof(ngx_buf_t));
     58    b->start = ngx_palloc(pool, size);
     59    if (b->start == NULL) {
     60        return NULL;
     61    }
     62
     63    /*
     64     * set by ngx_calloc_buf():
     65     *
     66     *     b->file_pos = 0;
     67     *     b->file_last = 0;
     68     *     b->file = NULL;
     69     *     b->shadow = NULL;
     70     *     b->tag = 0;
     71     *     and flags
     72     */
     73
     74    b->pos = b->start;
     75    b->last = b->start;
     76    b->end = b->last + size;
     77    b->temporary = 1;
     78
     79    return b;
     80}
     81
    4682
    4783ngx_chain_t *
    4884ngx_alloc_chain_link(ngx_pool_t *pool)
  • nginx-1.12.0/src/core/ngx_buf.h

    diff --git a/nginx-1.12.0/src/core/ngx_buf.h b/nginx-1.12.0/src/core/ngx_buf.h
    old mode 100644
    new mode 100755
    index 12781a7..c0e1dcf
    a b typedef struct {  
    141141                            (b->file_last - b->file_pos))
    142142
    143143ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
     144ngx_buf_t *ngx_recreate_temp_buf(ngx_buf_t *b, ngx_pool_t *pool, size_t size);
    144145ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs);
    145146
    146147
  • nginx-1.12.0/src/core/ngx_connection.c

    diff --git a/nginx-1.12.0/src/core/ngx_connection.c b/nginx-1.12.0/src/core/ngx_connection.c
    old mode 100644
    new mode 100755
    index 2af2876..4fe9040
    a b ngx_close_connection(ngx_connection_t *c)  
    11581158
    11591159    log_error = c->log_error;
    11601160
     1161    if (c->type == SOCK_DGRAM && c->listening != NULL) {
     1162        uint64_t client_key = sock2key((struct sockaddr_in *)c->sockaddr);
     1163        ngx_radix64tree_delete(c->listening->dgram_conns, client_key, client_key);
     1164    }
     1165
    11611166    ngx_free_connection(c);
    11621167
    11631168    fd = c->fd;
  • nginx-1.12.0/src/core/ngx_connection.h

    diff --git a/nginx-1.12.0/src/core/ngx_connection.h b/nginx-1.12.0/src/core/ngx_connection.h
    old mode 100644
    new mode 100755
    index 1d3e3a3..d3182f0
    a b struct ngx_listening_s {  
    8787    int                 fastopen;
    8888#endif
    8989
     90    ngx_radix_tree_t   *dgram_conns;
    9091};
    9192
    9293
  • nginx-1.12.0/src/core/ngx_radix_tree.c

    diff --git a/nginx-1.12.0/src/core/ngx_radix_tree.c b/nginx-1.12.0/src/core/ngx_radix_tree.c
    old mode 100644
    new mode 100755
    index c1d8737..4ebaebd
    a b ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)  
    262262    return value;
    263263}
    264264
     265ngx_int_t
     266ngx_radix64tree_insert(ngx_radix_tree_t *tree, uint64_t key, uint64_t mask,
     267    uintptr_t value)
     268{
     269    uint64_t           bit;
     270    ngx_radix_node_t  *node, *next;
     271
     272    bit = 0x8000000000000000;
     273
     274    node = tree->root;
     275    next = tree->root;
     276
     277    while (bit & mask) {
     278        if (key & bit) {
     279            next = node->right;
     280
     281        } else {
     282            next = node->left;
     283        }
     284
     285        if (next == NULL) {
     286            break;
     287        }
     288
     289        bit >>= 1;
     290        node = next;
     291    }
     292
     293    if (next) {
     294        if (node->value != NGX_RADIX_NO_VALUE) {
     295            return NGX_BUSY;
     296        }
     297
     298        node->value = value;
     299        return NGX_OK;
     300    }
     301
     302    while (bit & mask) {
     303        next = ngx_radix_alloc(tree);
     304        if (next == NULL) {
     305            return NGX_ERROR;
     306        }
     307
     308        next->right = NULL;
     309        next->left = NULL;
     310        next->parent = node;
     311        next->value = NGX_RADIX_NO_VALUE;
     312
     313        if (key & bit) {
     314            node->right = next;
     315
     316        } else {
     317            node->left = next;
     318        }
     319
     320        bit >>= 1;
     321        node = next;
     322    }
     323
     324    node->value = value;
     325
     326    return NGX_OK;
     327}
     328
     329
     330ngx_int_t
     331ngx_radix64tree_delete(ngx_radix_tree_t *tree, uint64_t key, uint64_t mask)
     332{
     333    uint64_t           bit;
     334    ngx_radix_node_t  *node;
     335
     336    bit = 0x8000000000000000;
     337    node = tree->root;
     338
     339    while (node && (bit & mask)) {
     340        if (key & bit) {
     341            node = node->right;
     342
     343        } else {
     344            node = node->left;
     345        }
     346
     347        bit >>= 1;
     348    }
     349
     350    if (node == NULL) {
     351        return NGX_ERROR;
     352    }
     353
     354    if (node->right || node->left) {
     355        if (node->value != NGX_RADIX_NO_VALUE) {
     356            node->value = NGX_RADIX_NO_VALUE;
     357            return NGX_OK;
     358        }
     359
     360        return NGX_ERROR;
     361    }
     362
     363    for ( ;; ) {
     364        if (node->parent->right == node) {
     365            node->parent->right = NULL;
     366
     367        } else {
     368            node->parent->left = NULL;
     369        }
     370
     371        node->right = tree->free;
     372        tree->free = node;
     373
     374        node = node->parent;
     375
     376        if (node->right || node->left) {
     377            break;
     378        }
     379
     380        if (node->value != NGX_RADIX_NO_VALUE) {
     381            break;
     382        }
     383
     384        if (node->parent == NULL) {
     385            break;
     386        }
     387    }
     388
     389    return NGX_OK;
     390}
     391
     392
     393uintptr_t
     394ngx_radix64tree_find(ngx_radix_tree_t *tree, uint64_t key)
     395{
     396    uint64_t           bit;
     397    uintptr_t          value;
     398    ngx_radix_node_t  *node;
     399
     400    bit = 0x8000000000000000;
     401    value = NGX_RADIX_NO_VALUE;
     402    node = tree->root;
     403
     404    while (node) {
     405        if (node->value != NGX_RADIX_NO_VALUE) {
     406            value = node->value;
     407        }
     408
     409        if (key & bit) {
     410            node = node->right;
     411
     412        } else {
     413            node = node->left;
     414        }
     415
     416        bit >>= 1;
     417    }
     418
     419    return value;
     420}
     421
    265422
    266423#if (NGX_HAVE_INET6)
    267424
  • nginx-1.12.0/src/core/ngx_radix_tree.h

    diff --git a/nginx-1.12.0/src/core/ngx_radix_tree.h b/nginx-1.12.0/src/core/ngx_radix_tree.h
    old mode 100644
    new mode 100755
    index 4fe06e0..d34ac34
    a b ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,  
    4343    uint32_t key, uint32_t mask);
    4444uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key);
    4545
     46ngx_int_t ngx_radix64tree_insert(ngx_radix_tree_t *tree,
     47    uint64_t key, uint64_t mask, uintptr_t value);
     48ngx_int_t ngx_radix64tree_delete(ngx_radix_tree_t *tree,
     49    uint64_t key, uint64_t mask);
     50uintptr_t ngx_radix64tree_find(ngx_radix_tree_t *tree, uint64_t key);
     51
    4652#if (NGX_HAVE_INET6)
    4753ngx_int_t ngx_radix128tree_insert(ngx_radix_tree_t *tree,
    4854    u_char *key, u_char *mask, uintptr_t value);
    … … ngx_int_t ngx_radix128tree_delete(ngx_radix_tree_t *tree,  
    5157uintptr_t ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key);
    5258#endif
    5359
     60static ngx_inline uint64_t
     61sock2key(struct sockaddr_in *sin)
     62{
     63    return ((uint64_t)sin->sin_addr.s_addr << 32) + sin->sin_port;
     64}
    5465
    5566#endif /* _NGX_RADIX_TREE_H_INCLUDED_ */
  • nginx-1.12.0/src/event/ngx_event_accept.c

    diff --git a/nginx-1.12.0/src/event/ngx_event_accept.c b/nginx-1.12.0/src/event/ngx_event_accept.c
    old mode 100644
    new mode 100755
    index 406066f..5b922e3
    a b static void ngx_debug_accepted_connection(ngx_event_conf_t *ecf,  
    2121    ngx_connection_t *c);
    2222#endif
    2323
     24void ngx_stream_session_udp_handler(ngx_event_t *rev);
     25
    2426
    2527void
    2628ngx_event_accept(ngx_event_t *ev)
    … … ngx_event_recvmsg(ngx_event_t *ev)  
    341343    ngx_event_conf_t  *ecf;
    342344    ngx_connection_t  *c, *lc;
    343345    static u_char      buffer[65535];
     346#if (NGX_DEBUG)
     347    ngx_str_t          client_addr;
     348    u_char             client_text[NGX_SOCKADDR_STRLEN];
     349#endif
     350    uint64_t           client_key;
     351    uintptr_t          v;
    344352
    345353#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
    346354
    … … ngx_event_recvmsg(ngx_event_t *ev)  
    440448        ngx_accept_disabled = ngx_cycle->connection_n / 8
    441449                              - ngx_cycle->free_connection_n;
    442450
     451#if (NGX_DEBUG)
     452        client_addr.data = client_text;
     453        client_addr.len = ngx_sock_ntop((struct sockaddr *)msg.msg_name,
     454                msg.msg_namelen, client_text, NGX_SOCKADDR_STRLEN, 1);
     455#endif
     456
     457        client_key = sock2key(&sa.sockaddr_in);
     458        v = ngx_radix64tree_find(ls->dgram_conns, client_key);
     459        if (v != NGX_RADIX_NO_VALUE) {
     460#if (NGX_DEBUG)
     461            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
     462                "reuse incoming conenction on %V from %V(%08X)", &ls->addr_text, &client_addr, client_key);
     463#endif
     464            c = (ngx_connection_t *)v;
     465            c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
     466            c->log->connection = c->number;
     467            c->buffer = ngx_recreate_temp_buf(c->buffer, c->pool, n);
     468            if (c->buffer == NULL) {
     469                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
     470                    "failed to recreate buf for incoming conenction on %V", &ls->addr_text);
     471                ngx_close_accepted_connection(c);
     472                return;
     473            }
     474
     475            c->buffer->last = ngx_cpymem(c->buffer->last, buffer, n);
     476            ngx_stream_session_udp_handler(c->read);
     477            continue;
     478        }
     479
     480#if (NGX_DEBUG)
     481        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
     482            "setup incoming conenction on %V from %V(%08X)", &ls->addr_text, &client_addr, client_key);
     483#endif
    443484        c = ngx_get_connection(lc->fd, ev->log);
    444485        if (c == NULL) {
    445486#ifdef NGX_HTTP_STATUS
    … … ngx_event_recvmsg(ngx_event_t *ev)  
    641682            ev->available -= n;
    642683        }
    643684
     685        client_key = sock2key(&sa.sockaddr_in);
     686        ngx_radix64tree_insert(ls->dgram_conns, client_key, client_key, (uintptr_t)c);
    644687    } while (ev->available);
    645688}
    646689
  • nginx-1.12.0/src/stream/ngx_stream.c

    diff --git a/nginx-1.12.0/src/stream/ngx_stream.c b/nginx-1.12.0/src/stream/ngx_stream.c
    old mode 100644
    new mode 100755
    index 4a394d7..7f7b457
    a b ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)  
    521521
    522522            stport->naddrs = i + 1;
    523523
     524            if (ls->type == SOCK_DGRAM) {
     525                ls->dgram_conns = ngx_radix_tree_create(cf->pool, -1);
     526                if (ls->dgram_conns == NULL) {
     527                    return NGX_CONF_ERROR;
     528                }
     529            } else {
     530                ls->dgram_conns = NULL;
     531            }
     532
    524533            switch (ls->sockaddr->sa_family) {
    525534#if (NGX_HAVE_INET6)
    526535            case AF_INET6:
  • nginx-1.12.0/src/stream/ngx_stream.h

    diff --git a/nginx-1.12.0/src/stream/ngx_stream.h b/nginx-1.12.0/src/stream/ngx_stream.h
    old mode 100644
    new mode 100755
    index d478cc1..438e387
    a b ngx_int_t ngx_stream_core_content_phase(ngx_stream_session_t *s,  
    293293
    294294void ngx_stream_init_connection(ngx_connection_t *c);
    295295void ngx_stream_session_handler(ngx_event_t *rev);
     296void ngx_stream_session_udp_handler(ngx_event_t *rev);
    296297void ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc);
    297298
    298299
  • nginx-1.12.0/src/stream/ngx_stream_handler.c

    diff --git a/nginx-1.12.0/src/stream/ngx_stream_handler.c b/nginx-1.12.0/src/stream/ngx_stream_handler.c
    old mode 100644
    new mode 100755
    index 437f6ea..92b3f7a
    a b ngx_stream_session_handler(ngx_event_t *rev)  
    336336    ngx_stream_core_run_phases(s);
    337337}
    338338
     339void
     340ngx_stream_session_udp_handler(ngx_event_t *rev)
     341{
     342    ngx_connection_t      *c;
     343    ngx_stream_session_t  *s;
     344
     345    c = rev->data;
     346    s = c->data;
     347
     348    ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
     349                   "stream session udp handler");
     350
     351    c->log->action = "reuse session";
     352
     353    s->received += c->buffer->last - c->buffer->pos;
     354
     355    ngx_stream_core_run_phases(s);
     356}
     357
    339358
    340359void
    341360ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc)
  • nginx-1.12.0/src/stream/ngx_stream_proxy_module.c

    diff --git a/nginx-1.12.0/src/stream/ngx_stream_proxy_module.c b/nginx-1.12.0/src/stream/ngx_stream_proxy_module.c
    old mode 100644
    new mode 100755
    index c19dd7e..3d53b64
    a b ngx_stream_proxy_handler(ngx_stream_session_t *s)  
    368368
    369369    c = s->connection;
    370370
     371    if (c->type == SOCK_DGRAM && s->upstream) {
     372        ngx_stream_proxy_connect(s);
     373        return;
     374    }
     375
    371376    pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
    372377
    373378    ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
    … … ngx_stream_proxy_connect(ngx_stream_session_t *s)  
    709714
    710715    c = s->connection;
    711716
    712     c->log->action = "connecting to upstream";
    713 
    714717    pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
    715718
    716719    u = s->upstream;
    717720
     721    if (c->type == SOCK_DGRAM && u->peer.connection) {
     722        ngx_chain_t              *cl;
     723
     724        pc = u->peer.connection;
     725       
     726        ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "reuse proxy connect: %p", pc);
     727
     728        if (c->buffer && c->buffer->pos < c->buffer->last) {
     729            ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
     730                           "stream proxy add buffer: %uz",
     731                           c->buffer->last - c->buffer->pos);
     732
     733            cl = ngx_chain_get_free_buf(c->pool, &u->free);
     734            if (cl == NULL) {
     735#ifdef NGX_HTTP_STATUS
     736                ngx_http_status_update(cscf->status_index, STATUS_TYPE_PROXY_ERROR, 1);
     737#endif
     738                ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
     739                return;
     740            }
     741
     742            *cl->buf = *c->buffer;
     743
     744            cl->buf->tag = (ngx_buf_tag_t) &ngx_stream_proxy_module;
     745            cl->buf->flush = 1;
     746            cl->buf->last_buf = 1;
     747
     748            cl->next = u->upstream_out;
     749            u->upstream_out = cl;
     750        }
     751
     752        if (pscf->responses == 0) {
     753            pc->read->ready = 0;
     754            pc->read->eof = 1;
     755        }
     756
     757        ngx_stream_proxy_process(s, 0, 1);
     758   
     759        return;
     760    }
     761
     762    c->log->action = "connecting to upstream";
     763
    718764    u->connected = 0;
    719765    u->proxy_protocol = pscf->proxy_protocol;
    720766