• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

tcp_read.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00027 /*
00028  * History:
00029  * --------
00030  * 2002-12-??  created by andrei.
00031  * 2003-02-10  zero term before calling receive_msg & undo afterward (andrei)
00032  * 2003-05-13  l: (short form of Content-Length) is now recognized (andrei)
00033  * 2003-07-01  tcp_read & friends take no a single tcp_connection 
00034  *              parameter & they set c->state to S_CONN_EOF on eof (andrei)
00035  * 2003-07-04  fixed tcp EOF handling (possible infinite loop) (andrei)
00036  * 2005-07-05  migrated to the new io_wait code (andrei)
00037  * 2006-02-03  use tsend_stream instead of send_all (andrei)
00038  * 2006-10-13  added STUN support - state machine for TCP (vlada)
00039  * 2007-02-20  fixed timeout calc. bug (andrei)
00040  * 2007-11-26  improved tcp timers: switched to local_timer (andrei)
00041  * 2008-02-04  optimizations: handle POLLRDHUP (if supported), detect short
00042  *              reads (sock. buffer empty) (andrei)
00043  * 2009-02-26  direct blacklist support (andrei)
00044  * 2009-04-09  tcp ev and tcp stats macros added (andrei)
00045  * 2010-05-14  split tcp_read() into tcp_read() and tcp_read_data() (andrei)
00046  * 2010-05-17  new RD_CONN_REPEAT_READ flag, used by the tls hooks (andrei)
00047  */
00048 
00055 #ifdef USE_TCP
00056 
00057 #include <stdio.h>
00058 #include <errno.h>
00059 #include <string.h>
00060 
00061 
00062 #include <sys/time.h>
00063 #include <sys/types.h>
00064 #include <sys/select.h>
00065 #include <sys/socket.h>
00066 
00067 #include <unistd.h>
00068 #include <stdlib.h> /* for abort() */
00069 
00070 
00071 #include "dprint.h"
00072 #include "tcp_conn.h"
00073 #include "tcp_read.h"
00074 #include "tcp_stats.h"
00075 #include "tcp_ev.h"
00076 #include "pass_fd.h"
00077 #include "globals.h"
00078 #include "receive.h"
00079 #include "timer.h"
00080 #include "local_timer.h"
00081 #include "ut.h"
00082 #include "trim.h"
00083 #include "pt.h"
00084 #include "cfg/cfg_struct.h"
00085 #ifdef CORE_TLS
00086 #include "tls/tls_server.h"
00087 #else
00088 #include "tls_hooks.h"
00089 #endif /* CORE_TLS */
00090 #ifdef USE_DST_BLACKLIST
00091 #include "dst_blacklist.h"
00092 #endif /* USE_DST_BLACKLIST */
00093 
00094 #define HANDLE_IO_INLINE
00095 #include "io_wait.h"
00096 #include <fcntl.h> /* must be included after io_wait.h if SIGIO_RT is used */
00097 #include "tsend.h"
00098 #include "forward.h"
00099 #include "events.h"
00100 
00101 #ifdef USE_STUN
00102 #include "ser_stun.h"
00103 
00104 int is_msg_complete(struct tcp_req* r);
00105 
00106 #endif /* USE_STUN */
00107 
00108 #ifdef READ_HTTP11
00109 #define HTTP11CONTINUE  "HTTP/1.1 100 Continue\r\nContent-Lenght: 0\r\n\r\n"
00110 #define HTTP11CONTINUE_LEN      (sizeof(HTTP11CONTINUE)-1)
00111 #endif
00112 
00113 #define TCPCONN_TIMEOUT_MIN_RUN  1 /* run the timers each new tick */
00114 
00115 /* types used in io_wait* */
00116 enum fd_types { F_NONE, F_TCPMAIN, F_TCPCONN };
00117 
00118 /* list of tcp connections handled by this process */
00119 static struct tcp_connection* tcp_conn_lst=0;
00120 static io_wait_h io_w; /* io_wait handler*/
00121 static int tcpmain_sock=-1;
00122 
00123 static struct local_timer tcp_reader_ltimer;
00124 static ticks_t tcp_reader_prev_ticks;
00125 
00131 #define TCP_CLONE_RCVBUF
00132 static int tcp_clone_rcvbuf = 0;
00133 
00134 int tcp_set_clone_rcvbuf(int v)
00135 {
00136         int r;
00137         r = tcp_clone_rcvbuf;
00138         tcp_clone_rcvbuf = v;
00139         return r;
00140 }
00141 
00142 #ifdef READ_HTTP11
00143 static inline char *strfindcasestrz(str *haystack, char *needlez)
00144 {
00145         int i,j;
00146         str needle;
00147 
00148         needle.s = needlez;
00149         needle.len = strlen(needlez);
00150         for(i=0;i<haystack->len-needle.len;i++) {
00151                 for(j=0;j<needle.len;j++) {
00152                         if ( !((haystack->s[i+j]==needle.s[j]) ||
00153                                         ( isalpha((int)haystack->s[i+j])
00154                                                 && ((haystack->s[i+j])^(needle.s[j]))==0x20 )) )
00155                                 break;
00156                 }
00157                 if (j==needle.len)
00158                         return haystack->s+i;
00159         }
00160         return 0;
00161 }
00162 
00163 int tcp_http11_continue(struct tcp_connection *c)
00164 {
00165         struct dest_info dst;
00166         char *p;
00167         struct msg_start fline;
00168         int ret;
00169         str msg;
00170 
00171         ret = 0;
00172 
00173         msg.s = c->req.start;
00174         msg.len = c->req.pos - c->req.start;
00175 #ifdef READ_MSRP
00176         /* skip if MSRP message */
00177         if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
00178                 return 0;
00179 #endif
00180         p = parse_first_line(msg.s, msg.len, &fline);
00181         if(p==NULL)
00182                 return 0;
00183 
00184         if(fline.type!=SIP_REQUEST)
00185                 return 0;
00186 
00187         /* check if http request */
00188         if(fline.u.request.version.len < HTTP_VERSION_LEN
00189                         || strncasecmp(fline.u.request.version.s,
00190                                 HTTP_VERSION, HTTP_VERSION_LEN))
00191                 return 0;
00192 
00193         /* check for Expect header */
00194         if(strfindcasestrz(&msg, "Expect: 100-continue")!=NULL)
00195         {
00196                 init_dst_from_rcv(&dst, &c->rcv);
00197                 if (tcp_send(&dst, 0, HTTP11CONTINUE, HTTP11CONTINUE_LEN) < 0) {
00198                         LOG(L_ERR, "HTTP/1.1 continue failed\n");
00199                 }
00200         }
00201         /* check for Transfer-Encoding header */
00202         if(strfindcasestrz(&msg, "Transfer-Encoding: chunked")!=NULL)
00203         {
00204                 c->req.flags |= F_TCP_REQ_BCHUNKED;
00205                 ret = 1;
00206         }
00207         return ret;
00208 }
00209 #endif /* HTTP11 */
00210 
00211 
00240 int tcp_read_data(int fd, struct tcp_connection *c,
00241                                         char* buf, int b_size, int* flags)
00242 {
00243         int bytes_read;
00244         
00245 again:
00246         bytes_read=read(fd, buf, b_size);
00247         
00248         if (likely(bytes_read!=b_size)){
00249                 if(unlikely(bytes_read==-1)){
00250                         if (errno == EWOULDBLOCK || errno == EAGAIN){
00251                                 bytes_read=0; /* nothing has been read */
00252                         }else if (errno == EINTR) goto again;
00253                         else{
00254                                 if (unlikely(c->state==S_CONN_CONNECT)){
00255                                         switch(errno){
00256                                                 case ECONNRESET:
00257 #ifdef USE_DST_BLACKLIST
00258                                                         dst_blacklist_su(BLST_ERR_CONNECT, c->rcv.proto,
00259                                                                                                 &c->rcv.src_su,
00260                                                                                                 &c->send_flags, 0);
00261 #endif /* USE_DST_BLACKLIST */
00262                                                         TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
00263                                                                         TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
00264                                                         break;
00265                                                 case ETIMEDOUT:
00266 #ifdef USE_DST_BLACKLIST
00267                                                         dst_blacklist_su(BLST_ERR_CONNECT, c->rcv.proto,
00268                                                                                                 &c->rcv.src_su,
00269                                                                                                 &c->send_flags, 0);
00270 #endif /* USE_DST_BLACKLIST */
00271                                                         TCP_EV_CONNECT_TIMEOUT(errno, TCP_LADDR(c),
00272                                                                         TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
00273                                                         break;
00274                                                 default:
00275                                                         TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
00276                                                                         TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
00277                                         }
00278                                         TCP_STATS_CONNECT_FAILED();
00279                                 }else{
00280                                                 switch(errno){
00281                                                         case ECONNRESET:
00282                                                                 TCP_STATS_CON_RESET();
00283                                                         case ETIMEDOUT:
00284 #ifdef USE_DST_BLACKLIST
00285                                                                 dst_blacklist_su(BLST_ERR_SEND, c->rcv.proto,
00286                                                                                                         &c->rcv.src_su,
00287                                                                                                         &c->send_flags, 0);
00288 #endif /* USE_DST_BLACKLIST */
00289                                                                 break;
00290                                                 }
00291                                 }
00292                                 LOG(cfg_get(core, core_cfg, corelog),
00293                                                 "error reading: %s (%d)\n", strerror(errno), errno);
00294                                 return -1;
00295                         }
00296                 }else if (unlikely((bytes_read==0) || 
00297                                         (*flags & RD_CONN_FORCE_EOF))){
00298                         c->state=S_CONN_EOF;
00299                         *flags|=RD_CONN_EOF;
00300                         DBG("EOF on %p, FD %d\n", c, fd);
00301                 }else{
00302                         if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
00303                                 TCP_STATS_ESTABLISHED(c->state);
00304                                 c->state=S_CONN_OK;
00305                         }
00306                 }
00307                 /* short read */
00308                 *flags|=RD_CONN_SHORT_READ;
00309         }else{ /* else normal full read */
00310                 if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
00311                         TCP_STATS_ESTABLISHED(c->state);
00312                         c->state=S_CONN_OK;
00313                 }
00314         }
00315         return bytes_read;
00316 }
00317 
00318 
00319 
00320 /* reads next available bytes
00321  *   c- tcp connection used for reading, tcp_read changes also c->state on
00322  *      EOF and c->req.error on read error
00323  *   * flags - value/result - used to signal a seen or "forced" EOF on the 
00324  *     connection (when it is known that no more data will come after the 
00325  *     current socket buffer is emptied )=> return/signal EOF on the first 
00326  *     short read (=> don't use it on POLLPRI, as OOB data will cause short
00327  *      reads even if there are still remaining bytes in the socket buffer)
00328  * return number of bytes read, 0 on EOF or -1 on error,
00329  * on EOF it also sets c->state to S_CONN_EOF.
00330  * (to distinguish from reads that would block which could return 0)
00331  * RD_CONN_SHORT_READ is also set in *flags for short reads.
00332  * sets also r->error */
00333 int tcp_read(struct tcp_connection *c, int* flags)
00334 {
00335         int bytes_free, bytes_read;
00336         struct tcp_req *r;
00337         int fd;
00338 
00339         r=&c->req;
00340         fd=c->fd;
00341         bytes_free=r->b_size- (int)(r->pos - r->buf);
00342         
00343         if (unlikely(bytes_free==0)){
00344                 LOG(L_ERR, "ERROR: tcp_read: buffer overrun, dropping\n");
00345                 r->error=TCP_REQ_OVERRUN;
00346                 return -1;
00347         }
00348         bytes_read = tcp_read_data(fd, c, r->pos, bytes_free, flags);
00349         if (unlikely(bytes_read < 0)){
00350                 r->error=TCP_READ_ERROR;
00351                 return -1;
00352         }
00353 #ifdef EXTRA_DEBUG
00354         DBG("tcp_read: read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
00355 #endif
00356         r->pos+=bytes_read;
00357         return bytes_read;
00358 }
00359 
00360 
00361 
00362 /* reads all headers (until double crlf), & parses the content-length header
00363  * (WARNING: inefficient, tries to reuse receive_msg but will go through
00364  * the headers twice [once here looking for Content-Length and for the end
00365  * of the headers and once in receive_msg]; a more speed efficient version will
00366  * result in either major code duplication or major changes to the receive code)
00367  * returns number of bytes read & sets r->state & r->body
00368  * when either r->body!=0 or r->state==H_BODY =>
00369  * all headers have been read. It should be called in a while loop.
00370  * returns < 0 if error or 0 if EOF */
00371 int tcp_read_headers(struct tcp_connection *c, int* read_flags)
00372 {
00373         int bytes, remaining;
00374         char *p;
00375         struct tcp_req* r;
00376 
00377 #ifdef USE_STUN
00378         unsigned int mc;   /* magic cookie */
00379         unsigned short body_len;
00380 #endif
00381 
00382 #ifdef READ_MSRP
00383         char *mfline;
00384         str mtransid;
00385 #endif
00386 
00387         #define crlf_default_skip_case \
00388                                         case '\n': \
00389                                                 r->state=H_LF; \
00390                                                 break; \
00391                                         default: \
00392                                                 r->state=H_SKIP
00393         
00394         #define content_len_beg_case \
00395                                         case ' ': \
00396                                         case '\t': \
00397                                                 if (!TCP_REQ_HAS_CLEN(r)) r->state=H_STARTWS; \
00398                                                 else r->state=H_SKIP; \
00399                                                         /* not interested if we already found one */ \
00400                                                 break; \
00401                                         case 'C': \
00402                                         case 'c': \
00403                                                 if(!TCP_REQ_HAS_CLEN(r)) r->state=H_CONT_LEN1; \
00404                                                 else r->state=H_SKIP; \
00405                                                 break; \
00406                                         case 'l': \
00407                                         case 'L': \
00408                                                 /* short form for Content-Length */ \
00409                                                 if (!TCP_REQ_HAS_CLEN(r)) r->state=H_L_COLON; \
00410                                                 else r->state=H_SKIP; \
00411                                                 break
00412                                                 
00413         #define change_state(upper, lower, newstate)\
00414                                         switch(*p){ \
00415                                                 case upper: \
00416                                                 case lower: \
00417                                                         r->state=(newstate); break; \
00418                                                 crlf_default_skip_case; \
00419                                         }
00420         
00421         #define change_state_case(state0, upper, lower, newstate)\
00422                                         case state0: \
00423                                                           change_state(upper, lower, newstate); \
00424                                                           p++; \
00425                                                           break
00426 
00427 
00428         r=&c->req;
00429         /* if we still have some unparsed part, parse it first, don't do the read*/
00430         if (unlikely(r->parsed<r->pos)){
00431                 bytes=0;
00432         }else{
00433 #ifdef USE_TLS
00434                 if (unlikely(c->type==PROTO_TLS))
00435                         bytes=tls_read(c, read_flags);
00436                 else
00437 #endif
00438                         bytes=tcp_read(c, read_flags);
00439                 if (bytes<=0) return bytes;
00440         }
00441         p=r->parsed;
00442         
00443         while(p<r->pos && r->error==TCP_REQ_OK){
00444                 switch((unsigned char)r->state){
00445                         case H_BODY: /* read the body*/
00446                                 remaining=r->pos-p;
00447                                 if (remaining>r->bytes_to_go) remaining=r->bytes_to_go;
00448                                 r->bytes_to_go-=remaining;
00449                                 p+=remaining;
00450                                 if (r->bytes_to_go==0){
00451                                         r->flags|=F_TCP_REQ_COMPLETE;
00452                                         goto skip;
00453                                 }
00454                                 break;
00455                                 
00456                         case H_SKIP:
00457                                 /* find lf, we are in this state if we are not interested
00458                                  * in anything till end of line*/
00459                                 p=q_memchr(p, '\n', r->pos-p);
00460                                 if (p){
00461 #ifdef READ_MSRP
00462                                         /* catch if it is MSRP or not with first '\n' */
00463                                         if(!((r->flags&F_TCP_REQ_MSRP_NO)
00464                                                                 || (r->flags&F_TCP_REQ_MSRP_FRAME))) {
00465                                                 if((r->pos - r->start)>5
00466                                                                         && strncmp(r->start, "MSRP ", 5)==0)
00467                                                 {
00468                                                         r->flags |= F_TCP_REQ_MSRP_FRAME;
00469                                                 } else {
00470                                                         r->flags |= F_TCP_REQ_MSRP_NO;
00471                                                 }
00472                                         }
00473 #endif
00474                                         p++;
00475                                         r->state=H_LF;
00476                                 }else{
00477                                         p=r->pos;
00478                                 }
00479                                 break;
00480                                 
00481                         case H_LF:
00482                                 /* terminate on LF CR LF or LF LF */
00483                                 switch (*p){
00484                                         case '\r':
00485                                                 r->state=H_LFCR;
00486                                                 break;
00487                                         case '\n':
00488                                                 /* found LF LF */
00489                                                 r->state=H_BODY;
00490                                                 if (TCP_REQ_HAS_CLEN(r)){
00491                                                         r->body=p+1;
00492                                                         r->bytes_to_go=r->content_len;
00493                                                         if (r->bytes_to_go==0){
00494                                                                 r->flags|=F_TCP_REQ_COMPLETE;
00495                                                                 p++;
00496                                                                 goto skip;
00497                                                         }
00498                                                 }else{
00499                                                         DBG("tcp_read_headers: ERROR: no clen, p=%X\n",
00500                                                                         *p);
00501                                                         r->error=TCP_REQ_BAD_LEN;
00502                                                 }
00503                                                 break;
00504                                         case '-':
00505                                                 r->state=H_SKIP;
00506 #ifdef READ_MSRP
00507                                                 /* catch end of MSRP frame without body
00508                                                  *     '-------sessid$\r\n'
00509                                                  * follows headers wihtout extra CRLF */
00510                                                 if(r->flags&F_TCP_REQ_MSRP_FRAME) {
00511                                                         p--;
00512                                                         r->state=H_MSRP_BODY_END;
00513                                                 }
00514 #endif
00515                                                 break;
00516                                         content_len_beg_case;
00517                                         default: 
00518                                                 r->state=H_SKIP;
00519                                 }
00520                                 p++;
00521                                 break;
00522                         case H_LFCR:
00523                                 if (*p=='\n'){
00524                                         /* found LF CR LF */
00525                                         r->state=H_BODY;
00526 #ifdef READ_HTTP11
00527                                         if (cfg_get(tcp, tcp_cfg, accept_no_cl)!=0)
00528                                                 tcp_http11_continue(c);
00529 #endif
00530                                         if (TCP_REQ_HAS_CLEN(r)){
00531                                                 r->body=p+1;
00532                                                 r->bytes_to_go=r->content_len;
00533                                                 if (r->bytes_to_go==0){
00534                                                         r->flags|=F_TCP_REQ_COMPLETE;
00535                                                         p++;
00536                                                         goto skip;
00537                                                 }
00538                                         }else{
00539                                                 if (cfg_get(tcp, tcp_cfg, accept_no_cl)!=0) {
00540 #ifdef READ_MSRP
00541                                                         /* if MSRP message */
00542                                                         if(c->req.flags&F_TCP_REQ_MSRP_FRAME)
00543                                                         {
00544                                                                 r->body=p+1;
00545                                                                 /* at least 3 bytes: 0\r\n */
00546                                                                 r->bytes_to_go=3;
00547                                                                 p++;
00548                                                                 r->content_len = 0;
00549                                                                 r->state=H_MSRP_BODY;
00550                                                                 break;
00551                                                         }
00552 #endif
00553 
00554 #ifdef READ_HTTP11
00555                                                         if(TCP_REQ_BCHUNKED(r)) {
00556                                                                 r->body=p+1;
00557                                                                 /* at least 3 bytes: 0\r\n */
00558                                                                 r->bytes_to_go=3;
00559                                                                 p++;
00560                                                                 r->content_len = 0;
00561                                                                 r->state=H_HTTP11_CHUNK_START;
00562                                                                 break;
00563                                                         }
00564 #endif
00565                                                         r->body=p+1;
00566                                                         r->bytes_to_go=0;
00567                                                         r->flags|=F_TCP_REQ_COMPLETE;
00568                                                         p++;
00569                                                         goto skip;
00570                                                 } else {
00571                                                         DBG("tcp_read_headers: ERROR: no clen, p=%X\n",
00572                                                                         *p);
00573                                                         r->error=TCP_REQ_BAD_LEN;
00574                                                 }
00575                                         }
00576                                 }else r->state=H_SKIP;
00577                                 p++;
00578                                 break;
00579                                 
00580                         case H_STARTWS:
00581                                 switch (*p){
00582                                         content_len_beg_case;
00583                                         crlf_default_skip_case;
00584                                 }
00585                                 p++;
00586                                 break;
00587                         case H_SKIP_EMPTY:
00588                                 switch (*p){
00589                                         case '\n':
00590                                                 break;
00591                                         case '\r':
00592                                                 if (cfg_get(tcp, tcp_cfg, crlf_ping)) {
00593                                                         r->state=H_SKIP_EMPTY_CR_FOUND;
00594                                                         r->start=p;
00595                                                 }
00596                                                 break;
00597                                         case ' ':
00598                                         case '\t':
00599                                                 /* skip empty lines */
00600                                                 break;
00601                                         case 'C': 
00602                                         case 'c': 
00603                                                 r->state=H_CONT_LEN1; 
00604                                                 r->start=p;
00605                                                 break;
00606                                         case 'l':
00607                                         case 'L':
00608                                                 /* short form for Content-Length */
00609                                                 r->state=H_L_COLON;
00610                                                 r->start=p;
00611                                                 break;
00612                                         default:
00613 #ifdef USE_STUN
00614                                                 /* STUN support can be switched off even if it's compiled */
00615                                                 /* stun test */                                         
00616                                                 if (stun_allow_stun && (unsigned char)*p == 0x00) {
00617                                                         r->state=H_STUN_MSG;
00618                                                 /* body will used as pointer to the last used byte */
00619                                                         r->body=p;
00620                                                         r->content_len = 0;
00621                                                         DBG("stun msg detected\n");
00622                                                 }else
00623 #endif
00624                                                 r->state=H_SKIP;
00625                                                 r->start=p;
00626                                 };
00627                                 p++;
00628                                 break;
00629 
00630                         case H_SKIP_EMPTY_CR_FOUND:
00631                                 if (*p=='\n'){
00632                                         r->state=H_SKIP_EMPTY_CRLF_FOUND;
00633                                         p++;
00634                                 }else{
00635                                         r->state=H_SKIP_EMPTY;
00636                                 }
00637                                 break;
00638 
00639                         case H_SKIP_EMPTY_CRLF_FOUND:
00640                                 if (*p=='\r'){
00641                                         r->state = H_SKIP_EMPTY_CRLFCR_FOUND;
00642                                         p++;
00643                                 }else{
00644                                         r->state = H_SKIP_EMPTY;
00645                                 }
00646                                 break;
00647 
00648                         case H_SKIP_EMPTY_CRLFCR_FOUND:
00649                                 if (*p=='\n'){
00650                                         r->state = H_PING_CRLF;
00651                                         r->flags |= F_TCP_REQ_HAS_CLEN |
00652                                                         F_TCP_REQ_COMPLETE; /* hack to avoid error check */
00653                                         p++;
00654                                         goto skip;
00655                                 }else{
00656                                         r->state = H_SKIP_EMPTY;
00657                                 }
00658                                 break;
00659 #ifdef USE_STUN
00660                         case H_STUN_MSG:
00661                                 if ((r->pos - r->body) >= sizeof(struct stun_hdr)) {
00662                                         /* copy second short from buffer where should be body 
00663                                          * length 
00664                                          */
00665                                         memcpy(&body_len, &r->start[sizeof(unsigned short)], 
00666                                                 sizeof(unsigned short));
00667                                         
00668                                         body_len = ntohs(body_len);
00669                                         
00670                                         /* check if there is valid magic cookie */
00671                                         memcpy(&mc, &r->start[sizeof(unsigned int)], 
00672                                                 sizeof(unsigned int));
00673                                         mc = ntohl(mc);
00674                                         /* using has_content_len as a flag if there should be
00675                                          * fingerprint or no
00676                                          */
00677                                         r->flags |= (mc == MAGIC_COOKIE) ? F_TCP_REQ_HAS_CLEN : 0;
00678                                         
00679                                         r->body += sizeof(struct stun_hdr);
00680                                         p = r->body; 
00681                                         
00682                                         if (body_len > 0) {
00683                                                 r->state = H_STUN_READ_BODY;
00684                                         }
00685                                         else {
00686                                                 if (is_msg_complete(r) != 0) {
00687                                                         goto skip;
00688                                                 }
00689                                                 else {
00690                                                         /* set content_len to length of fingerprint */
00691                                                         body_len = sizeof(struct stun_attr) + 
00692                                                                            SHA_DIGEST_LENGTH;
00693                                                 }
00694                                         }
00695                                         r->content_len=body_len;
00696                                 }
00697                                 else {
00698                                         p = r->pos; 
00699                                 }
00700                                 break;
00701                                 
00702                         case H_STUN_READ_BODY:
00703                                 /* check if the whole body was read */
00704                                 body_len=r->content_len;
00705                                 if ((r->pos - r->body) >= body_len) {
00706                                         r->body += body_len;
00707                                         p = r->body;
00708                                         if (is_msg_complete(r) != 0) {
00709                                                 r->content_len=0;
00710                                                 goto skip;
00711                                         }
00712                                         else {
00713                                                 /* set content_len to length of fingerprint */
00714                                                 body_len = sizeof(struct stun_attr)+SHA_DIGEST_LENGTH;
00715                                                 r->content_len=body_len;
00716                                         }
00717                                 }
00718                                 else {
00719                                         p = r->pos;
00720                                 }
00721                                 break;
00722                                 
00723                         case H_STUN_FP:
00724                                 /* content_len contains length of fingerprint in this place! */
00725                                 body_len=r->content_len;
00726                                 if ((r->pos - r->body) >= body_len) {
00727                                         r->body += body_len;
00728                                         p = r->body;
00729                                         r->state = H_STUN_END;
00730                                         r->flags |= F_TCP_REQ_COMPLETE |
00731                                                 F_TCP_REQ_HAS_CLEN; /* hack to avoid error check */
00732                                         r->content_len=0;
00733                                         goto skip;
00734                                 }
00735                                 else {
00736                                         p = r->pos;
00737                                 }
00738                                 break;
00739 #endif /* USE_STUN */
00740                         change_state_case(H_CONT_LEN1,  'O', 'o', H_CONT_LEN2);
00741                         change_state_case(H_CONT_LEN2,  'N', 'n', H_CONT_LEN3);
00742                         change_state_case(H_CONT_LEN3,  'T', 't', H_CONT_LEN4);
00743                         change_state_case(H_CONT_LEN4,  'E', 'e', H_CONT_LEN5);
00744                         change_state_case(H_CONT_LEN5,  'N', 'n', H_CONT_LEN6);
00745                         change_state_case(H_CONT_LEN6,  'T', 't', H_CONT_LEN7);
00746                         change_state_case(H_CONT_LEN7,  '-', '_', H_CONT_LEN8);
00747                         change_state_case(H_CONT_LEN8,  'L', 'l', H_CONT_LEN9);
00748                         change_state_case(H_CONT_LEN9,  'E', 'e', H_CONT_LEN10);
00749                         change_state_case(H_CONT_LEN10, 'N', 'n', H_CONT_LEN11);
00750                         change_state_case(H_CONT_LEN11, 'G', 'g', H_CONT_LEN12);
00751                         change_state_case(H_CONT_LEN12, 'T', 't', H_CONT_LEN13);
00752                         change_state_case(H_CONT_LEN13, 'H', 'h', H_L_COLON);
00753 
00754                         case H_L_COLON:
00755                                 switch(*p){
00756                                         case ' ':
00757                                         case '\t':
00758                                                 break; /* skip space */
00759                                         case ':':
00760                                                 r->state=H_CONT_LEN_BODY;
00761                                                 break;
00762                                         crlf_default_skip_case;
00763                                 };
00764                                 p++;
00765                                 break;
00766 
00767                         case  H_CONT_LEN_BODY:
00768                                 switch(*p){
00769                                         case ' ':
00770                                         case '\t':
00771                                                 break; /* eat space */
00772                                         case '0':
00773                                         case '1':
00774                                         case '2':
00775                                         case '3':
00776                                         case '4':
00777                                         case '5':
00778                                         case '6':
00779                                         case '7':
00780                                         case '8':
00781                                         case '9':
00782                                                 r->state=H_CONT_LEN_BODY_PARSE;
00783                                                 r->content_len=(*p-'0');
00784                                                 break;
00785                                         /*FIXME: content length on different lines ! */
00786                                         crlf_default_skip_case;
00787                                 }
00788                                 p++;
00789                                 break;
00790 
00791                         case H_CONT_LEN_BODY_PARSE:
00792                                 switch(*p){
00793                                         case '0':
00794                                         case '1':
00795                                         case '2':
00796                                         case '3':
00797                                         case '4':
00798                                         case '5':
00799                                         case '6':
00800                                         case '7':
00801                                         case '8':
00802                                         case '9':
00803                                                 r->content_len=r->content_len*10+(*p-'0');
00804                                                 break;
00805                                         case '\r':
00806                                         case ' ':
00807                                         case '\t': /* FIXME: check if line contains only WS */
00808                                                 r->state=H_SKIP;
00809                                                 r->flags|=F_TCP_REQ_HAS_CLEN;
00810                                                 break;
00811                                         case '\n':
00812                                                 /* end of line, parse successful */
00813                                                 r->state=H_LF;
00814                                                 r->flags|=F_TCP_REQ_HAS_CLEN;
00815                                                 break;
00816                                         default:
00817                                                 LOG(L_ERR, "ERROR: tcp_read_headers: bad "
00818                                                                 "Content-Length header value, unexpected "
00819                                                                 "char %c in state %d\n", *p, r->state);
00820                                                 r->state=H_SKIP; /* try to find another?*/
00821                                 }
00822                                 p++;
00823                                 break;
00824                         
00825 #ifdef READ_HTTP11
00826                         case H_HTTP11_CHUNK_START: /* start a new body chunk: SIZE\r\nBODY\r\n */
00827                                 r->chunk_size = 0;
00828                                 r->state = H_HTTP11_CHUNK_SIZE;
00829                                 break;
00830                         case H_HTTP11_CHUNK_BODY: /* content of chunnk */
00831                                 remaining=r->pos-p;
00832                                 if (remaining>r->bytes_to_go) remaining=r->bytes_to_go;
00833                                 r->bytes_to_go-=remaining;
00834                                 p+=remaining;
00835                                 if (r->bytes_to_go==0){
00836                                         r->state = H_HTTP11_CHUNK_END;
00837                                         /* shift back body content */
00838                                         if(r->chunk_size>0 && p-r->chunk_size>r->body) {
00839                                                 memmove(r->body + r->content_len, p - r->chunk_size,
00840                                                                 r->chunk_size);
00841                                                 r->content_len += r->chunk_size;
00842                                         }
00843                                         goto skip;
00844                                 }
00845                                 break;
00846 
00847                         case H_HTTP11_CHUNK_END:
00848                                 switch(*p){
00849                                         case '\r':
00850                                         case ' ':
00851                                         case '\t': /* skip */
00852                                                 break;
00853                                         case '\n':
00854                                                 r->state = H_HTTP11_CHUNK_START;
00855                                                 break;
00856                                         default:
00857                                                 LM_ERR("bad chunk, unexpected "
00858                                                                 "char %c in state %d\n", *p, r->state);
00859                                                 r->state=H_SKIP; /* try to find another?*/
00860                                 }
00861                                 p++;
00862                                 break;
00863 
00864                         case H_HTTP11_CHUNK_SIZE:
00865                                 switch(*p){
00866                                         case '0': case '1': case '2': case '3':
00867                                         case '4': case '5': case '6': case '7':
00868                                         case '8': case '9':
00869                                                 r->chunk_size <<= 4;
00870                                                 r->chunk_size += *p - '0';
00871                                                 break;
00872                                         case 'a': case 'b': case 'c': case 'd':
00873                                         case 'e': case 'f':
00874                                                 r->chunk_size <<= 4;
00875                                                 r->chunk_size += *p - 'a' + 10;
00876                                                 break;
00877                                         case 'A': case 'B': case 'C': case 'D':
00878                                         case 'E': case 'F':
00879                                                 r->chunk_size <<= 4;
00880                                                 r->chunk_size += *p - 'A' + 10;
00881                                                 break;
00882                                         case '\r':
00883                                         case ' ':
00884                                         case '\t': /* skip */
00885                                                 break;
00886                                         case '\n':
00887                                                 /* end of line, parse successful */
00888                                                 r->state=H_HTTP11_CHUNK_BODY;
00889                                                 r->bytes_to_go = r->chunk_size;
00890                                                 if (r->bytes_to_go==0){
00891                                                         r->state=H_HTTP11_CHUNK_FINISH;
00892                                                         r->flags|=F_TCP_REQ_COMPLETE;
00893                                                         p++;
00894                                                         goto skip;
00895                                                 }
00896                                                 break;
00897                                         default:
00898                                                 LM_ERR("bad chunk size value, unexpected "
00899                                                                 "char %c in state %d\n", *p, r->state);
00900                                                 r->state=H_SKIP; /* try to find another?*/
00901                                 }
00902                                 p++;
00903                                 break;
00904 #endif
00905 #ifdef READ_MSRP
00906                         case H_MSRP_BODY: /* body of msrp frame */
00907                                 /* find lf, we are in this state if we are not interested
00908                                  * in anything till end of line*/
00909                                 r->flags |= F_TCP_REQ_MSRP_BODY;
00910                                 p = q_memchr(p, '\n', r->pos-p);
00911                                 if (p) {
00912                                         p++;
00913                                         r->state=H_MSRP_BODY_LF;
00914                                 } else {
00915                                         p=r->pos;
00916                                 }
00917                                 break;
00918                         case H_MSRP_BODY_LF: /* LF in body of msrp frame */
00919                                 switch (*p) {
00920                                         case '-':
00921                                                         p--;
00922                                                         r->state=H_MSRP_BODY_END;
00923                                                 break;
00924                                         default:
00925                                                 r->state=H_MSRP_BODY;
00926                                 }
00927                                 p++;
00928                                 break;
00929                         case H_MSRP_BODY_END: /* end of body for msrp frame */
00930                                 /* find LF and check if it is end-line */
00931                                 p = q_memchr(p, '\n', r->pos-p);
00932                                 if (p) {
00933                                         /* check if it is end line '-------sessid$\r\n' */
00934                                         if(r->pos - r->start < 10) {
00935                                                 LM_ERR("weird situation when reading MSRP frame"
00936                                                                 " - continue reading\n");
00937                                                 p++;
00938                                                 r->state=H_MSRP_BODY;
00939                                                 break;
00940                                         }
00941                                         if(*(p-1)!='\r') {
00942                                                 /* not ending in '\r\n' - not end-line */
00943                                                 p++;
00944                                                 r->state=H_MSRP_BODY;
00945                                                 break;
00946                                         }
00947                                         /* locate transaction id in first line
00948                                          * -- first line exists, that's why we are here */
00949                                         mfline =  q_memchr(r->start, '\n', r->pos-r->start);
00950                                         mtransid.s = q_memchr(r->start + 5 /* 'MSRP ' */, ' ',
00951                                                         mfline - r->start);
00952                                         mtransid.len = mtransid.s - r->start - 5;
00953                                         mtransid.s = r->start + 5;
00954                                         trim(&mtransid);
00955                                         if(memcmp(mtransid.s,
00956                                                         p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - mtransid.len,
00957                                                         mtransid.len)!=0) {
00958                                                 /* no match on session id - not end-line */
00959                                                 p++;
00960                                                 r->state=H_MSRP_BODY;
00961                                                 break;
00962                                         }
00963                                         if(memcmp(p - 1 /*\r*/ - 1 /* '+'|'#'|'$' */ - mtransid.len
00964                                                                 - 7 /* 7 x '-' */ - 1 /* '\n' */, "\n-------",
00965                                                                 8)!=0) {
00966                                                 /* no match on "\n-------" - not end-line */
00967                                                 p++;
00968                                                 r->state=H_MSRP_BODY;
00969                                                 break;
00970                                         }
00971                                         r->state=H_MSRP_FINISH;
00972                                         r->flags|=F_TCP_REQ_COMPLETE;
00973                                         p++;
00974                                         goto skip;
00975 
00976                                 } else {
00977                                         p=r->pos;
00978                                 }
00979                                 break;
00980 #endif
00981 
00982                         default:
00983                                 LOG(L_CRIT, "BUG: tcp_read_headers: unexpected state %d\n",
00984                                                 r->state);
00985                                 abort();
00986                 }
00987         }
00988 skip:
00989         r->parsed=p;
00990         return bytes;
00991 }
00992 
00993 
00994 #ifdef READ_MSRP
00995 int msrp_process_msg(char* tcpbuf, unsigned int len,
00996                 struct receive_info* rcv_info, struct tcp_connection* con)
00997 {
00998         int ret;
00999         tcp_event_info_t tev;
01000 
01001         ret = 0;
01002         LM_DBG("MSRP Message: [[>>>\n%.*s<<<]]\n", len, tcpbuf);
01003         if(likely(sr_event_enabled(SREV_TCP_MSRP_FRAME))) {
01004                 memset(&tev, 0, sizeof(tcp_event_info_t));
01005                 tev.type = SREV_TCP_MSRP_FRAME;
01006                 tev.buf = tcpbuf;
01007                 tev.len = len;
01008                 tev.rcv = rcv_info;
01009                 tev.con = con;
01010                 ret = sr_event_exec(SREV_TCP_MSRP_FRAME, (void*)(&tev));
01011         } else {
01012                 LM_DBG("no callback registering for handling MSRP - dropping!\n");
01013         }
01014         return ret;
01015 }
01016 #endif
01017 
01026 int receive_tcp_msg(char* tcpbuf, unsigned int len,
01027                 struct receive_info* rcv_info, struct tcp_connection* con)
01028 {
01029 #ifdef TCP_CLONE_RCVBUF
01030 #ifdef DYN_BUF
01031         char *buf = NULL;
01032 #else
01033         static char *buf = NULL;
01034         static unsigned int bsize = 0;
01035 #endif
01036         int blen;
01037 
01038         /* cloning is disabled via parameter */
01039         if(likely(tcp_clone_rcvbuf==0)) {
01040 #ifdef READ_MSRP
01041                 if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
01042                         return msrp_process_msg(tcpbuf, len, rcv_info, con);
01043 #endif
01044                 return receive_msg(tcpbuf, len, rcv_info);
01045         }
01046 
01047         /* min buffer size is BUF_SIZE */
01048         blen = len;
01049         if(blen < BUF_SIZE)
01050                 blen = BUF_SIZE;
01051 
01052 #ifdef DYN_BUF
01053         buf=pkg_malloc(blen+1);
01054         if (buf==0) {
01055                 LM_ERR("could not allocate receive buffer\n");
01056                 return -1;
01057         }
01058 #else
01059         /* allocate buffer when needed
01060          * - no buffer yet
01061          * - existing buffer too small (min size is BUF_SIZE - to accomodate most
01062          *   of SIP messages; expected larger for HTTP/XCAP)
01063          * - existing buffer too large (e.g., we got a too big message in the past,
01064          *   let's free it)
01065          *
01066          * - also, use system memory, not to eat from PKG (same as static buffer
01067          *   from PKG pov)
01068          */
01069         if(buf==NULL || bsize < blen || blen < bsize/2) {
01070                 if(buf!=NULL)
01071                         free(buf);
01072                 buf=malloc(blen+1);
01073                 if (buf==0) {
01074                         LM_ERR("could not allocate receive buffer\n");
01075                         return -1;
01076                 }
01077                 bsize = blen;
01078         }
01079 #endif
01080 
01081         memcpy(buf, tcpbuf, len);
01082         buf[len] = '\0';
01083 #ifdef READ_MSRP
01084         if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
01085                 return msrp_process_msg(buf, len, rcv_info, con);
01086 #endif
01087         return receive_msg(buf, len, rcv_info);
01088 #else /* TCP_CLONE_RCVBUF */
01089 #ifdef READ_MSRP
01090         if(unlikely(con->req.flags&F_TCP_REQ_MSRP_FRAME))
01091                 return msrp_process_msg(tcpbuf, len, rcv_info, con);
01092 #endif
01093         return receive_msg(tcpbuf, len, rcv_info);
01094 #endif /* TCP_CLONE_RCVBUF */
01095 }
01096 
01097 int tcp_read_req(struct tcp_connection* con, int* bytes_read, int* read_flags)
01098 {
01099         int bytes;
01100         int total_bytes;
01101         int resp;
01102         long size;
01103         struct tcp_req* req;
01104         struct dest_info dst;
01105         char c;
01106         int ret;
01107                 
01108                 bytes=-1;
01109                 total_bytes=0;
01110                 resp=CONN_RELEASE;
01111                 req=&con->req;
01112 
01113 again:
01114                 if (likely(req->error==TCP_REQ_OK)){
01115                         bytes=tcp_read_headers(con, read_flags);
01116 #ifdef EXTRA_DEBUG
01117                                                 /* if timeout state=0; goto end__req; */
01118                         DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n",
01119                                         bytes, (int)(req->parsed-req->start), req->state,
01120                                         req->error );
01121                         DBG("tcp_read_req: last char=0x%02X, parsed msg=\n%.*s\n",
01122                                         *(req->parsed-1), (int)(req->parsed-req->start),
01123                                         req->start);
01124 #endif
01125                         if (unlikely(bytes==-1)){
01126                                 LOG(cfg_get(core, core_cfg, corelog),
01127                                                 "ERROR: tcp_read_req: error reading \n");
01128                                 resp=CONN_ERROR;
01129                                 goto end_req;
01130                         }
01131                         total_bytes+=bytes;
01132                         /* eof check:
01133                          * is EOF if eof on fd and req.  not complete yet,
01134                          * if req. is complete we might have a second unparsed
01135                          * request after it, so postpone release_with_eof
01136                          */
01137                         if (unlikely((con->state==S_CONN_EOF) && 
01138                                                 (! TCP_REQ_COMPLETE(req)))) {
01139                                 DBG( "tcp_read_req: EOF\n");
01140                                 resp=CONN_EOF;
01141                                 goto end_req;
01142                         }
01143                 
01144                 }
01145                 if (unlikely(req->error!=TCP_REQ_OK)){
01146                         LOG(L_ERR,"ERROR: tcp_read_req: bad request, state=%d, error=%d "
01147                                           "buf:\n%.*s\nparsed:\n%.*s\n", req->state, req->error,
01148                                           (int)(req->pos-req->buf), req->buf,
01149                                           (int)(req->parsed-req->start), req->start);
01150                         DBG("- received from: port %d\n", con->rcv.src_port);
01151                         print_ip("- received from: ip ",&con->rcv.src_ip, "\n");
01152                         resp=CONN_ERROR;
01153                         goto end_req;
01154                 }
01155                 if (likely(TCP_REQ_COMPLETE(req))){
01156 #ifdef EXTRA_DEBUG
01157                         DBG("tcp_read_req: end of header part\n");
01158                         DBG("- received from: port %d\n", con->rcv.src_port);
01159                         print_ip("- received from: ip ", &con->rcv.src_ip, "\n");
01160                         DBG("tcp_read_req: headers:\n%.*s.\n",
01161                                         (int)(req->body-req->start), req->start);
01162 #endif
01163                         if (likely(TCP_REQ_HAS_CLEN(req))){
01164                                 DBG("tcp_read_req: content-length= %d\n", req->content_len);
01165 #ifdef EXTRA_DEBUG
01166                                 DBG("tcp_read_req: body:\n%.*s\n", req->content_len,req->body);
01167 #endif
01168                         }else{
01169                                 if (cfg_get(tcp, tcp_cfg, accept_no_cl)==0) {
01170                                         req->error=TCP_REQ_BAD_LEN;
01171                                         LOG(L_ERR, "ERROR: tcp_read_req: content length not present or"
01172                                                 " unparsable\n");
01173                                         resp=CONN_ERROR;
01174                                         goto end_req;
01175                                 }
01176                         }
01177                         /* if we are here everything is nice and ok*/
01178                         resp=CONN_RELEASE;
01179 #ifdef EXTRA_DEBUG
01180                         DBG("receiving msg(%p, %d, )\n",
01181                                         req->start, (int)(req->parsed-req->start));
01182 #endif
01183                         /* rcv.bind_address should always be !=0 */
01184                         bind_address=con->rcv.bind_address;
01185                         /* just for debugging use sendipv4 as receiving socket  FIXME*/
01186                         /*
01187                         if (con->rcv.dst_ip.af==AF_INET6){
01188                                 bind_address=sendipv6_tcp;
01189                         }else{
01190                                 bind_address=sendipv4_tcp;
01191                         }
01192                         */
01193                         con->rcv.proto_reserved1=con->id; /* copy the id */
01194                         c=*req->parsed; /* ugly hack: zero term the msg & save the
01195                                                            previous char, req->parsed should be ok
01196                                                            because we always alloc BUF_SIZE+1 */
01197                         *req->parsed=0;
01198 
01199                         if (req->state==H_PING_CRLF) {
01200                                 init_dst_from_rcv(&dst, &con->rcv);
01201 
01202                                 if (tcp_send(&dst, 0, CRLF, CRLF_LEN) < 0) {
01203                                         LOG(L_ERR, "CRLF ping: tcp_send() failed\n");
01204                                 }
01205                                 ret = 0;
01206                         }else
01207 #ifdef USE_STUN
01208                         if (unlikely(req->state==H_STUN_END)){
01209                                 /* stun request */
01210                                 ret = stun_process_msg(req->start, req->parsed-req->start,
01211                                                                          &con->rcv);
01212                         }else
01213 #endif
01214 #ifdef READ_MSRP
01215                         // if (unlikely(req->flags&F_TCP_REQ_MSRP_FRAME)){
01216                         if (unlikely(req->state==H_MSRP_FINISH)){
01217                                 /* msrp frame */
01218                                 ret = receive_tcp_msg(req->start, req->parsed-req->start,
01219                                                                         &con->rcv, con);
01220                         }else
01221 #endif
01222 #ifdef READ_HTTP11
01223                         if (unlikely(req->state==H_HTTP11_CHUNK_FINISH)){
01224                                 /* http chunked request */
01225                                 req->body[req->content_len] = 0;
01226                                 ret = receive_tcp_msg(req->start,
01227                                                 req->body + req->content_len - req->start,
01228                                                 &con->rcv, con);
01229                         }else
01230 #endif
01231                                 ret = receive_tcp_msg(req->start, req->parsed-req->start,
01232                                                                         &con->rcv, con);
01233                                 
01234                         if (unlikely(ret < 0)) {
01235                                 *req->parsed=c;
01236                                 resp=CONN_ERROR;
01237                                 goto end_req;
01238                         }
01239                         *req->parsed=c;
01240                         
01241                         /* prepare for next request */
01242                         size=req->pos-req->parsed;
01243                         req->start=req->buf;
01244                         req->body=0;
01245                         req->error=TCP_REQ_OK;
01246                         req->state=H_SKIP_EMPTY;
01247                         req->flags=0;
01248                         req->content_len=0;
01249                         req->bytes_to_go=0;
01250                         req->pos=req->buf+size;
01251                         
01252                         if (unlikely(size)){ 
01253                                 memmove(req->buf, req->parsed, size);
01254                                 req->parsed=req->buf; /* fix req->parsed after using it */
01255 #ifdef EXTRA_DEBUG
01256                                 DBG("tcp_read_req: preparing for new request, kept %ld"
01257                                                 " bytes\n", size);
01258 #endif
01259                                 /*if we still have some unparsed bytes, try to parse them too*/
01260                                 goto again;
01261                         } else if (unlikely(con->state==S_CONN_EOF)){
01262                                 DBG( "tcp_read_req: EOF after reading complete request\n");
01263                                 resp=CONN_EOF;
01264                         }
01265                         req->parsed=req->buf; /* fix req->parsed */
01266                 }
01267                 
01268                 
01269         end_req:
01270                 if (likely(bytes_read)) *bytes_read=total_bytes;
01271                 return resp;
01272 }
01273 
01274 
01275 
01276 void release_tcpconn(struct tcp_connection* c, long state, int unix_sock)
01277 {
01278         long response[2];
01279         
01280                 DBG( "releasing con %p, state %ld, fd=%d, id=%d\n",
01281                                 c, state, c->fd, c->id);
01282                 DBG(" extra_data %p\n", c->extra_data);
01283                 /* release req & signal the parent */
01284                 c->reader_pid=0; /* reset it */
01285                 if (c->fd!=-1){
01286                         close(c->fd);
01287                         c->fd=-1;
01288                 }
01289                 /* errno==EINTR, EWOULDBLOCK a.s.o todo */
01290                 response[0]=(long)c;
01291                 response[1]=state;
01292                 
01293                 if (tsend_stream(unix_sock, (char*)response, sizeof(response), -1)<=0)
01294                         LOG(L_ERR, "ERROR: release_tcpconn: tsend_stream failed\n");
01295 }
01296 
01297 
01298 
01299 static ticks_t tcpconn_read_timeout(ticks_t t, struct timer_ln* tl, void* data)
01300 {
01301         struct tcp_connection *c;
01302         
01303         c=(struct tcp_connection*)data; 
01304         /* or (struct tcp...*)(tl-offset(c->timer)) */
01305         
01306         if (likely(!(c->state<0) && TICKS_LT(t, c->timeout))){
01307                 /* timeout extended, exit */
01308                 return (ticks_t)(c->timeout - t);
01309         }
01310         /* if conn->state is ERROR or BAD => force timeout too */
01311         if (unlikely(io_watch_del(&io_w, c->fd, -1, IO_FD_CLOSING)<0)){
01312                 LOG(L_ERR, "ERROR: tcpconn_read_timeout: io_watch_del failed for %p"
01313                                         " id %d fd %d, state %d, flags %x, main fd %d\n",
01314                                         c, c->id, c->fd, c->state, c->flags, c->s);
01315         }
01316         tcpconn_listrm(tcp_conn_lst, c, c_next, c_prev);
01317         release_tcpconn(c, (c->state<0)?CONN_ERROR:CONN_RELEASE, tcpmain_sock);
01318         
01319         return 0;
01320 }
01321 
01322 
01323 
01324 /* handle io routine, based on the fd_map type
01325  * (it will be called from io_wait_loop* )
01326  * params:  fm  - pointer to a fd hash entry
01327  *          idx - index in the fd_array (or -1 if not known)
01328  * return: -1 on error, or when we are not interested any more on reads
01329  *            from this fd (e.g.: we are closing it )
01330  *          0 on EAGAIN or when by some other way it is known that no more 
01331  *            io events are queued on the fd (the receive buffer is empty).
01332  *            Usefull to detect when there are no more io events queued for
01333  *            sigio_rt, epoll_et, kqueue.
01334  *         >0 on successfull read from the fd (when there might be more io
01335  *            queued -- the receive buffer might still be non-empty)
01336  */
01337 inline static int handle_io(struct fd_map* fm, short events, int idx)
01338 {       
01339         int ret;
01340         int n;
01341         int read_flags;
01342         struct tcp_connection* con;
01343         int s;
01344         long resp;
01345         ticks_t t;
01346         
01347         /* update the local config */
01348         cfg_update();
01349         
01350         switch(fm->type){
01351                 case F_TCPMAIN:
01352 again:
01353                         ret=n=receive_fd(fm->fd, &con, sizeof(con), &s, 0);
01354                         DBG("received n=%d con=%p, fd=%d\n", n, con, s);
01355                         if (unlikely(n<0)){
01356                                 if (errno == EWOULDBLOCK || errno == EAGAIN){
01357                                         ret=0;
01358                                         break;
01359                                 }else if (errno == EINTR) goto again;
01360                                 else{
01361                                         LOG(L_CRIT,"BUG: tcp_receive: handle_io: read_fd: %s \n",
01362                                                         strerror(errno));
01363                                                 abort(); /* big error*/
01364                                 }
01365                         }
01366                         if (unlikely(n==0)){
01367                                 LOG(L_ERR, "WARNING: tcp_receive: handle_io: 0 bytes read\n");
01368                                 goto error;
01369                         }
01370                         if (unlikely(con==0)){
01371                                         LOG(L_CRIT, "BUG: tcp_receive: handle_io null pointer\n");
01372                                         goto error;
01373                         }
01374                         con->fd=s;
01375                         if (unlikely(s==-1)) {
01376                                 LOG(L_ERR, "ERROR: tcp_receive: handle_io: read_fd:"
01377                                                                         "no fd read\n");
01378                                 goto con_error;
01379                         }
01380                         con->reader_pid=my_pid();
01381                         if (unlikely(con==tcp_conn_lst)){
01382                                 LOG(L_CRIT, "BUG: tcp_receive: handle_io: duplicate"
01383                                                         " connection received: %p, id %d, fd %d, refcnt %d"
01384                                                         " state %d (n=%d)\n", con, con->id, con->fd,
01385                                                         atomic_get(&con->refcnt), con->state, n);
01386                                 goto con_error;
01387                                 break; /* try to recover */
01388                         }
01389                         if (unlikely(con->state==S_CONN_BAD)){
01390                                 LOG(L_WARN, "WARNING: tcp_receive: handle_io: received an"
01391                                                         " already bad connection: %p id %d refcnt %d\n",
01392                                                         con, con->id, atomic_get(&con->refcnt));
01393                                 goto con_error;
01394                         }
01395                         /* if we received the fd there is most likely data waiting to
01396                          * be read => process it first to avoid extra sys calls */
01397                         read_flags=((con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)) &&
01398                                                 !(con->flags & F_CONN_OOB_DATA))? RD_CONN_FORCE_EOF
01399                                                 :0;
01400 #ifdef USE_TLS
01401 repeat_1st_read:
01402 #endif /* USE_TLS */
01403                         resp=tcp_read_req(con, &n, &read_flags);
01404                         if (unlikely(resp<0)){
01405                                 /* some error occured, but on the new fd, not on the tcp
01406                                  * main fd, so keep the ret value */
01407                                 if (unlikely(resp!=CONN_EOF))
01408                                         con->state=S_CONN_BAD;
01409                                 release_tcpconn(con, resp, tcpmain_sock);
01410                                 break;
01411                         }
01412 #ifdef USE_TLS
01413                         /* repeat read if requested (for now only tls might do this) */
01414                         if (unlikely(read_flags & RD_CONN_REPEAT_READ))
01415                                 goto repeat_1st_read;
01416 #endif /* USE_TLS */
01417                         
01418                         /* must be before io_watch_add, io_watch_add might catch some
01419                          * already existing events => might call handle_io and
01420                          * handle_io might decide to del. the new connection =>
01421                          * must be in the list */
01422                         tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev);
01423                         t=get_ticks_raw();
01424                         con->timeout=t+S_TO_TICKS(TCP_CHILD_TIMEOUT);
01425                         /* re-activate the timer */
01426                         con->timer.f=tcpconn_read_timeout;
01427                         local_timer_reinit(&con->timer);
01428                         local_timer_add(&tcp_reader_ltimer, &con->timer,
01429                                                                 S_TO_TICKS(TCP_CHILD_TIMEOUT), t);
01430                         if (unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con)<0)){
01431                                 LOG(L_CRIT, "ERROR: tcpconn_receive: handle_io: io_watch_add "
01432                                                         "failed for %p id %d fd %d, state %d, flags %x,"
01433                                                         " main fd %d, refcnt %d\n",
01434                                                         con, con->id, con->fd, con->state, con->flags,
01435                                                         con->s, atomic_get(&con->refcnt));
01436                                 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
01437                                 local_timer_del(&tcp_reader_ltimer, &con->timer);
01438                                 goto con_error;
01439                         }
01440                         break;
01441                 case F_TCPCONN:
01442                         con=(struct tcp_connection*)fm->data;
01443                         if (unlikely(con->state==S_CONN_BAD)){
01444                                 resp=CONN_ERROR;
01445                                 if (!(con->send_flags.f & SND_F_CON_CLOSE))
01446                                         LOG(L_WARN, "WARNING: tcp_receive: handle_io: F_TCPCONN"
01447                                                         " connection marked as bad: %p id %d refcnt %d\n",
01448                                                         con, con->id, atomic_get(&con->refcnt));
01449                                 goto read_error;
01450                         }
01451                         read_flags=((
01452 #ifdef POLLRDHUP
01453                                                 (events & POLLRDHUP) |
01454 #endif /* POLLRDHUP */
01455                                                 (events & (POLLHUP|POLLERR)) |
01456                                                         (con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)))
01457                                                 && !(events & POLLPRI))? RD_CONN_FORCE_EOF: 0;
01458 #ifdef USE_TLS
01459 repeat_read:
01460 #endif /* USE_TLS */
01461                         resp=tcp_read_req(con, &ret, &read_flags);
01462                         if (unlikely(resp<0)){
01463 read_error:
01464                                 ret=-1; /* some error occured */
01465                                 if (unlikely(io_watch_del(&io_w, con->fd, idx,
01466                                                                                         IO_FD_CLOSING) < 0)){
01467                                         LOG(L_CRIT, "ERROR: tcpconn_receive: handle_io: "
01468                                                         "io_watch_del failed for %p id %d fd %d,"
01469                                                         " state %d, flags %x, main fd %d, refcnt %d\n",
01470                                                         con, con->id, con->fd, con->state,
01471                                                         con->flags, con->s, atomic_get(&con->refcnt));
01472                                 }
01473                                 tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
01474                                 local_timer_del(&tcp_reader_ltimer, &con->timer);
01475                                 if (unlikely(resp!=CONN_EOF))
01476                                         con->state=S_CONN_BAD;
01477                                 release_tcpconn(con, resp, tcpmain_sock);
01478                         }else{
01479 #ifdef USE_TLS
01480                                 if (unlikely(read_flags & RD_CONN_REPEAT_READ))
01481                                                 goto repeat_read;
01482 #endif /* USE_TLS */
01483                                 /* update timeout */
01484                                 con->timeout=get_ticks_raw()+S_TO_TICKS(TCP_CHILD_TIMEOUT);
01485                                 /* ret= 0 (read the whole socket buffer) if short read & 
01486                                  *  !POLLPRI,  bytes read otherwise */
01487                                 ret&=(((read_flags & RD_CONN_SHORT_READ) &&
01488                                                 !(events & POLLPRI)) - 1);
01489                         }
01490                         break;
01491                 case F_NONE:
01492                         LOG(L_CRIT, "BUG: handle_io: empty fd map %p (%d): "
01493                                                 "{%d, %d, %p}\n", fm, (int)(fm-io_w.fd_hash),
01494                                                 fm->fd, fm->type, fm->data);
01495                         goto error;
01496                 default:
01497                         LOG(L_CRIT, "BUG: handle_io: uknown fd type %d\n", fm->type); 
01498                         goto error;
01499         }
01500         
01501         return ret;
01502 con_error:
01503         con->state=S_CONN_BAD;
01504         release_tcpconn(con, CONN_ERROR, tcpmain_sock);
01505         return ret;
01506 error:
01507         return -1;
01508 }
01509 
01510 
01511 
01512 inline static void tcp_reader_timer_run(void)
01513 {
01514         ticks_t ticks;
01515         
01516         ticks=get_ticks_raw();
01517         if (unlikely((ticks-tcp_reader_prev_ticks)<TCPCONN_TIMEOUT_MIN_RUN))
01518                 return;
01519         tcp_reader_prev_ticks=ticks;
01520         local_timer_run(&tcp_reader_ltimer, ticks);
01521 }
01522 
01523 
01524 
01525 void tcp_receive_loop(int unix_sock)
01526 {
01527         
01528         /* init */
01529         tcpmain_sock=unix_sock; /* init com. socket */
01530         if (init_io_wait(&io_w, get_max_open_fds(), tcp_poll_method)<0)
01531                 goto error;
01532         tcp_reader_prev_ticks=get_ticks_raw();
01533         if (init_local_timer(&tcp_reader_ltimer, get_ticks_raw())!=0)
01534                 goto error;
01535         /* add the unix socket */
01536         if (io_watch_add(&io_w, tcpmain_sock, POLLIN,  F_TCPMAIN, 0)<0){
01537                 LOG(L_CRIT, "ERROR: tcp_receive_loop: init: failed to add socket "
01538                                                         " to the fd list\n");
01539                 goto error;
01540         }
01541 
01542         /* initialize the config framework */
01543         if (cfg_child_init()) goto error;
01544 
01545         /* main loop */
01546         switch(io_w.poll_method){
01547                 case POLL_POLL:
01548                                 while(1){
01549                                         io_wait_loop_poll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
01550                                         tcp_reader_timer_run();
01551                                 }
01552                                 break;
01553 #ifdef HAVE_SELECT
01554                 case POLL_SELECT:
01555                         while(1){
01556                                 io_wait_loop_select(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
01557                                 tcp_reader_timer_run();
01558                         }
01559                         break;
01560 #endif
01561 #ifdef HAVE_SIGIO_RT
01562                 case POLL_SIGIO_RT:
01563                         while(1){
01564                                 io_wait_loop_sigio_rt(&io_w, TCP_CHILD_SELECT_TIMEOUT);
01565                                 tcp_reader_timer_run();
01566                         }
01567                         break;
01568 #endif
01569 #ifdef HAVE_EPOLL
01570                 case POLL_EPOLL_LT:
01571                         while(1){
01572                                 io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
01573                                 tcp_reader_timer_run();
01574                         }
01575                         break;
01576                 case POLL_EPOLL_ET:
01577                         while(1){
01578                                 io_wait_loop_epoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 1);
01579                                 tcp_reader_timer_run();
01580                         }
01581                         break;
01582 #endif
01583 #ifdef HAVE_KQUEUE
01584                 case POLL_KQUEUE:
01585                         while(1){
01586                                 io_wait_loop_kqueue(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
01587                                 tcp_reader_timer_run();
01588                         }
01589                         break;
01590 #endif
01591 #ifdef HAVE_DEVPOLL
01592                 case POLL_DEVPOLL:
01593                         while(1){
01594                                 io_wait_loop_devpoll(&io_w, TCP_CHILD_SELECT_TIMEOUT, 0);
01595                                 tcp_reader_timer_run();
01596                         }
01597                         break;
01598 #endif
01599                 default:
01600                         LOG(L_CRIT, "BUG: tcp_receive_loop: no support for poll method "
01601                                         " %s (%d)\n", 
01602                                         poll_method_name(io_w.poll_method), io_w.poll_method);
01603                         goto error;
01604         }
01605 error:
01606         destroy_io_wait(&io_w);
01607         LOG(L_CRIT, "ERROR: tcp_receive_loop: exiting...");
01608         exit(-1);
01609 }
01610 
01611 
01612 
01613 #ifdef USE_STUN
01614 int is_msg_complete(struct tcp_req* r)
01615 {
01616         if (TCP_REQ_HAS_CLEN(r)) {
01617                 r->state = H_STUN_FP;
01618                 return 0;
01619         }
01620         else {
01621                 /* STUN message is complete */
01622                 r->state = H_STUN_END;
01623                 r->flags |= F_TCP_REQ_COMPLETE |
01624                                         F_TCP_REQ_HAS_CLEN; /* hack to avoid error check */
01625                 return 1;
01626         }
01627 }
01628 #endif
01629 
01630 #endif /* USE_TCP */

Generated on Tue May 22 2012 13:10:17 for SIP Router by  doxygen 1.7.1