00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifdef USE_TCP
00039
00040 #include <stdio.h>
00041 #include <errno.h>
00042 #include <string.h>
00043
00044
00045 #include <sys/time.h>
00046 #include <sys/types.h>
00047 #include <sys/select.h>
00048 #include <sys/socket.h>
00049
00050 #include <unistd.h>
00051 #include <stdlib.h>
00052
00053
00054 #include "dprint.h"
00055 #include "tcp_conn.h"
00056 #include "pass_fd.h"
00057 #include "globals.h"
00058 #include "receive.h"
00059 #include "timer.h"
00060 #include "ut.h"
00061 #ifdef USE_TLS
00062 #include "tls/tls_server.h"
00063 #endif
00064
00065 #define HANDLE_IO_INLINE
00066 #include "io_wait.h"
00067 #include <fcntl.h>
00068 #include "forward.h"
00069
00070 enum fd_types { F_NONE, F_TCPMAIN, F_TCPCONN };
00071
00072 static struct tcp_connection* tcp_conn_lst=0;
00073 static io_wait_h io_w;
00074 static int tcpmain_sock=-1;
00075
00076
00077
00078
00079
00080
00081
00082
00083 int tcp_read(struct tcp_connection *c)
00084 {
00085 int bytes_free, bytes_read;
00086 struct tcp_req *r;
00087 int fd;
00088
00089 r=&c->req;
00090 fd=c->fd;
00091 bytes_free=TCP_BUF_SIZE- (int)(r->pos - r->buf);
00092
00093 if (bytes_free==0){
00094 LM_ERR("buffer overrun, dropping\n");
00095 r->error=TCP_REQ_OVERRUN;
00096 return -1;
00097 }
00098 again:
00099 bytes_read=read(fd, r->pos, bytes_free);
00100
00101 if(bytes_read==-1){
00102 if (errno == EWOULDBLOCK || errno == EAGAIN){
00103 return 0;
00104 }else if (errno == EINTR) goto again;
00105 else{
00106 LM_ERR("error reading: %s\n",strerror(errno));
00107 r->error=TCP_READ_ERROR;
00108 return -1;
00109 }
00110 }else if (bytes_read==0){
00111 c->state=S_CONN_EOF;
00112 LM_DBG("EOF on %p, FD %d\n", c, fd);
00113 }
00114 #ifdef EXTRA_DEBUG
00115 LM_DBG("read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
00116 #endif
00117 r->pos+=bytes_read;
00118 return bytes_read;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 int tcp_read_headers(struct tcp_connection *c)
00136 {
00137 unsigned int remaining;
00138 int bytes;
00139 char *p;
00140 struct tcp_req* r;
00141
00142 #define crlf_default_skip_case \
00143 case '\n': \
00144 r->state=H_LF; \
00145 break; \
00146 default: \
00147 r->state=H_SKIP
00148
00149 #define content_len_beg_case \
00150 case ' ': \
00151 case '\t': \
00152 if (!r->has_content_len) r->state=H_STARTWS; \
00153 else r->state=H_SKIP; \
00154 \
00155 break; \
00156 case 'C': \
00157 case 'c': \
00158 if(!r->has_content_len) r->state=H_CONT_LEN1; \
00159 else r->state=H_SKIP; \
00160 break; \
00161 case 'l': \
00162 case 'L': \
00163 \
00164 if (!r->has_content_len) r->state=H_L_COLON; \
00165 else r->state=H_SKIP; \
00166 break
00167
00168 #define change_state(upper, lower, newstate)\
00169 switch(*p){ \
00170 case upper: \
00171 case lower: \
00172 r->state=(newstate); break; \
00173 crlf_default_skip_case; \
00174 }
00175
00176 #define change_state_case(state0, upper, lower, newstate)\
00177 case state0: \
00178 change_state(upper, lower, newstate); \
00179 p++; \
00180 break
00181
00182
00183 r=&c->req;
00184
00185 if (r->parsed<r->pos){
00186 bytes=0;
00187 }else{
00188 #ifdef USE_TLS
00189 if (c->type==PROTO_TLS)
00190 bytes=tls_read(c);
00191 else
00192 #endif
00193 bytes=tcp_read(c);
00194 if (bytes<=0) return bytes;
00195 }
00196 p=r->parsed;
00197
00198 while(p<r->pos && r->error==TCP_REQ_OK){
00199 switch((unsigned char)r->state){
00200 case H_BODY:
00201 remaining=r->pos-p;
00202 if (remaining>r->bytes_to_go) remaining=r->bytes_to_go;
00203 r->bytes_to_go-=remaining;
00204 p+=remaining;
00205 if (r->bytes_to_go==0){
00206 r->complete=1;
00207 goto skip;
00208 }
00209 break;
00210
00211 case H_SKIP:
00212
00213
00214 p=memchr(p, '\n', r->pos-p);
00215 if (p){
00216 p++;
00217 r->state=H_LF;
00218 }else{
00219 p=r->pos;
00220 }
00221 break;
00222
00223 case H_LF:
00224
00225 switch (*p){
00226 case '\r':
00227 r->state=H_LFCR;
00228 break;
00229 case '\n':
00230
00231 r->state=H_BODY;
00232 if (r->has_content_len){
00233 r->body=p+1;
00234 r->bytes_to_go=r->content_len;
00235 if (r->bytes_to_go==0){
00236 r->complete=1;
00237 p++;
00238 goto skip;
00239 }
00240 }else{
00241 LM_DBG("no clen, p=%X\n", *p);
00242 r->error=TCP_REQ_BAD_LEN;
00243 }
00244 break;
00245 content_len_beg_case;
00246 default:
00247 r->state=H_SKIP;
00248 }
00249 p++;
00250 break;
00251 case H_LFCR:
00252 if (*p=='\n'){
00253
00254 r->state=H_BODY;
00255 if (r->has_content_len){
00256 r->body=p+1;
00257 r->bytes_to_go=r->content_len;
00258 if (r->bytes_to_go==0){
00259 r->complete=1;
00260 p++;
00261 goto skip;
00262 }
00263 }else{
00264 LM_DBG("no clen, p=%X\n", *p);
00265 r->error=TCP_REQ_BAD_LEN;
00266 }
00267 }else r->state=H_SKIP;
00268 p++;
00269 break;
00270
00271 case H_STARTWS:
00272 switch (*p){
00273 content_len_beg_case;
00274 crlf_default_skip_case;
00275 }
00276 p++;
00277 break;
00278 case H_SKIP_EMPTY:
00279 switch (*p){
00280 case '\n':
00281 break;
00282 case '\r':
00283 if (tcp_crlf_pingpong) {
00284 r->state=H_SKIP_EMPTY_CR_FOUND;
00285 r->start=p;
00286 }
00287 break;
00288 case ' ':
00289 case '\t':
00290
00291 break;
00292 case 'C':
00293 case 'c':
00294 r->state=H_CONT_LEN1;
00295 r->start=p;
00296 break;
00297 case 'l':
00298 case 'L':
00299
00300 r->state=H_L_COLON;
00301 r->start=p;
00302 break;
00303 default:
00304 r->state=H_SKIP;
00305 r->start=p;
00306 };
00307 p++;
00308 break;
00309 case H_SKIP_EMPTY_CR_FOUND:
00310 if (*p=='\n'){
00311 r->state=H_SKIP_EMPTY_CRLF_FOUND;
00312 p++;
00313 }else{
00314 r->state=H_SKIP_EMPTY;
00315 }
00316 break;
00317
00318 case H_SKIP_EMPTY_CRLF_FOUND:
00319 if (*p=='\r'){
00320 r->state = H_SKIP_EMPTY_CRLFCR_FOUND;
00321 p++;
00322 }else{
00323 r->state = H_SKIP_EMPTY;
00324 }
00325 break;
00326
00327 case H_SKIP_EMPTY_CRLFCR_FOUND:
00328 if (*p=='\n'){
00329 r->state = H_PING_CRLFCRLF;
00330 r->complete = 1;
00331 r->has_content_len = 1;
00332 p++;
00333 goto skip;
00334 }else{
00335 r->state = H_SKIP_EMPTY;
00336 }
00337 break;
00338 change_state_case(H_CONT_LEN1, 'O', 'o', H_CONT_LEN2);
00339 change_state_case(H_CONT_LEN2, 'N', 'n', H_CONT_LEN3);
00340 change_state_case(H_CONT_LEN3, 'T', 't', H_CONT_LEN4);
00341 change_state_case(H_CONT_LEN4, 'E', 'e', H_CONT_LEN5);
00342 change_state_case(H_CONT_LEN5, 'N', 'n', H_CONT_LEN6);
00343 change_state_case(H_CONT_LEN6, 'T', 't', H_CONT_LEN7);
00344 change_state_case(H_CONT_LEN7, '-', '_', H_CONT_LEN8);
00345 change_state_case(H_CONT_LEN8, 'L', 'l', H_CONT_LEN9);
00346 change_state_case(H_CONT_LEN9, 'E', 'e', H_CONT_LEN10);
00347 change_state_case(H_CONT_LEN10, 'N', 'n', H_CONT_LEN11);
00348 change_state_case(H_CONT_LEN11, 'G', 'g', H_CONT_LEN12);
00349 change_state_case(H_CONT_LEN12, 'T', 't', H_CONT_LEN13);
00350 change_state_case(H_CONT_LEN13, 'H', 'h', H_L_COLON);
00351
00352 case H_L_COLON:
00353 switch(*p){
00354 case ' ':
00355 case '\t':
00356 break;
00357 case ':':
00358 r->state=H_CONT_LEN_BODY;
00359 break;
00360 crlf_default_skip_case;
00361 };
00362 p++;
00363 break;
00364
00365 case H_CONT_LEN_BODY:
00366 switch(*p){
00367 case ' ':
00368 case '\t':
00369 break;
00370 case '0':
00371 case '1':
00372 case '2':
00373 case '3':
00374 case '4':
00375 case '5':
00376 case '6':
00377 case '7':
00378 case '8':
00379 case '9':
00380 r->state=H_CONT_LEN_BODY_PARSE;
00381 r->content_len=(*p-'0');
00382 break;
00383
00384 crlf_default_skip_case;
00385 }
00386 p++;
00387 break;
00388
00389 case H_CONT_LEN_BODY_PARSE:
00390 switch(*p){
00391 case '0':
00392 case '1':
00393 case '2':
00394 case '3':
00395 case '4':
00396 case '5':
00397 case '6':
00398 case '7':
00399 case '8':
00400 case '9':
00401 r->content_len=r->content_len*10+(*p-'0');
00402 break;
00403 case '\r':
00404 case ' ':
00405 case '\t':
00406 r->state=H_SKIP;
00407 r->has_content_len=1;
00408 break;
00409 case '\n':
00410
00411 r->state=H_LF;
00412 r->has_content_len=1;
00413 break;
00414 default:
00415 LM_ERR("bad Content-Length header value, unexpected "
00416 "char %c in state %d\n", *p, r->state);
00417 r->state=H_SKIP;
00418 }
00419 p++;
00420 break;
00421
00422 default:
00423 LM_CRIT("unexpected state %d\n", r->state);
00424 abort();
00425 }
00426 }
00427 skip:
00428 r->parsed=p;
00429 return bytes;
00430 }
00431
00432
00433
00434 int tcp_read_req(struct tcp_connection* con, int* bytes_read)
00435 {
00436 int bytes;
00437 int total_bytes;
00438 int resp;
00439 long size;
00440 struct tcp_req* req;
00441 int s;
00442 char c;
00443
00444 bytes=-1;
00445 total_bytes=0;
00446 resp=CONN_RELEASE;
00447 s=con->fd;
00448 req=&con->req;
00449 #ifdef USE_TLS
00450 if (con->type==PROTO_TLS){
00451 if (tls_fix_read_conn(con)!=0){
00452 resp=CONN_ERROR;
00453 goto end_req;
00454 }
00455 if(con->state!=S_CONN_OK) goto end_req;
00456 }
00457 #endif
00458
00459 again:
00460 if(req->error==TCP_REQ_OK){
00461 bytes=tcp_read_headers(con);
00462 #ifdef EXTRA_DEBUG
00463
00464 LM_DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n",
00465 bytes, (int)(req->parsed-req->start), req->state,
00466 req->error );
00467 LM_DBG("last char=0x%02X, parsed msg=\n%.*s\n",
00468 *(req->parsed-1), (int)(req->parsed-req->start),
00469 req->start);
00470 #endif
00471 if (bytes==-1){
00472 LM_ERR("failed to read \n");
00473 resp=CONN_ERROR;
00474 goto end_req;
00475 }
00476 total_bytes+=bytes;
00477
00478
00479
00480
00481
00482 if ((con->state==S_CONN_EOF) && (req->complete==0)) {
00483 LM_DBG("EOF\n");
00484 resp=CONN_EOF;
00485 goto end_req;
00486 }
00487
00488 }
00489 if (req->error!=TCP_REQ_OK){
00490 LM_ERR("bad request, state=%d, error=%d "
00491 "buf:\n%.*s\nparsed:\n%.*s\n", req->state, req->error,
00492 (int)(req->pos-req->buf), req->buf,
00493 (int)(req->parsed-req->start), req->start);
00494 LM_DBG("- received from: port %d\n", con->rcv.src_port);
00495 print_ip("- received from: ip ",&con->rcv.src_ip, "\n");
00496 resp=CONN_ERROR;
00497 goto end_req;
00498 }
00499 if (req->complete){
00500 #ifdef EXTRA_DEBUG
00501 LM_DBG("end of header part\n");
00502 LM_DBG("- received from: port %d\n", con->rcv.src_port);
00503 print_ip("- received from: ip ", &con->rcv.src_ip, "\n");
00504 LM_DBG("headers:\n%.*s.\n",(int)(req->body-req->start), req->start);
00505 #endif
00506 if (req->has_content_len){
00507 LM_DBG("content-length= %d\n", req->content_len);
00508 #ifdef EXTRA_DEBUG
00509 LM_DBG("body:\n%.*s\n", req->content_len,req->body);
00510 #endif
00511 }else{
00512 req->error=TCP_REQ_BAD_LEN;
00513 LM_ERR("content length not present or unparsable\n");
00514 resp=CONN_ERROR;
00515 goto end_req;
00516 }
00517
00518 resp=CONN_RELEASE;
00519 #ifdef EXTRA_DEBUG
00520 LM_DBG("calling receive_msg(%p, %d, )\n",
00521 req->start, (int)(req->parsed-req->start));
00522 #endif
00523
00524 bind_address=con->rcv.bind_address;
00525
00526
00527
00528
00529
00530
00531
00532
00533 con->rcv.proto_reserved1=con->id;
00534 c=*req->parsed;
00535
00536
00537 *req->parsed=0;
00538
00539 if (req->state==H_PING_CRLFCRLF) {
00540 if (tcp_send( con->rcv.bind_address, con->rcv.proto,CRLF,
00541 CRLF_LEN, &(con->rcv.src_su), con->rcv.proto_reserved1) < 0) {
00542 LM_ERR("CRLF pong - tcp_send() failed\n");
00543 }
00544 } else if (receive_msg(req->start, req->parsed-req->start,
00545 &con->rcv)<0) {
00546 *req->parsed=c;
00547 resp=CONN_ERROR;
00548 goto end_req;
00549 }
00550 *req->parsed=c;
00551
00552
00553 size=req->pos-req->parsed;
00554 if (size) memmove(req->buf, req->parsed, size);
00555 #ifdef EXTRA_DEBUG
00556 LM_DBG("preparing for new request, kept %ld bytes\n", size);
00557 #endif
00558 req->pos=req->buf+size;
00559 req->parsed=req->buf;
00560 req->start=req->buf;
00561 req->body=0;
00562 req->error=TCP_REQ_OK;
00563 req->state=H_SKIP_EMPTY;
00564 req->complete=req->content_len=req->has_content_len=0;
00565 req->bytes_to_go=0;
00566
00567 if (size) goto again;
00568 else if (con->state==S_CONN_EOF){
00569 LM_DBG("EOF after reading complete request\n");
00570 resp=CONN_EOF;
00571 }
00572
00573 }
00574
00575
00576 end_req:
00577 if (bytes_read) *bytes_read=total_bytes;
00578 return resp;
00579 }
00580
00581
00582
00583 void release_tcpconn(struct tcp_connection* c, long state, int unix_sock)
00584 {
00585 long response[2];
00586
00587 LM_DBG(" releasing con %p, state %ld, fd=%d, id=%d\n",
00588 c, state, c->fd, c->id);
00589 LM_DBG(" extra_data %p\n", c->extra_data);
00590
00591 if (c->fd!=-1) close(c->fd);
00592
00593 response[0]=(long)c;
00594 response[1]=state;
00595 if (send_all(unix_sock, response, sizeof(response))<=0)
00596 LM_ERR("send_all failed\n");
00597 }
00598
00599
00600 #ifdef DEBUG_TCP_RECEIVE
00601
00602 void tcp_receive_loop(int unix_sock)
00603 {
00604 struct tcp_connection* list;
00605 struct tcp_connection* con;
00606 struct tcp_connection* c_next;
00607 int n;
00608 int nfds;
00609 int s;
00610 long resp;
00611 fd_set master_set;
00612 fd_set sel_set;
00613 int maxfd;
00614 struct timeval timeout;
00615 int ticks;
00616
00617
00618
00619 list=con=0;
00620 FD_ZERO(&master_set);
00621 FD_SET(unix_sock, &master_set);
00622 maxfd=unix_sock;
00623
00624
00625 for(;;){
00626 timeout.tv_sec=TCP_CHILD_SELECT_TIMEOUT;
00627 timeout.tv_usec=0;
00628 sel_set=master_set;
00629 nfds=select(maxfd+1, &sel_set, 0 , 0 , &timeout);
00630 #ifdef EXTRA_DEBUG
00631 for (n=0; n<maxfd; n++){
00632 if (FD_ISSET(n, &sel_set))
00633 LM_DBG("fd %d is set\n", n);
00634 }
00635 #endif
00636 if (nfds<0){
00637 if (errno==EINTR) continue;
00638
00639 LM_ERR("select:(%d) %s\n", errno,
00640 strerror(errno));
00641 continue;
00642 }
00643 if (FD_ISSET(unix_sock, &sel_set)){
00644 nfds--;
00645
00646 n=receive_fd(unix_sock, &con, sizeof(con), &s, 0);
00647 if (n<0){
00648 if (errno == EWOULDBLOCK || errno == EAGAIN ||
00649 errno == EINTR){
00650 goto skip;
00651 }else{
00652 LM_CRIT("read_fd: %s\n",strerror(errno));
00653 abort();
00654 }
00655 }
00656 LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s);
00657 if (n==0){
00658 LM_WARN("0 bytes read\n");
00659 goto skip;
00660 }
00661 if (con==0){
00662 LM_CRIT("null pointer\n");
00663 goto skip;
00664 }
00665 con->fd=s;
00666 if (s==-1) {
00667 LM_ERR("read_fd: no fd read\n");
00668 resp=CONN_ERROR;
00669 con->state=S_CONN_BAD;
00670 release_tcpconn(con, resp, unix_sock);
00671 goto skip;
00672 }
00673 con->timeout=get_ticks()+TCP_CHILD_TIMEOUT;
00674 FD_SET(s, &master_set);
00675 if (maxfd<s) maxfd=s;
00676 if (con==list){
00677 LM_CRIT("duplicate"
00678 " connection received: %p, id %d, fd %d, refcnt %d"
00679 " state %d (n=%d)\n", con, con->id, con->fd,
00680 con->refcnt, con->state, n);
00681 resp=CONN_ERROR;
00682 release_tcpconn(con, resp, unix_sock);
00683 goto skip;
00684 }
00685 tcpconn_listadd(list, con, c_next, c_prev);
00686 }
00687 skip:
00688 ticks=get_ticks();
00689 for (con=list; con ; con=c_next){
00690 c_next=con->c_next;
00691 #ifdef EXTRA_DEBUG
00692 LM_DBG("list fd=%d, id=%d, timeout=%d, refcnt=%d\n",
00693 con->fd, con->id, con->timeout, con->refcnt);
00694 #endif
00695 if (con->state<0){
00696
00697 resp=CONN_ERROR;
00698 FD_CLR(con->fd, &master_set);
00699 tcpconn_listrm(list, con, c_next, c_prev);
00700 con->state=S_CONN_BAD;
00701 release_tcpconn(con, resp, unix_sock);
00702 continue;
00703 }
00704 if (nfds && FD_ISSET(con->fd, &sel_set)){
00705 #ifdef EXTRA_DEBUG
00706 LM_DBG("match, fd:isset\n");
00707 #endif
00708 nfds--;
00709 resp=tcp_read_req(con);
00710
00711 if (resp<0){
00712 FD_CLR(con->fd, &master_set);
00713 tcpconn_listrm(list, con, c_next, c_prev);
00714 con->state=S_CONN_BAD;
00715 release_tcpconn(con, resp, unix_sock);
00716 }else{
00717
00718 con->timeout=ticks+TCP_CHILD_TIMEOUT;
00719 }
00720 }else{
00721
00722 if (con->timeout<=ticks){
00723
00724 LM_DBG("%p expired (%d, %d)\n",
00725 con, con->timeout, ticks);
00726 resp=CONN_RELEASE;
00727 FD_CLR(con->fd, &master_set);
00728 tcpconn_listrm(list, con, c_next, c_prev);
00729 release_tcpconn(con, resp, unix_sock);
00730 }
00731 }
00732 }
00733
00734 }
00735 }
00736 #else
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 inline static int handle_io(struct fd_map* fm, int idx)
00755 {
00756 int ret;
00757 int n;
00758 struct tcp_connection* con;
00759 int s;
00760 long resp;
00761
00762 switch(fm->type){
00763 case F_TCPMAIN:
00764 again:
00765 ret=n=receive_fd(fm->fd, &con, sizeof(con), &s, 0);
00766 LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s);
00767 if (n<0){
00768 if (errno == EWOULDBLOCK || errno == EAGAIN){
00769 ret=0;
00770 break;
00771 }else if (errno == EINTR) goto again;
00772 else{
00773 LM_CRIT("read_fd: %s \n", strerror(errno));
00774 abort();
00775 }
00776 }
00777 if (n==0){
00778 LM_WARN("0 bytes read\n");
00779 break;
00780 }
00781 if (con==0){
00782 LM_CRIT("null pointer\n");
00783 break;
00784 }
00785 con->fd=s;
00786 if (s==-1) {
00787 LM_ERR("read_fd:no fd read\n");
00788 goto con_error;
00789 }
00790 if (con==tcp_conn_lst){
00791 LM_CRIT("duplicate"
00792 " connection received: %p, id %d, fd %d, refcnt %d"
00793 " state %d (n=%d)\n", con, con->id, con->fd,
00794 con->refcnt, con->state, n);
00795 release_tcpconn(con, CONN_ERROR, tcpmain_sock);
00796 break;
00797 }
00798
00799
00800
00801
00802 tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev);
00803 con->timeout=get_ticks()+TCP_CHILD_TIMEOUT;
00804 if (io_watch_add(&io_w, s, F_TCPCONN, con)<0){
00805 LM_CRIT("failed to add new socket to the fd list\n");
00806 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
00807 goto con_error;
00808 }
00809 break;
00810 case F_TCPCONN:
00811 con=(struct tcp_connection*)fm->data;
00812 resp=tcp_read_req(con, &ret);
00813 if (resp<0){
00814 ret=-1;
00815 io_watch_del(&io_w, con->fd, idx, IO_FD_CLOSING);
00816 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
00817 con->state=S_CONN_BAD;
00818 release_tcpconn(con, resp, tcpmain_sock);
00819 }else{
00820
00821 con->timeout=get_ticks()+TCP_CHILD_TIMEOUT;
00822 }
00823 break;
00824 case F_NONE:
00825 LM_CRIT("empty fd map %p (%d): "
00826 "{%d, %d, %p}\n", fm, (int)(fm-io_w.fd_hash),
00827 fm->fd, fm->type, fm->data);
00828 goto error;
00829 default:
00830 LM_CRIT("uknown fd type %d\n", fm->type);
00831 goto error;
00832 }
00833
00834 return ret;
00835 con_error:
00836 con->state=S_CONN_BAD;
00837 release_tcpconn(con, CONN_ERROR, fm->fd);
00838 return ret;
00839 error:
00840 return -1;
00841 }
00842
00843
00844
00845 static unsigned int c_tcp_con_lifetime = 0;
00846 static int c_tcp_con_id = -1;
00847
00848
00849 void force_tcp_conn_lifetime(struct receive_info *rcv, unsigned int timeout)
00850 {
00851 c_tcp_con_lifetime = get_ticks() + timeout;
00852 c_tcp_con_id = rcv->proto_reserved1;
00853 }
00854
00855
00856
00857
00858 static inline void tcp_receive_timeout(void)
00859 {
00860 struct tcp_connection* con;
00861 struct tcp_connection* next;
00862 unsigned int ticks;
00863
00864 ticks=get_ticks();
00865 for (con=tcp_conn_lst; con; con=next){
00866 next=con->c_next;
00867 if (con->state<0){
00868
00869
00870 io_watch_del(&io_w, con->fd, -1, IO_FD_CLOSING);
00871 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
00872 con->state=S_CONN_BAD;
00873 release_tcpconn(con, CONN_ERROR, tcpmain_sock);
00874 continue;
00875 }
00876 if (con->timeout<=ticks){
00877
00878 if (c_tcp_con_id==con->id) {
00879 con->lifetime = c_tcp_con_lifetime;
00880 }
00881 LM_DBG("%p expired (%d, %d) lt=%d\n",
00882 con, con->timeout, ticks,con->lifetime);
00883
00884 io_watch_del(&io_w, con->fd, -1, IO_FD_CLOSING);
00885 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
00886 release_tcpconn(con, CONN_RELEASE, tcpmain_sock);
00887 }
00888 }
00889 }
00890
00891
00892
00893 void tcp_receive_loop(int unix_sock)
00894 {
00895
00896
00897 tcpmain_sock=unix_sock;
00898 if (init_io_wait(&io_w, tcp_max_fd_no, tcp_poll_method)<0)
00899 goto error;
00900
00901 if (io_watch_add(&io_w, tcpmain_sock, F_TCPMAIN, 0)<0){
00902 LM_CRIT("failed to add socket to the fd list\n");
00903 goto error;
00904 }
00905
00906 switch(io_w.poll_method){
00907 case POLL_POLL:
00908 while(1){
00909 io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
00910 tcp_receive_timeout();
00911 }
00912 break;
00913 #ifdef HAVE_SELECT
00914 case POLL_SELECT:
00915 while(1){
00916 io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
00917 tcp_receive_timeout();
00918 }
00919 break;
00920 #endif
00921 #ifdef HAVE_SIGIO_RT
00922 case POLL_SIGIO_RT:
00923 while(1){
00924 io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT);
00925 tcp_receive_timeout();
00926 }
00927 break;
00928 #endif
00929 #ifdef HAVE_EPOLL
00930 case POLL_EPOLL_LT:
00931 while(1){
00932 io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
00933 tcp_receive_timeout();
00934 }
00935 break;
00936 case POLL_EPOLL_ET:
00937 while(1){
00938 io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1);
00939 tcp_receive_timeout();
00940 }
00941 break;
00942 #endif
00943 #ifdef HAVE_KQUEUE
00944 case POLL_KQUEUE:
00945 while(1){
00946 io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
00947 tcp_receive_timeout();
00948 }
00949 break;
00950 #endif
00951 #ifdef HAVE_DEVPOLL
00952 case POLL_DEVPOLL:
00953 while(1){
00954 io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
00955 tcp_receive_timeout();
00956 }
00957 break;
00958 #endif
00959 default:
00960 LM_CRIT("no support for poll method %s (%d)\n",
00961 poll_method_name(io_w.poll_method), io_w.poll_method);
00962 goto error;
00963 }
00964 error:
00965 destroy_io_wait(&io_w);
00966 LM_CRIT("exiting...");
00967 exit(-1);
00968 }
00969
00970 #endif
00971
00972 #endif