- sock_lists completely re-organized
[sip-router] / tcp_main.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  * History:
29  * --------
30  *  2002-11-29  created by andrei
31  *  2002-12-11  added tcp_send (andrei)
32  *  2003-01-20  locking fixes, hashtables (andrei)
33  *  2003-02-20  s/lock_t/gen_lock_t/ to avoid a conflict on solaris (andrei)
34  *  2003-02-25  Nagle is disabled if -DDISABLE_NAGLE (andrei)
35  *  2003-03-29  SO_REUSEADDR before calling bind to allow
36  *              server restart, Nagle set on the (hopefuly) 
37  *              correct socket (jiri)
38  *  2003-03-31  always try to find the corresponding tcp listen socket for
39  *               a temp. socket and store in in *->bind_address: added
40  *               find_tcp_si, modified tcpconn_connect (andrei)
41  *  2003-04-14  set sockopts to TOS low delay (andrei)
42  *  2003-06-30  moved tcp new connect checking & handling to
43  *               handle_new_connect (andrei)
44  *  2003-07-09  tls_close called before closing the tcp connection (andrei)
45  *  2003-10-24  converted to the new socket_info lists (andrei)
46  */
47
48
49 #ifdef USE_TCP
50
51
52 #ifndef SHM_MEM
53 #error "shared memory support needed (add -DSHM_MEM to Makefile.defs)"
54 #endif
55
56
57 #include <sys/time.h>
58 #include <sys/types.h>
59 #include <sys/select.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/tcp.h>
65 #include <sys/uio.h>  /* writev*/
66 #include <netdb.h>
67
68 #include <unistd.h>
69
70 #include <errno.h>
71 #include <string.h>
72
73
74
75 #include "ip_addr.h"
76 #include "pass_fd.h"
77 #include "tcp_conn.h"
78 #include "globals.h"
79 #include "pt.h"
80 #include "locking.h"
81 #include "mem/mem.h"
82 #include "mem/shm_mem.h"
83 #include "timer.h"
84 #include "sr_module.h"
85 #include "tcp_server.h"
86 #include "tcp_init.h"
87 #ifdef USE_TLS
88 #include "tls/tls_server.h"
89 #endif
90
91
92
93
94 #define local_malloc pkg_malloc
95 #define local_free   pkg_free
96
97 #define MAX_TCP_CHILDREN 100
98
99 struct tcp_child{
100         pid_t pid;
101         int proc_no; /* ser proc_no, for debugging */
102         int unix_sock; /* unix sock fd, copied from pt*/
103         int busy;
104         int n_reqs; /* number of requests serviced so far */
105 };
106
107
108
109 /* connection hash table (after ip&port) */
110 struct tcp_connection** tcpconn_addr_hash=0;
111 /* connection hash table (after connection id) */
112 struct tcp_connection** tcpconn_id_hash=0;
113 gen_lock_t* tcpconn_lock=0;
114
115 struct tcp_child tcp_children[MAX_TCP_CHILDREN];
116 static int* connection_id=0; /*  unique for each connection, used for 
117                                                                 quickly finding the corresponding connection
118                                                                 for a reply */
119 int unix_tcp_sock;
120
121 int tcp_proto_no=-1; /* tcp protocol number as returned by getprotobyname */
122
123
124 struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
125                                                                         struct socket_info* ba, int type, 
126                                                                         int state)
127 {
128         struct tcp_connection *c;
129         
130         c=(struct tcp_connection*)shm_malloc(sizeof(struct tcp_connection));
131         if (c==0){
132                 LOG(L_ERR, "ERROR: tcpconn_new: mem. allocation failure\n");
133                 goto error;
134         }
135         c->s=sock;
136         c->fd=-1; /* not initialized */
137         if (lock_init(&c->write_lock)==0){
138                 LOG(L_ERR, "ERROR: tcpconn_new: init lock failed\n");
139                 goto error;
140         }
141         
142         c->rcv.src_su=*su;
143         
144         c->refcnt=0;
145         su2ip_addr(&c->rcv.src_ip, su);
146         c->rcv.src_port=su_getport(su);
147         c->rcv.bind_address=ba;
148         if (ba){
149                 c->rcv.dst_ip=ba->address;
150                 c->rcv.dst_port=ba->port_no;
151         }
152         print_ip("tcpconn_new: new tcp connection: ", &c->rcv.src_ip, "\n");
153         DBG(     "tcpconn_new: on port %d, type %d\n", c->rcv.src_port, type);
154         init_tcp_req(&c->req);
155         c->id=(*connection_id)++;
156         c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
157         c->rcv.proto_reserved2=0;
158         c->state=state;
159         c->extra_data=0;
160 #ifdef USE_TLS
161         if (type==PROTO_TLS){
162                 if (tls_tcpconn_init(c, sock)==-1) goto error;
163         }else
164 #endif /* USE_TLS*/
165         {
166                 c->type=PROTO_TCP;
167                 c->rcv.proto=PROTO_TCP;
168                 c->flags=0;
169                 c->timeout=get_ticks()+TCP_CON_TIMEOUT;
170         }
171                         
172                 
173         return c;
174         
175 error:
176         if (c) shm_free(c);
177         return 0;
178 }
179
180
181
182
183 struct socket_info* find_tcp_si(union sockaddr_union* s)
184 {
185         struct ip_addr ip;
186         struct socket_info* si;
187         
188         su2ip_addr(&ip, s);
189         for (si=tcp_listen; si; si=si->next)
190                 if (ip_addr_cmp(&ip, &si->address)){
191                         /* found it, we use first match */
192                         return si;
193                 }
194         return 0; /* no match */
195 }
196
197
198 struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
199 {
200         int s;
201         struct socket_info* si;
202         union sockaddr_union my_name;
203         socklen_t my_name_len;
204         int optval;
205 #ifdef DISABLE_NAGLE
206         int flag;
207 #endif
208
209         s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
210         if (s<0){
211                 LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
212                                 errno, strerror(errno));
213                 goto error;
214         }
215 #ifdef DISABLE_NAGLE
216         flag=1;
217         if ( (tcp_proto_no!=-1) && (setsockopt(s, tcp_proto_no , TCP_NODELAY,
218                                         &flag, sizeof(flag))<0) ){
219                 LOG(L_ERR, "ERROR: tcp_connect: could not disable Nagle: %s\n",
220                                 strerror(errno));
221         }
222 #endif
223         /* tos*/
224         optval=IPTOS_LOWDELAY;
225         if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval, sizeof(optval)) ==-1){
226                 LOG(L_WARN, "WARNING: tcpconn_connect: setsockopt tos: %s\n",
227                                 strerror(errno));
228                 /* continue since this is not critical */
229         }
230
231         if (connect(s, &server->s, sockaddru_len(*server))<0){
232                 LOG(L_ERR, "ERROR: tcpconn_connect: connect: (%d) %s\n",
233                                 errno, strerror(errno));
234                 goto error;
235         }
236         my_name_len=sizeof(my_name);
237         if (getsockname(s, &my_name.s, &my_name_len)!=0){
238                 LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
239                                 strerror(errno), errno);
240                 si=0; /* try to go on */
241         }
242         si=find_tcp_si(&my_name);
243         if (si==0){
244                 LOG(L_ERR, "ERROR: tcp_connect: could not find coresponding"
245                                 " listening socket, using default...\n");
246                 if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
247 #ifdef USE_IPV6
248                 else si=sendipv6_tcp;
249 #endif
250         }
251         return tcpconn_new(s, server, si, type, S_CONN_CONNECT);
252         /*FIXME: set sock idx! */
253 error:
254         return 0;
255 }
256
257
258
259 struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
260 {
261         unsigned hash;
262
263         if (c){
264                 TCPCONN_LOCK;
265                 /* add it at the begining of the list*/
266                 hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
267                 c->addr_hash=hash;
268                 tcpconn_listadd(tcpconn_addr_hash[hash], c, next, prev);
269                 hash=tcp_id_hash(c->id);
270                 c->id_hash=hash;
271                 tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev);
272                 TCPCONN_UNLOCK;
273                 DBG("tcpconn_add: hashes: %d, %d\n", c->addr_hash, c->id_hash);
274                 return c;
275         }else{
276                 LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n");
277                 return 0;
278         }
279 }
280
281
282 /* unsafe tcpconn_rm version (nolocks) */
283 void _tcpconn_rm(struct tcp_connection* c)
284 {
285         tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev);
286         tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
287         lock_destroy(&c->write_lock);
288 #ifdef USE_TLS
289         if (c->type==PROTO_TLS) tls_tcpconn_clean(c);
290 #endif
291         shm_free(c);
292 }
293
294
295
296 void tcpconn_rm(struct tcp_connection* c)
297 {
298         TCPCONN_LOCK;
299         tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev);
300         tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
301         TCPCONN_UNLOCK;
302         lock_destroy(&c->write_lock);
303 #ifdef USE_TLS
304         if ((c->type==PROTO_TLS)&&(c->extra_data)) tls_tcpconn_clean(c);
305 #endif
306         shm_free(c);
307 }
308
309
310 /* finds a connection, if id=0 uses the ip addr & port (host byte order)
311  * WARNING: unprotected (locks) use tcpconn_get unless you really
312  * know what you are doing */
313 struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port)
314 {
315
316         struct tcp_connection *c;
317         unsigned hash;
318         
319 #ifdef EXTRA_DEBUG
320         DBG("tcpconn_find: %d  port %d\n",id, port);
321         print_ip("tcpconn_find: ip ", ip, "\n");
322 #endif
323         if (id){
324                 hash=tcp_id_hash(id);
325                 for (c=tcpconn_id_hash[hash]; c; c=c->id_next){
326 #ifdef EXTRA_DEBUG
327                         DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port);
328                         print_ip("ip=", &c->rcv.src_ip, "\n");
329 #endif
330                         if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c;
331                 }
332         }else if (ip){
333                 hash=tcp_addr_hash(ip, port);
334                 for (c=tcpconn_addr_hash[hash]; c; c=c->next){
335 #ifdef EXTRA_DEBUG
336                         DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port);
337                         print_ip("ip=",&c->rcv.src_ip,"\n");
338 #endif
339                         if ( (c->state!=S_CONN_BAD) && (port==c->rcv.src_port) &&
340                                         (ip_addr_cmp(ip, &c->rcv.src_ip)) )
341                                 return c;
342                 }
343         }
344         return 0;
345 }
346
347
348
349 /* _tcpconn_find with locks and timeout */
350 struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
351                                                                         int timeout)
352 {
353         struct tcp_connection* c;
354         TCPCONN_LOCK;
355         c=_tcpconn_find(id, ip, port);
356         if (c){ 
357                         c->refcnt++;
358                         c->timeout=get_ticks()+timeout;
359         }
360         TCPCONN_UNLOCK;
361         return c;
362 }
363
364
365
366 void tcpconn_put(struct tcp_connection* c)
367 {
368         c->refcnt--; /* FIXME: atomic_dec */
369 }
370
371
372
373 /* finds a tcpconn & sends on it */
374 int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
375                                 int id)
376 {
377         struct tcp_connection *c;
378         struct ip_addr ip;
379         int port;
380         int fd;
381         long response[2];
382         int n;
383         
384         port=0;
385         if (to){
386                 su2ip_addr(&ip, to);
387                 port=su_getport(to);
388                 c=tcpconn_get(id, &ip, port, TCP_CON_SEND_TIMEOUT); 
389         }else if (id){
390                 c=tcpconn_get(id, 0, 0, TCP_CON_SEND_TIMEOUT);
391         }else{
392                 LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
393                 return -1;
394         }
395         
396         if (id){
397                 if (c==0) {
398                         if (to){
399                                 /* try again w/o id */
400                                 c=tcpconn_get(0, &ip, port, TCP_CON_SEND_TIMEOUT);
401                                 goto no_id;
402                         }else{
403                                 LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
404                                                 id);
405                                 return -1;
406                         }
407                 }else goto get_fd;
408         }
409 no_id:
410                 if (c==0){
411                         DBG("tcp_send: no open tcp connection found, opening new one\n");
412                         /* create tcp connection */
413                         if ((c=tcpconn_connect(to, type))==0){
414                                 LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
415                                 return -1;
416                         }
417                         c->refcnt++;
418                         fd=c->s;
419                         
420                         /* send the new tcpconn to "tcp main" */
421                         response[0]=(long)c;
422                         response[1]=CONN_NEW;
423                         n=write(unix_tcp_sock, response, sizeof(response));
424                         if (n<0){
425                                 LOG(L_ERR, "BUG: tcp_send: failed write: %s (%d)\n",
426                                                 strerror(errno), errno);
427                                 goto end;
428                         }       
429                         n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
430                         if (n<0){
431                                 LOG(L_ERR, "BUG: tcp_send: failed send_fd: %s (%d)\n",
432                                                 strerror(errno), errno);
433                                 goto end;
434                         }
435                         goto send_it;
436                 }
437 get_fd:
438                         /* todo: see if this is not the same process holding
439                          *  c  and if so send directly on c->fd */
440                         DBG("tcp_send: tcp connection found, acquiring fd\n");
441                         /* get the fd */
442                         response[0]=(long)c;
443                         response[1]=CONN_GET_FD;
444                         n=write(unix_tcp_sock, response, sizeof(response));
445                         if (n<0){
446                                 LOG(L_ERR, "BUG: tcp_send: failed to get fd(write):%s (%d)\n",
447                                                 strerror(errno), errno);
448                                 goto release_c;
449                         }
450                         DBG("tcp_send, c= %p, n=%d\n", c, n);
451                         n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd);
452                         if (n<0){
453                                 LOG(L_ERR, "BUG: tcp_send: failed to get fd(receive_fd):"
454                                                         " %s (%d)\n", strerror(errno), errno);
455                                 goto release_c;
456                         }
457                         DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
458                 
459         
460         
461 send_it:
462         DBG("tcp_send: sending...\n");
463         lock_get(&c->write_lock);
464 #ifdef USE_TLS
465         if (c->type==PROTO_TLS)
466                 n=tls_blocking_write(c, fd, buf, len);
467         else
468 #endif
469                 n=send(fd, buf, len,
470 #ifdef HAVE_MSG_NOSIGNAL
471                         MSG_NOSIGNAL
472 #else
473                         0
474 #endif
475                         );
476         lock_release(&c->write_lock);
477         DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, fd);
478         DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
479         if (n<0){
480                 if (errno==EINTR) goto send_it; /* interrupted write, try again*/
481                                                                                 /* keep the lock or lock/unlock again?*/
482                 LOG(L_ERR, "ERROR: tcpsend: failed to send, n=%d: %s (%d)\n",
483                                 n, strerror(errno), errno);
484                 /* error on the connection , mark it as bad and set 0 timeout */
485                 c->state=S_CONN_BAD;
486                 c->timeout=0;
487                 /* tell "main" it should drop this (optional it will t/o anyway?)*/
488                 response[0]=(long)c;
489                 response[1]=CONN_ERROR;
490                 n=write(unix_tcp_sock, response, sizeof(response));
491                 /* CONN_ERROR wil auto-dec refcnt => we must not call tcpconn_put !!*/
492                 if (n<0){
493                         LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n",
494                                         strerror(errno), errno);
495                 }
496                 close(fd);
497                 return n; /* error return, no tcpconn_put */
498         }
499 end:
500         close(fd);
501 release_c:
502         tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
503         return n;
504 }
505
506
507
508 /* very ineficient for now - FIXME*/
509 void tcpconn_timeout(fd_set* set)
510 {
511         struct tcp_connection *c, *next;
512         int ticks;
513         unsigned h;
514         int fd;
515         
516         
517         ticks=get_ticks();
518         TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */
519         for(h=0; h<TCP_ADDR_HASH_SIZE; h++){
520                 c=tcpconn_addr_hash[h];
521                 while(c){
522                         next=c->next;
523                         if ((c->refcnt==0) && (ticks>c->timeout)) {
524                                 DBG("tcpconn_timeout: timeout for hash=%d - %p (%d > %d)\n",
525                                                 h, c, ticks, c->timeout);
526                                 fd=c->s;
527 #ifdef USE_TLS
528                                 if (c->type==PROTO_TLS)
529                                         tls_close(c, fd);
530 #endif
531                                 _tcpconn_rm(c);
532                                 if (fd>0) {
533                                         FD_CLR(fd, set);
534                                         close(fd);
535                                 }
536                         }
537                         c=next;
538                 }
539         }
540         TCPCONN_UNLOCK;
541 }
542
543
544
545 int tcp_init(struct socket_info* sock_info)
546 {
547         union sockaddr_union* addr;
548         int optval;
549 #ifdef DISABLE_NAGLE
550         int flag;
551         struct protoent* pe;
552
553         if (tcp_proto_no==-1){ /* if not already set */
554                 pe=getprotobyname("tcp");
555                 if (pe==0){
556                         LOG(L_ERR, "ERROR: tcp_init: could not get TCP protocol number\n");
557                         tcp_proto_no=-1;
558                 }else{
559                         tcp_proto_no=pe->p_proto;
560                 }
561         }
562 #endif
563         
564         addr=&sock_info->su;
565         sock_info->proto=PROTO_TCP;
566         if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
567                 LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n");
568                 goto error;
569         }
570         sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0);
571         if (sock_info->socket==-1){
572                 LOG(L_ERR, "ERROR: tcp_init: socket: %s\n", strerror(errno));
573                 goto error;
574         }
575 #ifdef DISABLE_NAGLE
576         flag=1;
577         if ( (tcp_proto_no!=-1) &&
578                  (setsockopt(sock_info->socket, tcp_proto_no , TCP_NODELAY,
579                                          &flag, sizeof(flag))<0) ){
580                 LOG(L_ERR, "ERROR: tcp_init: could not disable Nagle: %s\n",
581                                 strerror(errno));
582         }
583 #endif
584
585
586 #if  !defined(TCP_DONT_REUSEADDR) 
587         /* Stevens, "Network Programming", Section 7.5, "Generic Socket
588      * Options": "...server started,..a child continues..on existing
589          * connection..listening server is restarted...call to bind fails
590          * ... ALL TCP servers should specify the SO_REUSEADDRE option 
591          * to allow the server to be restarted in this situation
592          *
593          * Indeed, without this option, the server can't restart.
594          *   -jiri
595          */
596         optval=1;
597         if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR,
598                                 (void*)&optval, sizeof(optval))==-1) {
599                 LOG(L_ERR, "ERROR: tcp_init: setsockopt %s\n",
600                         strerror(errno));
601                 goto error;
602         }
603 #endif
604         /* tos */
605         optval=IPTOS_LOWDELAY;
606         if (setsockopt(sock_info->socket, IPPROTO_IP, IP_TOS, (void*)&optval, 
607                                 sizeof(optval)) ==-1){
608                 LOG(L_WARN, "WARNING: tcp_init: setsockopt tos: %s\n", strerror(errno));
609                 /* continue since this is not critical */
610         }
611         if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){
612                 LOG(L_ERR, "ERROR: tcp_init: bind(%x, %p, %d) on %s: %s\n",
613                                 sock_info->socket, &addr->s, 
614                                 sockaddru_len(*addr),
615                                 sock_info->address_str.s,
616                                 strerror(errno));
617                 goto error;
618         }
619         if (listen(sock_info->socket, 10)==-1){
620                 LOG(L_ERR, "ERROR: tcp_init: listen(%x, %p, %d) on %s: %s\n",
621                                 sock_info->socket, &addr->s, 
622                                 sockaddru_len(*addr),
623                                 sock_info->address_str.s,
624                                 strerror(errno));
625                 goto error;
626         }
627         
628         return 0;
629 error:
630         if (sock_info->socket!=-1){
631                 close(sock_info->socket);
632                 sock_info->socket=-1;
633         }
634         return -1;
635 }
636
637
638
639 static int send2child(struct tcp_connection* tcpconn)
640 {
641         int i;
642         int min_busy;
643         int idx;
644         
645         min_busy=tcp_children[0].busy;
646         idx=0;
647         for (i=0; i<tcp_children_no; i++){
648                 if (!tcp_children[i].busy){
649                         idx=i;
650                         min_busy=0;
651                         break;
652                 }else if (min_busy>tcp_children[i].busy){
653                         min_busy=tcp_children[i].busy;
654                         idx=i;
655                 }
656         }
657         
658         tcp_children[idx].busy++;
659         tcp_children[idx].n_reqs++;
660         tcpconn->refcnt++;
661         if (min_busy){
662                 LOG(L_WARN, "WARNING: send2child:no free tcp receiver, "
663                                 " connection passed to the least busy one (%d)\n",
664                                 min_busy);
665         }
666         DBG("send2child: to tcp child %d %d(%d), %p\n", idx, 
667                                         tcp_children[idx].proc_no,
668                                         tcp_children[idx].pid, tcpconn);
669         send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn),
670                         tcpconn->s);
671         
672         return 0; /* just to fix a warning*/
673 }
674
675
676 /* handle a new connection, called internally by tcp_main_loop */
677 static inline void handle_new_connect(struct socket_info* si,
678                                                                                 fd_set* sel_set, int* n)
679 {
680         union sockaddr_union su;
681         struct tcp_connection* tcpconn;
682         socklen_t su_len;
683         int new_sock;
684         
685         if ((FD_ISSET(si->socket, sel_set))){
686                 /* got a connection on r */
687                 su_len=sizeof(su);
688                 new_sock=accept(si->socket, &(su.s), &su_len);
689                 (*n)--;
690                 if (new_sock<0){
691                         LOG(L_ERR,  "WARNING: tcp_main_loop: error while accepting"
692                                         " connection(%d): %s\n", errno, strerror(errno));
693                         return;
694                 }
695                 
696                 /* add socket to list */
697                 tcpconn=tcpconn_new(new_sock, &su, si, si->proto, S_CONN_ACCEPT);
698                 if (tcpconn){
699                         tcpconn_add(tcpconn);
700                         DBG("tcp_main_loop: new connection: %p %d\n",
701                                 tcpconn, tcpconn->s);
702                         /* pass it to a child */
703                         if(send2child(tcpconn)<0){
704                                 LOG(L_ERR,"ERROR: tcp_main_loop: no children "
705                                                 "available\n");
706                                 TCPCONN_LOCK;
707                                 if (tcpconn->refcnt==0){
708                                         close(tcpconn->s);
709                                         _tcpconn_rm(tcpconn);
710                                 }else tcpconn->timeout=0; /* force expire */
711                                 TCPCONN_UNLOCK;
712                         }
713                 }
714         }
715 }
716
717
718 void tcp_main_loop()
719 {
720         int r;
721         int n;
722         fd_set master_set;
723         fd_set sel_set;
724         int maxfd;
725         struct tcp_connection* tcpconn;
726         unsigned h;
727         long response[2];
728         int cmd;
729         int bytes;
730         struct timeval timeout;
731         int fd;
732         struct socket_info* si;
733
734         /*init */
735         maxfd=0;
736         FD_ZERO(&master_set);
737         /* set all the listen addresses */
738         for (si=tcp_listen; si; si=si->next){
739                 if ((si->proto==PROTO_TCP) &&(si->socket!=-1)){
740                         FD_SET(si->socket, &master_set);
741                         if (si->socket>maxfd) maxfd=si->socket;
742                 }else{
743                         LOG(L_CRIT, "BUG: tcp_main_loop: non tcp address in tcp_listen\n");
744                 }
745         }
746 #ifdef USE_TLS
747         if (!tls_disable){
748                 for (si=tls_listen; si; si=si->next){
749                         if ((si->proto==PROTO_TLS) && (si->socket!=-1)){
750                                 FD_SET(si->socket, &master_set);
751                                 if (si->socket>maxfd) maxfd=si->socket;
752                         }else{
753                         LOG(L_CRIT, "BUG: tcp_main_loop: non tls address in tls_listen\n");
754                 }
755         }
756 #endif
757         /* set all the unix sockets used for child comm */
758         for (r=1; r<process_no; r++){
759                 if (pt[r].unix_sock>0){ /* we can't have 0, we never close it!*/
760                         FD_SET(pt[r].unix_sock, &master_set);
761                         if (pt[r].unix_sock>maxfd) maxfd=pt[r].unix_sock;
762                 }
763         }
764         
765         
766         /* main loop*/
767         
768         while(1){
769                 sel_set=master_set;
770                 timeout.tv_sec=TCP_MAIN_SELECT_TIMEOUT;
771                 timeout.tv_usec=0;
772                 n=select(maxfd+1, &sel_set, 0 ,0 , &timeout);
773                 if (n<0){
774                         if (errno==EINTR) continue; /* just a signal */
775                         /* errors */
776                         LOG(L_ERR, "ERROR: tcp_main_loop: select:(%d) %s\n", errno,
777                                         strerror(errno));
778                         n=0;
779                 }
780                 
781                 for (si=tcp_listen; si && n; si=si->next)
782                         handle_new_connect(si, &sel_set, &n);
783 #ifdef USE_TLS
784                         if (!tls_disable)
785                                 for (si=tls_listen; si && n; si=si->next)
786                                         handle_new_connect(si, &sel_set, &n);
787 #endif
788                 
789                 /* check all the read fds (from the tcpconn_addr_hash ) */
790                 for (h=0; h<TCP_ADDR_HASH_SIZE; h++){
791                         for(tcpconn=tcpconn_addr_hash[h]; tcpconn && n; 
792                                         tcpconn=tcpconn->next){
793                                 if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
794                                         /* new data available */
795                                         n--;
796                                         /* pass it to child, so remove it from select list */
797                                         DBG("tcp_main_loop: data available on %p [h:%d] %d\n",
798                                                         tcpconn, h, tcpconn->s);
799                                         FD_CLR(tcpconn->s, &master_set);
800                                         if (send2child(tcpconn)<0){
801                                                 LOG(L_ERR,"ERROR: tcp_main_loop: no "
802                                                                         "children available\n");
803                                                 TCPCONN_LOCK;
804                                                 if (tcpconn->refcnt==0){
805                                                         fd=tcpconn->s;
806                                                         _tcpconn_rm(tcpconn);
807                                                         close(fd);
808                                                 }else tcpconn->timeout=0; /* force expire*/
809                                                 TCPCONN_UNLOCK;
810                                         }
811                                 }
812                         }
813                 }
814                 /* check unix sockets & listen | destroy connections */
815                 /* start from 1, the "main" process does not transmit anything*/
816                 for (r=1; r<process_no && n; r++){
817                         if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
818                                 /* (we can't have a fd==0, 0 is never closed )*/
819                                 n--;
820                                 /* errno==EINTR !!! TODO*/
821 read_again:
822                                 bytes=read(pt[r].unix_sock, response, sizeof(response));
823                                 if (bytes==0){
824                                         /* EOF -> bad, child has died */
825                                         LOG(L_CRIT, "BUG: tcp_main_loop: dead child %d\n", r);
826                                         /* don't listen on it any more */
827                                         FD_CLR(pt[r].unix_sock, &master_set);
828                                         /*exit(-1);*/
829                                         continue;
830                                 }else if (bytes<0){
831                                         if (errno==EINTR) goto read_again;
832                                         else{
833                                                 LOG(L_CRIT, "ERROR: tcp_main_loop: read from child: "
834                                                                 " %s\n", strerror(errno));
835                                                 /* try to continue ? */
836                                                 continue;
837                                         }
838                                 }
839                                         
840                                 DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n",
841                                                 response[0], response[1], r, pt[r].pid);
842                                 cmd=response[1];
843                                 switch(cmd){
844                                         case CONN_RELEASE:
845                                                 if (pt[r].idx>=0){
846                                                         tcp_children[pt[r].idx].busy--;
847                                                 }else{
848                                                         LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
849                                                 }
850                                                 tcpconn=(struct tcp_connection*)response[0];
851                                                 if (tcpconn){
852                                                                 if (tcpconn->state==S_CONN_BAD) 
853                                                                         goto tcpconn_destroy;
854                                                                 FD_SET(tcpconn->s, &master_set);
855                                                                 if (maxfd<tcpconn->s) maxfd=tcpconn->s;
856                                                                 /* update the timeout*/
857                                                                 tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
858                                                                 tcpconn_put(tcpconn);
859                                                                 DBG("tcp_main_loop: %p refcnt= %d\n", 
860                                                                         tcpconn, tcpconn->refcnt);
861                                                 }
862                                                 break;
863                                         case CONN_ERROR:
864                                         case CONN_DESTROY:
865                                         case CONN_EOF:
866                                                 /* WARNING: this will auto-dec. refcnt! */
867                                                 if (pt[r].idx>=0){
868                                                         tcp_children[pt[r].idx].busy--;
869                                                 }else{
870                                                         LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
871                                                 }
872                                                 tcpconn=(struct tcp_connection*)response[0];
873                                                 if (tcpconn){
874                                                         if (tcpconn->s!=-1)
875                                                                 FD_CLR(tcpconn->s, &master_set);
876                 tcpconn_destroy:
877                                                         TCPCONN_LOCK; /*avoid races w/ tcp_send*/
878                                                         tcpconn->refcnt--;
879                                                         if (tcpconn->refcnt==0){ 
880                                                                 DBG("tcp_main_loop: destroying connection\n");
881                                                                 fd=tcpconn->s;
882 #ifdef USE_TLS
883                                                                 if (tcpconn->type==PROTO_TLS)
884                                                                         tls_close(tcpconn, fd);
885 #endif
886                                                                 _tcpconn_rm(tcpconn);
887                                                                 close(fd);
888                                                         }else{
889                                                                 /* force timeout */
890                                                                 tcpconn->timeout=0;
891                                                                 tcpconn->state=S_CONN_BAD;
892                                                                 DBG("tcp_main_loop: delaying ...\n");
893                                                                 
894                                                         }
895                                                         TCPCONN_UNLOCK;
896                                                 }
897                                                 break;
898                                         case CONN_GET_FD:
899                                                 /* send the requested FD  */
900                                                 tcpconn=(struct tcp_connection*)response[0];
901                                                 /* WARNING: take care of setting refcnt properly to
902                                                  * avoid race condition */
903                                                 if (tcpconn){
904                                                         send_fd(pt[r].unix_sock, &tcpconn,
905                                                                         sizeof(tcpconn), tcpconn->s);
906                                                 }else{
907                                                         LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
908                                                 }
909                                                 break;
910                                         case CONN_NEW:
911                                                 /* update the fd in the requested tcpconn*/
912                                                 tcpconn=(struct tcp_connection*)response[0];
913                                                 /* WARNING: take care of setting refcnt properly to
914                                                  * avoid race condition */
915                                                 if (tcpconn){
916                                                         receive_fd(pt[r].unix_sock, &tcpconn,
917                                                                                 sizeof(tcpconn), &tcpconn->s);
918                                                         /* add tcpconn to the list*/
919                                                         tcpconn_add(tcpconn);
920                                                         FD_SET(tcpconn->s, &master_set);
921                                                         if (maxfd<tcpconn->s) maxfd=tcpconn->s;
922                                                         /* update the timeout*/
923                                                         tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
924                                                 }else{
925                                                         LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
926                                                 }
927                                                 break;
928                                         default:
929                                                         LOG(L_CRIT, "BUG: tcp_main_loop: unknown cmd %d\n",
930                                                                         cmd);
931                                 }
932                         }
933                 }
934                 
935                 /* remove old connections */
936                 tcpconn_timeout(&master_set);
937         
938         }
939 }
940
941
942
943 int init_tcp()
944 {
945         /* init lock */
946         tcpconn_lock=lock_alloc();
947         if (tcpconn_lock==0){
948                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc lock\n");
949                 goto error;
950         }
951         if (lock_init(tcpconn_lock)==0){
952                 LOG(L_CRIT, "ERROR: init_tcp: could not init lock\n");
953                 lock_dealloc((void*)tcpconn_lock);
954                 tcpconn_lock=0;
955                 goto error;
956         }
957         /* init globals */
958         connection_id=(int*)shm_malloc(sizeof(int));
959         if (connection_id==0){
960                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
961                 lock_destroy(tcpconn_lock);
962                 lock_dealloc((void*)tcpconn_lock);
963                 tcpconn_lock=0;
964                 goto error;
965         }
966         *connection_id=1;
967         /* alloc hashtables*/
968         tcpconn_addr_hash=(struct tcp_connection**)shm_malloc(TCP_ADDR_HASH_SIZE*
969                                                                 sizeof(struct tcp_connection*));
970
971         if (tcpconn_addr_hash==0){
972                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc address hashtable\n");
973                 shm_free(connection_id);
974                 connection_id=0;
975                 lock_destroy(tcpconn_lock);
976                 lock_dealloc((void*)tcpconn_lock);
977                 tcpconn_lock=0;
978                 goto error;
979         }
980         
981         tcpconn_id_hash=(struct tcp_connection**)shm_malloc(TCP_ID_HASH_SIZE*
982                                                                 sizeof(struct tcp_connection*));
983         if (tcpconn_id_hash==0){
984                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc id hashtable\n");
985                 shm_free(connection_id);
986                 connection_id=0;
987                 shm_free(tcpconn_addr_hash);
988                 tcpconn_addr_hash=0;
989                 lock_destroy(tcpconn_lock);
990                 lock_dealloc((void*)tcpconn_lock);
991                 tcpconn_lock=0;
992                 goto error;
993         }
994         /* init hashtables*/
995         memset((void*)tcpconn_addr_hash, 0, 
996                         TCP_ADDR_HASH_SIZE * sizeof(struct tcp_connection*));
997         memset((void*)tcpconn_id_hash, 0, 
998                         TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*));
999         return 0;
1000 error:
1001                 return -1;
1002 }
1003
1004
1005
1006 /* cleanup before exit */
1007 void destroy_tcp()
1008 {
1009         if (tcpconn_lock){
1010                 lock_destroy(tcpconn_lock);
1011                 lock_dealloc((void*)tcpconn_lock);
1012                 tcpconn_lock=0;
1013         }
1014         if(tcpconn_addr_hash){
1015                 shm_free(tcpconn_addr_hash);
1016                 tcpconn_addr_hash=0;
1017         }
1018         if(tcpconn_id_hash){
1019                 shm_free(tcpconn_id_hash);
1020                 tcpconn_id_hash=0;
1021         }
1022         
1023         if(connection_id){
1024                 shm_free(connection_id);
1025                 connection_id=0;
1026         }
1027 }
1028
1029
1030
1031 /* starts the tcp processes */
1032 int tcp_init_children()
1033 {
1034         int r;
1035         int sockfd[2];
1036         pid_t pid;
1037         
1038         
1039         /* create the tcp sock_info structures */
1040         /* copy the sockets --moved to main_loop*/
1041         
1042         /* fork children & create the socket pairs*/
1043         for(r=0; r<tcp_children_no; r++){
1044                 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
1045                         LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1046                                         strerror(errno));
1047                         goto error;
1048                 }
1049                 
1050                 process_no++;
1051                 pid=fork();
1052                 if (pid<0){
1053                         LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
1054                                         strerror(errno));
1055                         goto error;
1056                 }else if (pid>0){
1057                         /* parent */
1058                         close(sockfd[1]);
1059                         tcp_children[r].pid=pid;
1060                         tcp_children[r].proc_no=process_no;
1061                         tcp_children[r].busy=0;
1062                         tcp_children[r].n_reqs=0;
1063                         tcp_children[r].unix_sock=sockfd[0];
1064                         pt[process_no].pid=pid;
1065                         pt[process_no].unix_sock=sockfd[0];
1066                         pt[process_no].idx=r;
1067                         strncpy(pt[process_no].desc, "tcp receiver", MAX_PT_DESC);
1068                 }else{
1069                         /* child */
1070                         close(sockfd[0]);
1071                         unix_tcp_sock=sockfd[1];
1072                         bind_address=0; /* force a SEGFAULT if someone uses a non-init.
1073                                                            bind address on tcp */
1074                         if (init_child(r+children_no+1) < 0) {
1075                                 LOG(L_ERR, "init_children failed\n");
1076                                 goto error;
1077                         }
1078                         tcp_receive_loop(sockfd[1]);
1079                 }
1080         }
1081         return 0;
1082 error:
1083         return -1;
1084 }
1085
1086 #endif