631d6d1e891629dc451fce1b2338e3fdb3f32703
[sip-router] / tcp_read.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 Fhg Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #ifdef USE_TCP
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <string.h>
33
34 #include <sys/select.h>
35
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39
40 #include <unistd.h>
41
42
43 #include "dprint.h"
44 #include "tcp_conn.h"
45 #include "pass_fd.h"
46 #include "globals.h"
47 #include "receive.h"
48 #include "timer.h"
49
50
51 #define q_memchr memchr
52
53 /* reads next available bytes
54  * return number of bytes read, 0 on EOF or -1 on error,
55  * sets also r->error */
56 int tcp_read(struct tcp_req *r, int fd)
57 {
58         int bytes_free, bytes_read;
59         
60         bytes_free=TCP_BUF_SIZE- (int)(r->pos - r->buf);
61         
62         if (bytes_free==0){
63                 LOG(L_ERR, "ERROR: tcp_read: buffer overrun, dropping\n");
64                 r->error=TCP_REQ_OVERRUN;
65                 return -1;
66         }
67 again:
68         bytes_read=read(fd, r->pos, bytes_free);
69
70         if(bytes_read==-1){
71                 if (errno == EWOULDBLOCK || errno == EAGAIN){
72                         return 0; /* nothing has been read */
73                 }else if (errno == EINTR) goto again;
74                 else{
75                         LOG(L_ERR, "ERROR: tcp_read: error reading: %s\n",strerror(errno));
76                         r->error=TCP_READ_ERROR;
77                         return -1;
78                 }
79         }
80         
81         r->pos+=bytes_read;
82         return bytes_read;
83 }
84
85
86
87 /* reads all headers (until double crlf), & parses the content-length header
88  * (WARNING: highly ineficient, tries to reuse receive_msg but will parse
89  *  all the header names twice [once here & once in receive_msg]; a more
90  *  speed eficient version will result in either major code duplication or
91  *  major changes to the receive code - TODO)
92  * returns number of bytes read & sets r->state & r->body
93  * when either r->body!=0 or r->state==H_BODY =>
94  * all headers have been read. It should be called in a while loop.
95  * returns < 0 if error or 0 if EOF */
96 int tcp_read_headers(struct tcp_req *r, int fd)
97 {
98         int bytes, remaining;
99         char *p;
100         
101         #define crlf_default_skip_case \
102                                         case '\n': \
103                                                 r->state=H_LF; \
104                                                 break; \
105                                         default: \
106                                                 r->state=H_SKIP
107         
108         #define content_len_beg_case \
109                                         case ' ': \
110                                         case '\t': \
111                                                 if (!r->has_content_len) r->state=H_STARTWS; \
112                                                 else r->state=H_SKIP; \
113                                                         /* not interested if we already found one */ \
114                                                 break; \
115                                         case 'C': \
116                                         case 'c': \
117                                                 if(!r->has_content_len) r->state=H_CONT_LEN1; \
118                                                 else r->state=H_SKIP; \
119                                                 break 
120                                                 
121         #define change_state(upper, lower, newstate)\
122                                         switch(*p){ \
123                                                 case upper: \
124                                                 case lower: \
125                                                         r->state=(newstate); break; \
126                                                 crlf_default_skip_case; \
127                                         }
128         
129         #define change_state_case(state0, upper, lower, newstate)\
130                                         case state0: \
131                                                           change_state(upper, lower, newstate); \
132                                                           p++; \
133                                                           break
134
135
136         
137         bytes=tcp_read(r, fd);
138         if (bytes<=0) return bytes;
139         p=r->parsed;
140         
141         while(p<r->pos && r->error==TCP_REQ_OK){
142                 switch(r->state){
143                         case H_BODY: /* read the body*/
144                                 remaining=r->pos-p;
145                                 if (remaining>r->bytes_to_go) remaining=r->bytes_to_go;
146                                 r->bytes_to_go-=remaining;
147                                 p+=remaining;
148                                 if (r->bytes_to_go==0){
149                                         r->complete=1;
150                                         goto skip;
151                                 }
152                                 break;
153                                 
154                         case H_SKIP:
155                                 /* find lf, we are in this state if we are not interested
156                                  * in anything till end of line*/
157                                 p=q_memchr(p, '\n', r->pos-r->parsed);
158                                 if (p){
159                                         p++;
160                                         r->state=H_LF;
161                                 }else{
162                                         p=r->pos;
163                                 }
164                                 break;
165                                 
166                         case H_LF:
167                                 /* terminate on LF CR LF or LF LF */
168                                 switch (*p){
169                                         case '\r':
170                                                 r->state=H_LFCR;
171                                                 break;
172                                         case '\n':
173                                                 /* found LF LF */
174                                                 r->state=H_BODY;
175                                                 if (r->has_content_len){
176                                                         r->body=p+1;
177                                                         r->bytes_to_go=r->content_len;
178                                                         if (r->bytes_to_go==0){
179                                                                 r->complete=1;
180                                                                 goto skip;
181                                                         }
182                                                 }else{
183                                                         r->error=TCP_REQ_BAD_LEN;
184                                                 }
185                                                 break;
186                                         content_len_beg_case;
187                                         default: 
188                                                 r->state=H_SKIP;
189                                 }
190                                 p++;
191                                 break;
192                         case H_LFCR:
193                                 if (*p=='\n'){
194                                         /* found LF CR LF */
195                                         r->state=H_BODY;
196                                         if (r->has_content_len){
197                                                 r->body=p+1;
198                                                 r->bytes_to_go=r->content_len;
199                                                 if (r->bytes_to_go==0){
200                                                         r->complete=1;
201                                                         goto skip;
202                                                 }
203                                         }else{
204                                                 r->error=TCP_REQ_BAD_LEN;
205                                         }
206                                 }else r->state=H_SKIP;
207                                 p++;
208                                 break;
209                                 
210                         case H_STARTWS:
211                                 switch (*p){
212                                         content_len_beg_case;
213                                         crlf_default_skip_case;
214                                 }
215                                 p++;
216                                 break;
217                         
218                         change_state_case(H_CONT_LEN1,  'O', 'o', H_CONT_LEN2);
219                         change_state_case(H_CONT_LEN2,  'N', 'n', H_CONT_LEN3);
220                         change_state_case(H_CONT_LEN3,  'T', 't', H_CONT_LEN4);
221                         change_state_case(H_CONT_LEN4,  'E', 'e', H_CONT_LEN5);
222                         change_state_case(H_CONT_LEN5,  'N', 'n', H_CONT_LEN6);
223                         change_state_case(H_CONT_LEN6,  'T', 't', H_CONT_LEN7);
224                         change_state_case(H_CONT_LEN7,  '-', '_', H_CONT_LEN8);
225                         change_state_case(H_CONT_LEN8,  'L', 'l', H_CONT_LEN9);
226                         change_state_case(H_CONT_LEN9,  'E', 'e', H_CONT_LEN10);
227                         change_state_case(H_CONT_LEN10, 'N', 'n', H_CONT_LEN11);
228                         change_state_case(H_CONT_LEN11, 'G', 'g', H_CONT_LEN12);
229                         change_state_case(H_CONT_LEN12, 'T', 't', H_CONT_LEN13);
230                         change_state_case(H_CONT_LEN13, 'H', 'h', H_L_COLON);
231                         
232                         case H_L_COLON:
233                                 switch(*p){
234                                         case ' ':
235                                         case '\t':
236                                                 break; /* skip space */
237                                         case ':':
238                                                 r->state=H_CONT_LEN_BODY;
239                                                 break;
240                                         crlf_default_skip_case;
241                                 };
242                                 p++;
243                                 break;
244                         
245                         case  H_CONT_LEN_BODY:
246                                 switch(*p){
247                                         case ' ':
248                                         case '\t':
249                                                 break; /* eat space */
250                                         case '0':
251                                         case '1':
252                                         case '2':
253                                         case '3':
254                                         case '4':
255                                         case '5':
256                                         case '6':
257                                         case '7':
258                                         case '8':
259                                         case '9':
260                                                 r->state=H_CONT_LEN_BODY_PARSE;
261                                                 r->content_len=(*p-'0');
262                                                 break;
263                                         /*FIXME: content lenght on different lines ! */
264                                         crlf_default_skip_case;
265                                 }
266                                 p++;
267                                 break;
268                                 
269                         case H_CONT_LEN_BODY_PARSE:
270                                 switch(*p){
271                                         case '0':
272                                         case '1':
273                                         case '2':
274                                         case '3':
275                                         case '4':
276                                         case '5':
277                                         case '6':
278                                         case '7':
279                                         case '8':
280                                                 r->content_len=r->content_len*10+(*p-'0');
281                                                 break;
282                                         case '\r':
283                                         case ' ':
284                                         case '\t': /* FIXME: check if line contains only WS */
285                                                 r->state=H_SKIP;
286                                                 r->has_content_len=1;
287                                                 break;
288                                         case '\n':
289                                                 /* end of line, parse succesfull */
290                                                 r->state=H_LF;
291                                                 r->has_content_len=1;
292                                                 break;
293                                         default:
294                                                 LOG(L_ERR, "ERROR: tcp_read_headers: bad "
295                                                                 "Content-Length header value, unexpected "
296                                                                 "char %c in state %d\n", *p, r->state);
297                                                 r->state=H_SKIP; /* try to find another?*/
298                                 }
299                                 p++;
300                                 break;
301                         
302                         default:
303                                 LOG(L_CRIT, "BUG: tcp_read_headers: unexpected state %d\n",
304                                                 r->state);
305                                 abort();
306                 }
307         }
308 skip:
309         r->parsed=p;
310         return bytes;
311 }
312
313
314
315 int tcp_read_req(struct tcp_connection* con)
316 {
317         int bytes;
318         int resp;
319         long size;
320         struct tcp_req* req;
321         int s;
322                 
323                 resp=CONN_RELEASE;
324                 s=con->fd;
325                 req=&con->req;
326                 if(req->complete==0 && req->error==TCP_REQ_OK){
327                         bytes=tcp_read_headers(req, s);
328                                                 /* if timeout state=0; goto end__req; */
329                         DBG("read= %d bytes, parsed=%d, state=%d, error=%d\n",
330                                         bytes, req->parsed-req->buf, req->state, req->error );
331                         if (bytes==-1){
332                                 LOG(L_ERR, "ERROR: tcp_read_req: error reading \n");
333                                 resp=CONN_ERROR;
334                                 goto end_req;
335                         }
336                         if (bytes==0){
337                                 DBG( "tcp_read_req: EOF\n");
338                                 resp=CONN_EOF;
339                                 goto end_req;
340                         }
341                 
342                 }
343                 if (req->error!=TCP_REQ_OK){
344                         LOG(L_ERR,"ERROR: tcp_read_req: bad request, state=%d, error=%d\n",
345                                         req->state, req->error);
346                         resp=CONN_ERROR;
347                         goto end_req;
348                 }
349                 if (req->complete){
350                         DBG("tcp_read_req: end of header part\n");
351                         DBG("tcp_read_req: headers:\n%.*s.\n",
352                                         req->body-req->buf, req->buf);
353                         if (req->has_content_len){
354                                 DBG("tcp_read_req: content-length= %d\n", req->content_len);
355                                 DBG("tcp_read_req: body:\n%.*s\n", req->content_len,req->body);
356                         }else{
357                                 req->error=TCP_REQ_BAD_LEN;
358                                 LOG(L_ERR, "ERROR: tcp_read_req: content length not present or"
359                                                 " unparsable\n");
360                                 resp=CONN_ERROR;
361                                 goto end_req;
362                         }
363                         /* if we are here everything is nice and ok*/
364                         resp=CONN_RELEASE;
365                         /* just for debugging use sendipv4 as receiving socket */
366                         DBG("calling receive_msg(%p, %d, )\n",
367                                         req->buf, (int)(req->parsed-req->buf));
368                         bind_address=sendipv4; /*&tcp_info[con->sock_idx];*/
369                         if (receive_msg(req->buf, req->parsed-req->buf, &con->su)<0){
370                                 resp=CONN_ERROR;
371                                 goto end_req;
372                         }
373                         
374                         /* prepare for next request */
375                         size=req->pos-req->body;
376                         if (size) memmove(req->buf, req->body, size);
377                         DBG("tcp_read_req: preparing for new request, kept %ld bytes\n",
378                                         size);
379                         req->pos=req->buf+size;
380                         req->parsed=req->buf;
381                         req->body=0;
382                         req->error=TCP_REQ_OK;
383                         req->state=H_STARTWS;
384                         req->complete=req->content_len=req->has_content_len=0;
385                         req->bytes_to_go=0;
386                         
387                 }
388                 
389                 
390         end_req:
391                 return resp;
392 }
393
394
395
396 void release_tcpconn(struct tcp_connection* c, long state, int unix_sock)
397 {
398         long response[2];
399         
400                 DBG( "releasing con %p, state %ld\n", c, state );
401                 /* release req & signal the parent */
402                 if (c->fd!=-1) close(c->fd);
403                 /* errno==EINTR, EWOULDBLOCK a.s.o todo */
404                 response[0]=(long)c;
405                 response[1]=state;
406                 write(unix_sock, response, sizeof(response));
407 }
408
409
410
411 void tcp_receive_loop(int unix_sock)
412 {
413         struct tcp_connection* list; /* list with connections in use */
414         struct tcp_connection* con;
415         struct tcp_connection* c_next;
416         int n;
417         int nfds;
418         int s;
419         long resp;
420         fd_set master_set;
421         fd_set sel_set;
422         int maxfd;
423         struct timeval timeout;
424         int ticks;
425         
426         
427         /* init */
428         list=con=0;
429         FD_ZERO(&master_set);
430         FD_SET(unix_sock, &master_set);
431         maxfd=unix_sock;
432         
433         /* listen on the unix socket for the fd */
434         for(;;){
435                         timeout.tv_sec=TCP_CHILD_SELECT_TIMEOUT;
436                         timeout.tv_usec=0;
437                         sel_set=master_set;
438                         nfds=select(maxfd+1, &sel_set, 0 , 0 , &timeout);
439                         if (nfds<0){
440                                 if (errno==EINTR) continue; /* just a signal */
441                                 /* errors */
442                                 LOG(L_ERR, "ERROR: tcp_receive_loop: select:(%d) %s\n", errno,
443                                         strerror(errno));
444                                 continue;
445                         }
446                         if (FD_ISSET(unix_sock, &sel_set)){
447                                 nfds--;
448                                 /* a new conn from "main" */
449                                 n=receive_fd(unix_sock, &con, sizeof(con), &s);
450                                 if (n<0){
451                                         if (errno == EWOULDBLOCK || errno == EAGAIN ||
452                                                         errno == EINTR){
453                                                 continue;
454                                         }else{
455                                                 LOG(L_CRIT,"BUG: tcp_receive_loop: read_fd: %s\n",
456                                                         strerror(errno));
457                                                 abort(); /* big error*/
458                                         }
459                                 }
460                                 if (n==0){
461                                         LOG(L_ERR, "WARNING: tcp_receive_loop: 0 bytes read\n");
462                                         continue;
463                                 }
464                                 con->fd=s;
465                                 DBG("received n=%d con=%p, fd=%d\n", n, con, s);
466                                 if (s==-1) {
467                                         LOG(L_ERR, "ERROR: tcp_receive_loop: read_fd:"
468                                                                         "no fd read\n");
469                                         resp=CONN_ERROR;
470                                         release_tcpconn(con, resp, unix_sock);
471                                 }
472                                 if (con==0){
473                                         LOG(L_ERR, "ERROR: tcp_receive_loop: null pointer\n");
474                                         resp=CONN_ERROR;
475                                         release_tcpconn(con, resp, unix_sock);
476                                 }
477                                 con->timeout=get_ticks()+TCP_CHILD_TIMEOUT;
478                                 FD_SET(s, &master_set);
479                                 if (maxfd<s) maxfd=s;
480                                 tcpconn_listadd(list, con, c_next, c_prev);
481                         }
482                         ticks=get_ticks();
483                         for (con=list; con ; con=c_next){
484                                 c_next=con->c_next; /* safe for removing*/
485                                 if (nfds && FD_ISSET(con->fd, &sel_set)){
486                                         nfds--;
487                                         resp=tcp_read_req(con);
488                                         if (resp<0){
489                                                 FD_CLR(con->fd, &master_set);
490                                                 tcpconn_listrm(list, con, c_next, c_prev);
491                                                 release_tcpconn(con, resp, unix_sock);
492                                         }else{
493                                                 /* update timeout */
494                                                 con->timeout=ticks+TCP_CHILD_TIMEOUT;
495                                         }
496                                 }else{
497                                         /* timeout */
498                                         if (con->timeout<=ticks){
499                                                 /* expired, return to "tcp main" */
500                                                 DBG("tcp_receive_loop: %p expired (%d, %d)\n",
501                                                                 con, con->timeout, ticks);
502                                                 resp=CONN_RELEASE;
503                                                 FD_CLR(con->fd, &master_set);
504                                                 tcpconn_listrm(list, con, c_next, c_prev);
505                                                 release_tcpconn(con, resp, unix_sock);
506                                         }
507                                 }
508                         }
509                 
510         }
511 }
512
513
514 #if 0
515 int main(int argv, char** argc )
516 {
517         printf("starting tests\n");
518         tcp_receive_loop();
519 }
520
521 #endif
522
523 #endif