2b64f1863d3da7fd8b8a4e3fe41a89f8a035abdc
[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  *  2003-10-27  tcp port aliases support added (andrei)
47  *  2003-11-04  always lock before manipulating refcnt; sendchild
48  *              does not inc refcnt by itself anymore (andrei)
49  *  2003-11-07  different unix sockets are used for fd passing
50  *              to/from readers/writers (andrei)
51  *  2003-11-17  handle_new_connect & tcp_connect will close the 
52  *              new socket if tcpconn_new return 0 (e.g. out of mem) (andrei)
53  *  2003-11-28  tcp_blocking_write & tcp_blocking_connect added (andrei)
54  */
55
56
57 #ifdef USE_TCP
58
59
60 #ifndef SHM_MEM
61 #error "shared memory support needed (add -DSHM_MEM to Makefile.defs)"
62 #endif
63
64
65 #include <sys/time.h>
66 #include <sys/types.h>
67 #include <sys/select.h>
68 #include <sys/socket.h>
69 #include <netinet/in.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/ip.h>
72 #include <netinet/tcp.h>
73 #include <sys/uio.h>  /* writev*/
74 #include <netdb.h>
75
76 #include <unistd.h>
77 #include <fcntl.h>
78
79 #include <errno.h>
80 #include <string.h>
81
82
83
84 #include "ip_addr.h"
85 #include "pass_fd.h"
86 #include "tcp_conn.h"
87 #include "globals.h"
88 #include "pt.h"
89 #include "locking.h"
90 #include "mem/mem.h"
91 #include "mem/shm_mem.h"
92 #include "timer.h"
93 #include "sr_module.h"
94 #include "tcp_server.h"
95 #include "tcp_init.h"
96 #include "tsend.h"
97 #ifdef USE_TLS
98 #include "tls/tls_server.h"
99 #endif
100
101
102
103
104 #define local_malloc pkg_malloc
105 #define local_free   pkg_free
106
107 #define MAX_TCP_CHILDREN 100
108
109 struct tcp_child{
110         pid_t pid;
111         int proc_no; /* ser proc_no, for debugging */
112         int unix_sock; /* unix "read child" sock fd */
113         int busy;
114         int n_reqs; /* number of requests serviced so far */
115 };
116
117
118 int tcp_accept_aliases=0; /* by default don't accept aliases */
119 int tcp_connect_timeout=DEFAULT_TCP_CONNECT_TIMEOUT;
120 int tcp_send_timeout=DEFAULT_TCP_SEND_TIMEOUT;
121
122 /* connection hash table (after ip&port) , includes also aliases */
123 struct tcp_conn_alias** tcpconn_aliases_hash=0;
124 /* connection hash table (after connection id) */
125 struct tcp_connection** tcpconn_id_hash=0;
126 gen_lock_t* tcpconn_lock=0;
127
128 struct tcp_child tcp_children[MAX_TCP_CHILDREN];
129 static int* connection_id=0; /*  unique for each connection, used for 
130                                                                 quickly finding the corresponding connection
131                                                                 for a reply */
132 int unix_tcp_sock;
133
134 int tcp_proto_no=-1; /* tcp protocol number as returned by getprotobyname */
135
136
137
138 /* set all socket/fd options:  disable nagle, tos lowdelay, non-blocking
139  * return -1 on error */
140 static int init_sock_opt(int s)
141 {
142         int flags;
143         int optval;
144         
145 #ifdef DISABLE_NAGLE
146         flags=1;
147         if ( (tcp_proto_no!=-1) && (setsockopt(s, tcp_proto_no , TCP_NODELAY,
148                                         &flags, sizeof(flags))<0) ){
149                 LOG(L_WARN, "WARNING: init_sock_opt: could not disable Nagle: %s\n",
150                                 strerror(errno));
151         }
152 #endif
153         /* tos*/
154         optval=IPTOS_LOWDELAY;
155         if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,sizeof(optval)) ==-1){
156                 LOG(L_WARN, "WARNING: init_sock_opt: setsockopt tos: %s\n",
157                                 strerror(errno));
158                 /* continue since this is not critical */
159         }
160         /* non-blocking */
161         flags=fcntl(s, F_GETFL);
162         if (flags==-1){
163                 LOG(L_ERR, "ERROR: init_sock_opt: fnctl failed: (%d) %s\n",
164                                 errno, strerror(errno));
165                 goto error;
166         }
167         if (fcntl(s, F_SETFL, flags|O_NONBLOCK)==-1){
168                 LOG(L_ERR, "ERROR: init_sock_opt: fcntl: set non-blocking failed:"
169                                 " (%d) %s\n", errno, strerror(errno));
170                 goto error;
171         }
172         return 0;
173 error:
174         return -1;
175 }
176
177
178
179 static int tcp_blocking_connect(int fd, const struct sockaddr *servaddr,
180                                                                 socklen_t addrlen)
181 {
182         int n;
183         fd_set sel_set;
184         struct timeval timeout;
185         int ticks;
186         int err;
187         unsigned int err_len;
188         
189 again:
190         n=connect(fd, servaddr, addrlen);
191         if (n==-1){
192                 if (errno==EINTR) goto again;
193                 if (errno!=EINPROGRESS && errno!=EALREADY){
194                         LOG(L_ERR, "ERROR: tcp_blocking_connect: (%d) %s\n",
195                                         errno, strerror(errno));
196                         goto error;
197                 }
198         }else goto end;
199         
200         while(1){
201                 FD_ZERO(&sel_set);
202                 FD_SET(fd, &sel_set);
203                 timeout.tv_sec=tcp_connect_timeout;
204                 timeout.tv_usec=0;
205                 ticks=get_ticks();
206                 n=select(fd+1, 0, &sel_set, 0, &timeout);
207                 if (n<0){
208                         if (errno==EINTR) continue;
209                         LOG(L_ERR, "ERROR: tcp_blocking_connect: select failed: (%d) %s\n",
210                                         errno, strerror(errno));
211                         goto error;
212                 }else if (n==0){
213                         /* timeout */
214                         if (get_ticks()-ticks>=tcp_connect_timeout){
215                                 LOG(L_ERR, "ERROR: tcp_blocking_connect: timeout (%d)\n",
216                                                 tcp_connect_timeout);
217                                 goto error;
218                         }
219                         continue;
220                 }
221                 if (FD_ISSET(fd, &sel_set)){
222                         err_len=sizeof(err);
223                         getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
224                         if (err==0) goto end;
225                         if (err!=EINPROGRESS && err!=EALREADY){
226                                 LOG(L_ERR, "ERROR: tcp_blocking_connect: SO_ERROR (%d) %s\n",
227                                                 err, strerror(err));
228                                 goto error;
229                         }
230                 }
231         }
232 error:
233         return -1;
234 end:
235         return 0;
236 }
237
238
239
240 #if 0
241 /* blocking write even on non-blocking sockets 
242  * if TCP_TIMEOUT will return with error */
243 static int tcp_blocking_write(struct tcp_connection* c, int fd, char* buf,
244                                                                 unsigned int len)
245 {
246         int n;
247         fd_set sel_set;
248         struct timeval timeout;
249         int ticks;
250         int initial_len;
251         
252         initial_len=len;
253 again:
254         
255         n=send(fd, buf, len,
256 #ifdef HAVE_MSG_NOSIGNAL
257                         MSG_NOSIGNAL
258 #else
259                         0
260 #endif
261                 );
262         if (n<0){
263                 if (errno==EINTR)       goto again;
264                 else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
265                         LOG(L_ERR, "tcp_blocking_write: failed to send: (%d) %s\n",
266                                         errno, strerror(errno));
267                         goto error;
268                 }
269         }else if (n<len){
270                 /* partial write */
271                 buf+=n;
272                 len-=n;
273         }else{
274                 /* success: full write */
275                 goto end;
276         }
277         while(1){
278                 FD_ZERO(&sel_set);
279                 FD_SET(fd, &sel_set);
280                 timeout.tv_sec=tcp_send_timeout;
281                 timeout.tv_usec=0;
282                 ticks=get_ticks();
283                 n=select(fd+1, 0, &sel_set, 0, &timeout);
284                 if (n<0){
285                         if (errno==EINTR) continue; /* signal, ignore */
286                         LOG(L_ERR, "ERROR: tcp_blocking_write: select failed: "
287                                         " (%d) %s\n", errno, strerror(errno));
288                         goto error;
289                 }else if (n==0){
290                         /* timeout */
291                         if (get_ticks()-ticks>=tcp_send_timeout){
292                                 LOG(L_ERR, "ERROR: tcp_blocking_write: send timeout (%d)\n",
293                                                 tcp_send_timeout);
294                                 goto error;
295                         }
296                         continue;
297                 }
298                 if (FD_ISSET(fd, &sel_set)){
299                         /* we can write again */
300                         goto again;
301                 }
302         }
303 error:
304                 return -1;
305 end:
306                 return initial_len;
307 }
308 #endif
309
310
311
312 struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
313                                                                         struct socket_info* ba, int type, 
314                                                                         int state)
315 {
316         struct tcp_connection *c;
317         
318         c=(struct tcp_connection*)shm_malloc(sizeof(struct tcp_connection));
319         if (c==0){
320                 LOG(L_ERR, "ERROR: tcpconn_new: mem. allocation failure\n");
321                 goto error;
322         }
323         memset(c, 0, sizeof(struct tcp_connection)); /* zero init */
324         c->s=sock;
325         c->fd=-1; /* not initialized */
326         if (lock_init(&c->write_lock)==0){
327                 LOG(L_ERR, "ERROR: tcpconn_new: init lock failed\n");
328                 goto error;
329         }
330         
331         c->rcv.src_su=*su;
332         
333         c->refcnt=0;
334         su2ip_addr(&c->rcv.src_ip, su);
335         c->rcv.src_port=su_getport(su);
336         c->rcv.bind_address=ba;
337         if (ba){
338                 c->rcv.dst_ip=ba->address;
339                 c->rcv.dst_port=ba->port_no;
340         }
341         print_ip("tcpconn_new: new tcp connection: ", &c->rcv.src_ip, "\n");
342         DBG(     "tcpconn_new: on port %d, type %d\n", c->rcv.src_port, type);
343         init_tcp_req(&c->req);
344         c->id=(*connection_id)++;
345         c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
346         c->rcv.proto_reserved2=0;
347         c->state=state;
348         c->extra_data=0;
349 #ifdef USE_TLS
350         if (type==PROTO_TLS){
351                 if (tls_tcpconn_init(c, sock)==-1) goto error;
352         }else
353 #endif /* USE_TLS*/
354         {
355                 c->type=PROTO_TCP;
356                 c->rcv.proto=PROTO_TCP;
357                 c->flags=0;
358                 c->timeout=get_ticks()+TCP_CON_TIMEOUT;
359         }
360                         
361                 
362         return c;
363         
364 error:
365         if (c) shm_free(c);
366         return 0;
367 }
368
369
370
371
372 struct socket_info* find_tcp_si(union sockaddr_union* s)
373 {
374         struct ip_addr ip;
375         struct socket_info* si;
376         
377         su2ip_addr(&ip, s);
378         for (si=tcp_listen; si; si=si->next)
379                 if (ip_addr_cmp(&ip, &si->address)){
380                         /* found it, we use first match */
381                         return si;
382                 }
383         return 0; /* no match */
384 }
385
386
387 struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
388 {
389         int s;
390         struct socket_info* si;
391         union sockaddr_union my_name;
392         socklen_t my_name_len;
393         struct tcp_connection* con;
394
395         s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
396         if (s==-1){
397                 LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
398                                 errno, strerror(errno));
399                 goto error;
400         }
401         if (init_sock_opt(s)<0){
402                 LOG(L_ERR, "ERROR: tcpconn_connect: init_sock_opt failed\n");
403                 goto error;
404         }
405         if (tcp_blocking_connect(s, &server->s, sockaddru_len(*server))<0){
406                 LOG(L_ERR, "ERROR: tcpconn_connect: tcp_blocking_connect failed\n");
407                 goto error;
408         }
409         my_name_len=sizeof(my_name);
410         if (getsockname(s, &my_name.s, &my_name_len)!=0){
411                 LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
412                                 strerror(errno), errno);
413                 si=0; /* try to go on */
414         }
415 #ifdef USE_TLS
416         if (type==PROTO_TLS)
417                 si=find_tls_si(&my_name);
418         else
419 #endif
420                 si=find_tcp_si(&my_name);
421
422         if (si==0){
423                 LOG(L_ERR, "ERROR: tcp_connect: could not find coresponding"
424                                 " listening socket, using default...\n");
425                 if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
426 #ifdef USE_IPV6
427                 else si=sendipv6_tcp;
428 #endif
429         }
430         con=tcpconn_new(s, server, si, type, S_CONN_CONNECT);
431         if (con==0){
432                 LOG(L_ERR, "ERROR: tcp_connect: tcpconn_new failed, closing the "
433                                  " socket\n");
434                 goto error;
435         }
436         return con;
437         /*FIXME: set sock idx! */
438 error:
439         if (s!=-1) close(s); /* close the opened socket */
440         return 0;
441 }
442
443
444
445 struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
446 {
447         unsigned hash;
448
449         if (c){
450                 TCPCONN_LOCK;
451                 /* add it at the begining of the list*/
452                 hash=tcp_id_hash(c->id);
453                 c->id_hash=hash;
454                 tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev);
455                 
456                 hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port);
457                 /* set the first alias */
458                 c->con_aliases[0].port=c->rcv.src_port;
459                 c->con_aliases[0].hash=hash;
460                 c->con_aliases[0].parent=c;
461                 tcpconn_listadd(tcpconn_aliases_hash[hash], &c->con_aliases[0],
462                                                 next, prev);
463                 c->aliases++;
464                 TCPCONN_UNLOCK;
465                 DBG("tcpconn_add: hashes: %d, %d\n", hash, c->id_hash);
466                 return c;
467         }else{
468                 LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n");
469                 return 0;
470         }
471 }
472
473
474 /* unsafe tcpconn_rm version (nolocks) */
475 void _tcpconn_rm(struct tcp_connection* c)
476 {
477         int r;
478         tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
479         /* remove all the aliases */
480         for (r=0; r<c->aliases; r++)
481                 tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], 
482                                                 &c->con_aliases[r], next, prev);
483         lock_destroy(&c->write_lock);
484 #ifdef USE_TLS
485         if (c->type==PROTO_TLS) tls_tcpconn_clean(c);
486 #endif
487         shm_free(c);
488 }
489
490
491
492 void tcpconn_rm(struct tcp_connection* c)
493 {
494         int r;
495         TCPCONN_LOCK;
496         tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev);
497         /* remove all the aliases */
498         for (r=0; r<c->aliases; r++)
499                 tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], 
500                                                 &c->con_aliases[r], next, prev);
501         TCPCONN_UNLOCK;
502         lock_destroy(&c->write_lock);
503 #ifdef USE_TLS
504         if ((c->type==PROTO_TLS)&&(c->extra_data)) tls_tcpconn_clean(c);
505 #endif
506         shm_free(c);
507 }
508
509
510 /* finds a connection, if id=0 uses the ip addr & port (host byte order)
511  * WARNING: unprotected (locks) use tcpconn_get unless you really
512  * know what you are doing */
513 struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port)
514 {
515
516         struct tcp_connection *c;
517         struct tcp_conn_alias* a;
518         unsigned hash;
519         
520 #ifdef EXTRA_DEBUG
521         DBG("tcpconn_find: %d  port %d\n",id, port);
522         if (ip) print_ip("tcpconn_find: ip ", ip, "\n");
523 #endif
524         if (id){
525                 hash=tcp_id_hash(id);
526                 for (c=tcpconn_id_hash[hash]; c; c=c->id_next){
527 #ifdef EXTRA_DEBUG
528                         DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port);
529                         print_ip("ip=", &c->rcv.src_ip, "\n");
530 #endif
531                         if ((id==c->id)&&(c->state!=S_CONN_BAD)) return c;
532                 }
533         }else if (ip){
534                 hash=tcp_addr_hash(ip, port);
535                 for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
536 #ifdef EXTRA_DEBUG
537                         DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent,
538                                         a->parent->id, a->port, a->parent->rcv.src_port);
539                         print_ip("ip=",&a->parent->rcv.src_ip,"\n");
540 #endif
541                         if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
542                                         (ip_addr_cmp(ip, &a->parent->rcv.src_ip)) )
543                                 return a->parent;
544                 }
545         }
546         return 0;
547 }
548
549
550
551 /* _tcpconn_find with locks and timeout */
552 struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
553                                                                         int timeout)
554 {
555         struct tcp_connection* c;
556         TCPCONN_LOCK;
557         c=_tcpconn_find(id, ip, port);
558         if (c){ 
559                         c->refcnt++;
560                         c->timeout=get_ticks()+timeout;
561         }
562         TCPCONN_UNLOCK;
563         return c;
564 }
565
566
567
568 /* add port as an alias for the "id" connection
569  * returns 0 on success,-1 on failure */
570 int tcpconn_add_alias(int id, int port, int proto)
571 {
572         struct tcp_connection* c;
573         unsigned hash;
574         struct tcp_conn_alias* a;
575         
576         a=0;
577         /* fix the port */
578         port=port?port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT);
579         TCPCONN_LOCK;
580         /* check if alias already exists */
581         c=_tcpconn_find(id, 0, 0);
582         if (c){
583                 hash=tcp_addr_hash(&c->rcv.src_ip, port);
584                 /* search the aliases for an already existing one */
585                 for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
586                         if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
587                                         (ip_addr_cmp(&c->rcv.src_ip, &a->parent->rcv.src_ip)) ){
588                                 /* found */
589                                 if (a->parent!=c) goto error_sec;
590                                 else goto ok;
591                         }
592                 }
593                 if (c->aliases>=TCP_CON_MAX_ALIASES) goto error_aliases;
594                 c->con_aliases[c->aliases].parent=c;
595                 c->con_aliases[c->aliases].port=port;
596                 c->con_aliases[c->aliases].hash=hash;
597                 tcpconn_listadd(tcpconn_aliases_hash[hash], 
598                                                                 &c->con_aliases[c->aliases], next, prev);
599                 c->aliases++;
600         }else goto error_not_found;
601 ok:
602         TCPCONN_UNLOCK;
603 #ifdef EXTRA_DEBUG
604         if (a) DBG("tcpconn_add_alias: alias already present\n");
605         else   DBG("tcpconn_add_alias: alias port %d for hash %d, id %d\n",
606                         port, hash, c->id);
607 #endif
608         return 0;
609 error_aliases:
610         TCPCONN_UNLOCK;
611         LOG(L_ERR, "ERROR: tcpconn_add_alias: too many aliases for connection %p"
612                                 " (%d)\n", c, c->id);
613         return -1;
614 error_not_found:
615         TCPCONN_UNLOCK;
616         LOG(L_ERR, "ERROR: tcpconn_add_alias: no connection found for id %d\n",id);
617         return -1;
618 error_sec:
619         TCPCONN_UNLOCK;
620         LOG(L_ERR, "ERROR: tcpconn_add_alias: possible port hijack attemp\n");
621         LOG(L_ERR, "ERROR: tcpconn_add_alias: alias already present and points"
622                         " to another connection (%d : %d and %d : %d)\n",
623                         a->parent->id,  port, c->id, port);
624         return -1;
625 }
626
627
628
629 void tcpconn_ref(struct tcp_connection* c)
630 {
631         TCPCONN_LOCK;
632         c->refcnt++; /* FIXME: atomic_dec */
633         TCPCONN_UNLOCK;
634 }
635
636
637
638 void tcpconn_put(struct tcp_connection* c)
639 {
640         TCPCONN_LOCK;
641         c->refcnt--; /* FIXME: atomic_dec */
642         TCPCONN_UNLOCK;
643 }
644
645
646
647 /* finds a tcpconn & sends on it */
648 int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
649                                 int id)
650 {
651         struct tcp_connection *c;
652         struct tcp_connection *tmp;
653         struct ip_addr ip;
654         int port;
655         int fd;
656         long response[2];
657         int n;
658         
659         port=0;
660         if (to){
661                 su2ip_addr(&ip, to);
662                 port=su_getport(to);
663                 c=tcpconn_get(id, &ip, port, TCP_CON_SEND_TIMEOUT); 
664         }else if (id){
665                 c=tcpconn_get(id, 0, 0, TCP_CON_SEND_TIMEOUT);
666         }else{
667                 LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
668                 return -1;
669         }
670         
671         if (id){
672                 if (c==0) {
673                         if (to){
674                                 /* try again w/o id */
675                                 c=tcpconn_get(0, &ip, port, TCP_CON_SEND_TIMEOUT);
676                                 goto no_id;
677                         }else{
678                                 LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
679                                                 id);
680                                 return -1;
681                         }
682                 }else goto get_fd;
683         }
684 no_id:
685                 if (c==0){
686                         DBG("tcp_send: no open tcp connection found, opening new one\n");
687                         /* create tcp connection */
688                         if ((c=tcpconn_connect(to, type))==0){
689                                 LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
690                                 return -1;
691                         }
692                         c->refcnt++; /* safe to do it w/o locking, it's not yet
693                                                         available to the rest of the world */
694                         fd=c->s;
695                         
696                         /* send the new tcpconn to "tcp main" */
697                         response[0]=(long)c;
698                         response[1]=CONN_NEW;
699                         n=send_all(unix_tcp_sock, response, sizeof(response));
700                         if (n<=0){
701                                 LOG(L_ERR, "BUG: tcp_send: failed write: %s (%d)\n",
702                                                 strerror(errno), errno);
703                                 n=-1;
704                                 goto end;
705                         }       
706                         n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
707                         if (n<=0){
708                                 LOG(L_ERR, "BUG: tcp_send: failed send_fd: %s (%d)\n",
709                                                 strerror(errno), errno);
710                                 n=-1;
711                                 goto end;
712                         }
713                         goto send_it;
714                 }
715 get_fd:
716                         /* todo: see if this is not the same process holding
717                          *  c  and if so send directly on c->fd */
718                         DBG("tcp_send: tcp connection found (%p), acquiring fd\n", c);
719                         /* get the fd */
720                         response[0]=(long)c;
721                         response[1]=CONN_GET_FD;
722                         n=send_all(unix_tcp_sock, response, sizeof(response));
723                         if (n<=0){
724                                 LOG(L_ERR, "BUG: tcp_send: failed to get fd(write):%s (%d)\n",
725                                                 strerror(errno), errno);
726                                 n=-1;
727                                 goto release_c;
728                         }
729                         DBG("tcp_send, c= %p, n=%d\n", c, n);
730                         tmp=c;
731                         n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd);
732                         if (n<=0){
733                                 LOG(L_ERR, "BUG: tcp_send: failed to get fd(receive_fd):"
734                                                         " %s (%d)\n", strerror(errno), errno);
735                                 n=-1;
736                                 goto release_c;
737                         }
738                         if (c!=tmp){
739                                 LOG(L_CRIT, "BUG: tcp_send: get_fd: got different connection:"
740                                                 "  %p (id= %d, refcnt=%d state=%d != "
741                                                 "  %p (id= %d, refcnt=%d state=%d (n=%d)\n",
742                                                   c,   c->id,   c->refcnt,   c->state,
743                                                   tmp, tmp->id, tmp->refcnt, tmp->state, n
744                                    );
745                                 n=-1; /* fail */
746                                 goto end;
747                         }
748                         DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
749                 
750         
751         
752 send_it:
753         DBG("tcp_send: sending...\n");
754         lock_get(&c->write_lock);
755 #ifdef USE_TLS
756         if (c->type==PROTO_TLS)
757                 n=tls_blocking_write(c, fd, buf, len);
758         else
759 #endif
760                 /* n=tcp_blocking_write(c, fd, buf, len); */
761                 n=tsend_stream(fd, buf, len, tcp_send_timeout*1000); 
762         lock_release(&c->write_lock);
763         DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, fd);
764         DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
765         if (n<0){
766                 LOG(L_ERR, "ERROR: tcp_send: failed to send\n");
767                 /* error on the connection , mark it as bad and set 0 timeout */
768                 c->state=S_CONN_BAD;
769                 c->timeout=0;
770                 /* tell "main" it should drop this (optional it will t/o anyway?)*/
771                 response[0]=(long)c;
772                 response[1]=CONN_ERROR;
773                 n=send_all(unix_tcp_sock, response, sizeof(response));
774                 /* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/
775                 if (n<=0){
776                         LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n",
777                                         strerror(errno), errno);
778                         n=-1;
779                 }
780                 close(fd);
781                 return n; /* error return, no tcpconn_put */
782         }
783 end:
784         close(fd);
785 release_c:
786         tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
787         return n;
788 }
789
790
791
792 /* very ineficient for now - FIXME*/
793 void tcpconn_timeout(fd_set* set)
794 {
795         struct tcp_connection *c, *next;
796         int ticks;
797         unsigned h;
798         int fd;
799         
800         
801         ticks=get_ticks();
802         TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */
803         for(h=0; h<TCP_ID_HASH_SIZE; h++){
804                 c=tcpconn_id_hash[h];
805                 while(c){
806                         next=c->id_next;
807                         if ((c->refcnt==0) && (ticks>c->timeout)) {
808                                 DBG("tcpconn_timeout: timeout for hash=%d - %p (%d > %d)\n",
809                                                 h, c, ticks, c->timeout);
810                                 fd=c->s;
811 #ifdef USE_TLS
812                                 if (c->type==PROTO_TLS)
813                                         tls_close(c, fd);
814 #endif
815                                 _tcpconn_rm(c);
816                                 if (fd>0) {
817                                         FD_CLR(fd, set);
818                                         close(fd);
819                                 }
820                         }
821                         c=next;
822                 }
823         }
824         TCPCONN_UNLOCK;
825 }
826
827
828
829 int tcp_init(struct socket_info* sock_info)
830 {
831         union sockaddr_union* addr;
832         int optval;
833 #ifdef DISABLE_NAGLE
834         int flag;
835         struct protoent* pe;
836
837         if (tcp_proto_no==-1){ /* if not already set */
838                 pe=getprotobyname("tcp");
839                 if (pe==0){
840                         LOG(L_ERR, "ERROR: tcp_init: could not get TCP protocol number\n");
841                         tcp_proto_no=-1;
842                 }else{
843                         tcp_proto_no=pe->p_proto;
844                 }
845         }
846 #endif
847         
848         addr=&sock_info->su;
849         /* sock_info->proto=PROTO_TCP; */
850         if (init_su(addr, &sock_info->address, sock_info->port_no)<0){
851                 LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n");
852                 goto error;
853         }
854         sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0);
855         if (sock_info->socket==-1){
856                 LOG(L_ERR, "ERROR: tcp_init: socket: %s\n", strerror(errno));
857                 goto error;
858         }
859 #ifdef DISABLE_NAGLE
860         flag=1;
861         if ( (tcp_proto_no!=-1) &&
862                  (setsockopt(sock_info->socket, tcp_proto_no , TCP_NODELAY,
863                                          &flag, sizeof(flag))<0) ){
864                 LOG(L_ERR, "ERROR: tcp_init: could not disable Nagle: %s\n",
865                                 strerror(errno));
866         }
867 #endif
868
869
870 #if  !defined(TCP_DONT_REUSEADDR) 
871         /* Stevens, "Network Programming", Section 7.5, "Generic Socket
872      * Options": "...server started,..a child continues..on existing
873          * connection..listening server is restarted...call to bind fails
874          * ... ALL TCP servers should specify the SO_REUSEADDRE option 
875          * to allow the server to be restarted in this situation
876          *
877          * Indeed, without this option, the server can't restart.
878          *   -jiri
879          */
880         optval=1;
881         if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR,
882                                 (void*)&optval, sizeof(optval))==-1) {
883                 LOG(L_ERR, "ERROR: tcp_init: setsockopt %s\n",
884                         strerror(errno));
885                 goto error;
886         }
887 #endif
888         /* tos */
889         optval=IPTOS_LOWDELAY;
890         if (setsockopt(sock_info->socket, IPPROTO_IP, IP_TOS, (void*)&optval, 
891                                 sizeof(optval)) ==-1){
892                 LOG(L_WARN, "WARNING: tcp_init: setsockopt tos: %s\n", strerror(errno));
893                 /* continue since this is not critical */
894         }
895         if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){
896                 LOG(L_ERR, "ERROR: tcp_init: bind(%x, %p, %d) on %s: %s\n",
897                                 sock_info->socket, &addr->s, 
898                                 sockaddru_len(*addr),
899                                 sock_info->address_str.s,
900                                 strerror(errno));
901                 goto error;
902         }
903         if (listen(sock_info->socket, 10)==-1){
904                 LOG(L_ERR, "ERROR: tcp_init: listen(%x, %p, %d) on %s: %s\n",
905                                 sock_info->socket, &addr->s, 
906                                 sockaddru_len(*addr),
907                                 sock_info->address_str.s,
908                                 strerror(errno));
909                 goto error;
910         }
911         
912         return 0;
913 error:
914         if (sock_info->socket!=-1){
915                 close(sock_info->socket);
916                 sock_info->socket=-1;
917         }
918         return -1;
919 }
920
921
922
923 static int send2child(struct tcp_connection* tcpconn)
924 {
925         int i;
926         int min_busy;
927         int idx;
928         
929         min_busy=tcp_children[0].busy;
930         idx=0;
931         for (i=0; i<tcp_children_no; i++){
932                 if (!tcp_children[i].busy){
933                         idx=i;
934                         min_busy=0;
935                         break;
936                 }else if (min_busy>tcp_children[i].busy){
937                         min_busy=tcp_children[i].busy;
938                         idx=i;
939                 }
940         }
941         
942         tcp_children[idx].busy++;
943         tcp_children[idx].n_reqs++;
944         if (min_busy){
945                 DBG("WARNING: send2child: no free tcp receiver, "
946                                 " connection passed to the least busy one (%d)\n",
947                                 min_busy);
948         }
949         DBG("send2child: to tcp child %d %d(%d), %p\n", idx, 
950                                         tcp_children[idx].proc_no,
951                                         tcp_children[idx].pid, tcpconn);
952         if (send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn),
953                         tcpconn->s)<=0){
954                 LOG(L_ERR, "ERROR: send2child: send_fd failed\n");
955                 return -1;
956         }
957         
958         return 0;
959 }
960
961
962 /* handle a new connection, called internally by tcp_main_loop */
963 static inline void handle_new_connect(struct socket_info* si,
964                                                                                 fd_set* sel_set, int* n)
965 {
966         union sockaddr_union su;
967         struct tcp_connection* tcpconn;
968         socklen_t su_len;
969         int new_sock;
970         
971         if ((FD_ISSET(si->socket, sel_set))){
972                 /* got a connection on r */
973                 su_len=sizeof(su);
974                 new_sock=accept(si->socket, &(su.s), &su_len);
975                 (*n)--;
976                 if (new_sock==-1){
977                         LOG(L_ERR,  "WARNING: tcp_main_loop: error while accepting"
978                                         " connection(%d): %s\n", errno, strerror(errno));
979                         return;
980                 }
981                 if (init_sock_opt(new_sock)<0){
982                         LOG(L_ERR, "ERROR: tcp_main_loop: init_sock_opt failed\n");
983                         close(new_sock);
984                         return;
985                 }
986                 
987                 /* add socket to list */
988                 tcpconn=tcpconn_new(new_sock, &su, si, si->proto, S_CONN_ACCEPT);
989                 if (tcpconn){
990                         tcpconn->refcnt++; /* safe, not yet available to the
991                                                                   outside world */
992                         tcpconn_add(tcpconn);
993                         DBG("tcp_main_loop: new connection: %p %d\n",
994                                 tcpconn, tcpconn->s);
995                         /* pass it to a child */
996                         if(send2child(tcpconn)<0){
997                                 LOG(L_ERR,"ERROR: tcp_main_loop: no children "
998                                                 "available\n");
999                                 TCPCONN_LOCK;
1000                                 tcpconn->refcnt--;
1001                                 if (tcpconn->refcnt==0){
1002                                         close(tcpconn->s);
1003                                         _tcpconn_rm(tcpconn);
1004                                 }else tcpconn->timeout=0; /* force expire */
1005                                 TCPCONN_UNLOCK;
1006                         }
1007                 }else{ /*tcpconn==0 */
1008                         LOG(L_ERR, "ERROR: tcp_main_loop: tcpconn_new failed, "
1009                                         "closing socket\n");
1010                         close(new_sock);
1011                 }
1012         }
1013 }
1014
1015
1016 /* used internally by tcp_main_loop() */
1017 static void tcpconn_destroy(struct tcp_connection* tcpconn)
1018 {
1019         int fd;
1020
1021         TCPCONN_LOCK; /*avoid races w/ tcp_send*/
1022         tcpconn->refcnt--;
1023         if (tcpconn->refcnt==0){ 
1024                 DBG("tcp_main_loop: destroying connection\n");
1025                 fd=tcpconn->s;
1026 #ifdef USE_TLS
1027                 /*FIXME: lock ->writelock ? */
1028                 if (tcpconn->type==PROTO_TLS)
1029                         tls_close(tcpconn, fd);
1030 #endif
1031                 _tcpconn_rm(tcpconn);
1032                 close(fd);
1033         }else{
1034                 /* force timeout */
1035                 tcpconn->timeout=0;
1036                 tcpconn->state=S_CONN_BAD;
1037                 DBG("tcp_main_loop: delaying ...\n");
1038                 
1039         }
1040         TCPCONN_UNLOCK;
1041 }
1042
1043
1044 void tcp_main_loop()
1045 {
1046         int r;
1047         int n;
1048         fd_set master_set;
1049         fd_set sel_set;
1050         int maxfd;
1051         struct tcp_connection* tcpconn;
1052         unsigned h;
1053         long response[2];
1054         int cmd;
1055         int bytes;
1056         struct timeval timeout;
1057         int fd;
1058         struct socket_info* si;
1059
1060         /*init */
1061         maxfd=0;
1062         FD_ZERO(&master_set);
1063         /* set all the listen addresses */
1064         for (si=tcp_listen; si; si=si->next){
1065                 if ((si->proto==PROTO_TCP) &&(si->socket!=-1)){
1066                         FD_SET(si->socket, &master_set);
1067                         if (si->socket>maxfd) maxfd=si->socket;
1068                 }else{
1069                         LOG(L_CRIT, "BUG: tcp_main_loop: non tcp address in tcp_listen\n");
1070                 }
1071         }
1072 #ifdef USE_TLS
1073         if (!tls_disable){
1074                 for (si=tls_listen; si; si=si->next){
1075                         if ((si->proto==PROTO_TLS) && (si->socket!=-1)){
1076                                 FD_SET(si->socket, &master_set);
1077                                 if (si->socket>maxfd) maxfd=si->socket;
1078                         }else{
1079                                 LOG(L_CRIT, "BUG: tcp_main_loop: non tls address"
1080                                                 " in tls_listen\n");
1081                         }
1082                 }
1083         }
1084 #endif
1085         /* set all the unix sockets used for child comm */
1086         for (r=1; r<process_no; r++){
1087                 if (pt[r].unix_sock>0){ /* we can't have 0, we never close it!*/
1088                         FD_SET(pt[r].unix_sock, &master_set);
1089                         if (pt[r].unix_sock>maxfd) maxfd=pt[r].unix_sock;
1090                 }
1091         }
1092         for (r=0; r<tcp_children_no; r++){
1093                 if (tcp_children[r].unix_sock>0){ /* we can't have 0, 
1094                                                                                          we never close it!*/
1095                         FD_SET(tcp_children[r].unix_sock, &master_set);
1096                         if (tcp_children[r].unix_sock>maxfd)
1097                                 maxfd=tcp_children[r].unix_sock;
1098                 }
1099         }
1100         
1101         
1102         /* main loop*/
1103         
1104         while(1){
1105                 sel_set=master_set;
1106                 timeout.tv_sec=TCP_MAIN_SELECT_TIMEOUT;
1107                 timeout.tv_usec=0;
1108                 n=select(maxfd+1, &sel_set, 0 ,0 , &timeout);
1109                 if (n<0){
1110                         if (errno==EINTR) continue; /* just a signal */
1111                         /* errors */
1112                         LOG(L_ERR, "ERROR: tcp_main_loop: select:(%d) %s\n", errno,
1113                                         strerror(errno));
1114                         n=0;
1115                 }
1116                 
1117                 for (si=tcp_listen; si && n; si=si->next)
1118                         handle_new_connect(si, &sel_set, &n);
1119 #ifdef USE_TLS
1120                         if (!tls_disable)
1121                                 for (si=tls_listen; si && n; si=si->next)
1122                                         handle_new_connect(si, &sel_set, &n);
1123 #endif
1124                 
1125                 /* check all the read fds (from the tcpconn_addr_hash ) */
1126                 for (h=0; h<TCP_ID_HASH_SIZE; h++){
1127                         for(tcpconn=tcpconn_id_hash[h]; tcpconn && n; 
1128                                         tcpconn=tcpconn->id_next){
1129                                 /* FIXME: is refcnt==0 really necessary? */
1130                                 if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
1131                                         /* new data available */
1132                                         n--;
1133                                         /* pass it to child, so remove it from select list */
1134                                         DBG("tcp_main_loop: data available on %p [h:%d] %d\n",
1135                                                         tcpconn, h, tcpconn->s);
1136                                         FD_CLR(tcpconn->s, &master_set);
1137                                         tcpconn_ref(tcpconn); /* refcnt ++ */
1138                                         if (send2child(tcpconn)<0){
1139                                                 LOG(L_ERR,"ERROR: tcp_main_loop: no "
1140                                                                         "children available\n");
1141                                                 TCPCONN_LOCK;
1142                                                 tcpconn->refcnt--;
1143                                                 if (tcpconn->refcnt==0){
1144                                                         fd=tcpconn->s;
1145                                                         _tcpconn_rm(tcpconn);
1146                                                         close(fd);
1147                                                 }else tcpconn->timeout=0; /* force expire*/
1148                                                 TCPCONN_UNLOCK;
1149                                         }
1150                                 }
1151                         }
1152                 }
1153                 /* check unix sockets & listen | destroy connections */
1154                 /* tcp_children readers first */
1155                 for (r=0; r<tcp_children_no && n; r++){
1156                         if ( (tcp_children[r].unix_sock>0) && 
1157                                         FD_ISSET(tcp_children[r].unix_sock, &sel_set)){
1158                                 /* (we can't have a fd==0, 0 is never closed )*/
1159                                 n--;
1160                                 /* read until sizeof(response)
1161                                  * (this is a SOCK_STREAM so read is not atomic */
1162                                 bytes=recv_all(tcp_children[r].unix_sock, response,
1163                                                                 sizeof(response));
1164                                 if (bytes==0){
1165                                         /* EOF -> bad, child has died */
1166                                         DBG("DBG: tcp_main_loop: dead tcp child %d"
1167                                                         " (shutting down?)\n", r);
1168                                         /* don't listen on it any more */
1169                                         FD_CLR(tcp_children[r].unix_sock, &master_set);
1170                                         /*exit(-1);*/
1171                                         continue; /* skip this and try the next one */
1172                                 }else if (bytes<0){
1173                                         LOG(L_CRIT, "ERROR: tcp_main_loop: read from tcp child %d "
1174                                                         "%s\n", r, strerror(errno));
1175                                         /* try to ignore ? */
1176                                         continue; /* skip this and try the next one */
1177                                 }
1178                                         
1179                                 DBG("tcp_main_loop: reader response= %lx, %ld from %d \n",
1180                                                 response[0], response[1], r);
1181                                 cmd=response[1];
1182                                 tcpconn=(struct tcp_connection*)response[0];
1183                                 switch(cmd){
1184                                         case CONN_RELEASE:
1185                                                 tcp_children[r].busy--;
1186                                                 if (tcpconn){
1187                                                                 if (tcpconn->state==S_CONN_BAD){ 
1188                                                                         tcpconn_destroy(tcpconn);
1189                                                                         break;
1190                                                                 }
1191                                                                 FD_SET(tcpconn->s, &master_set);
1192                                                                 if (maxfd<tcpconn->s) maxfd=tcpconn->s;
1193                                                                 /* update the timeout*/
1194                                                                 tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
1195                                                                 tcpconn_put(tcpconn);
1196                                                                 DBG("tcp_main_loop: CONN_RELEASE  %p"
1197                                                                                 " refcnt= %d\n", 
1198                                                                                 tcpconn, tcpconn->refcnt);
1199                                                 }
1200                                                 break;
1201                                         case CONN_ERROR:
1202                                         case CONN_DESTROY:
1203                                         case CONN_EOF:
1204                                                 /* WARNING: this will auto-dec. refcnt! */
1205                                                 tcp_children[pt[r].idx].busy--;
1206                                                 if (tcpconn){
1207                                                         if (tcpconn->s!=-1)
1208                                                                 FD_CLR(tcpconn->s, &master_set);
1209                                                         tcpconn_destroy(tcpconn);
1210                                                 }
1211                                                 break;
1212                                         default:
1213                                                         LOG(L_CRIT, "BUG: tcp_main_loop:  unknown cmd %d"
1214                                                                                 " from tcp reader %d\n",
1215                                                                         cmd, r);
1216                                 }
1217                         }
1218                 }
1219                 /* check "send" unix sockets & listen | destroy connections */
1220                 /* start from 1, the "main" process does not transmit anything*/
1221                 for (r=1; r<process_no && n; r++){
1222                         if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
1223                                 /* (we can't have a fd==0, 0 is never closed )*/
1224                                 n--;
1225                                 /* read until sizeof(response)
1226                                  * (this is a SOCK_STREAM so read is not atomic */
1227                                 bytes=recv_all(pt[r].unix_sock, response, sizeof(response));
1228                                 if (bytes==0){
1229                                         /* EOF -> bad, child has died */
1230                                         DBG("DBG: tcp_main_loop: dead child %d"
1231                                                         " (shutting down?)\n", r);
1232                                         /* don't listen on it any more */
1233                                         FD_CLR(pt[r].unix_sock, &master_set);
1234                                         /*exit(-1);*/
1235                                         continue; /* skip this and try the next one */
1236                                 }else if (bytes<0){
1237                                         LOG(L_CRIT, "ERROR: tcp_main_loop: read from child:  %s\n",
1238                                                         strerror(errno));
1239                                         /* try to ignore ? */
1240                                         continue; /* skip this and try the next one */
1241                                 }
1242                                         
1243                                 DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n",
1244                                                 response[0], response[1], r, pt[r].pid);
1245                                 cmd=response[1];
1246                                 tcpconn=(struct tcp_connection*)response[0];
1247                                 switch(cmd){
1248                                         case CONN_ERROR:
1249                                                 if (tcpconn){
1250                                                         if (tcpconn->s!=-1)
1251                                                                 FD_CLR(tcpconn->s, &master_set);
1252                                                         tcpconn_destroy(tcpconn);
1253                                                 }
1254                                                 break;
1255                                         case CONN_GET_FD:
1256                                                 /* send the requested FD  */
1257                                                 /* WARNING: take care of setting refcnt properly to
1258                                                  * avoid race condition */
1259                                                 if (tcpconn){
1260                                                         if (send_fd(pt[r].unix_sock, &tcpconn,
1261                                                                                 sizeof(tcpconn), tcpconn->s)<=0){
1262                                                                 LOG(L_ERR, "ERROR: tcp_main_loop:"
1263                                                                                 "send_fd failed\n");
1264                                                         }
1265                                                 }else{
1266                                                         LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
1267                                                 }
1268                                                 break;
1269                                         case CONN_NEW:
1270                                                 /* update the fd in the requested tcpconn*/
1271                                                 /* WARNING: take care of setting refcnt properly to
1272                                                  * avoid race condition */
1273                                                 if (tcpconn){
1274                                                         bytes=receive_fd(pt[r].unix_sock, &tcpconn,
1275                                                                         sizeof(tcpconn), &tcpconn->s);
1276                                                                 if (bytes<sizeof(tcpconn)){
1277                                                                         if (bytes<0){
1278                                                                                 LOG(L_CRIT, "BUG: tcp_main_loop:"
1279                                                                                                 " CONN_NEW: receive_fd "
1280                                                                                                 "failed\n");
1281                                                                         }else{
1282                                                                                 LOG(L_CRIT, "BUG: tcp_main_loop:"
1283                                                                                                 " CONN_NEW: to few bytes "
1284                                                                                                 "received (%d)\n", bytes );
1285                                                                         }
1286                                                                         break; /* try to ignore */
1287                                                                 }
1288                                                         /* add tcpconn to the list*/
1289                                                         tcpconn_add(tcpconn);
1290                                                         FD_SET(tcpconn->s, &master_set);
1291                                                         if (maxfd<tcpconn->s) maxfd=tcpconn->s;
1292                                                         /* update the timeout*/
1293                                                         tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
1294                                                 }else{
1295                                                         LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
1296                                                 }
1297                                                 break;
1298                                         default:
1299                                                         LOG(L_CRIT, "BUG: tcp_main_loop: unknown cmd %d\n",
1300                                                                         cmd);
1301                                 }
1302                         }
1303                 } /* for */
1304                 
1305                 /* remove old connections */
1306                 tcpconn_timeout(&master_set);
1307         
1308         }
1309 }
1310
1311
1312
1313 int init_tcp()
1314 {
1315         /* init lock */
1316         tcpconn_lock=lock_alloc();
1317         if (tcpconn_lock==0){
1318                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc lock\n");
1319                 goto error;
1320         }
1321         if (lock_init(tcpconn_lock)==0){
1322                 LOG(L_CRIT, "ERROR: init_tcp: could not init lock\n");
1323                 lock_dealloc((void*)tcpconn_lock);
1324                 tcpconn_lock=0;
1325                 goto error;
1326         }
1327         /* init globals */
1328         connection_id=(int*)shm_malloc(sizeof(int));
1329         if (connection_id==0){
1330                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
1331                 lock_destroy(tcpconn_lock);
1332                 lock_dealloc((void*)tcpconn_lock);
1333                 tcpconn_lock=0;
1334                 goto error;
1335         }
1336         *connection_id=1;
1337         /* alloc hashtables*/
1338         tcpconn_aliases_hash=(struct tcp_conn_alias**)
1339                         shm_malloc(TCP_ALIAS_HASH_SIZE* sizeof(struct tcp_conn_alias*));
1340         if (tcpconn_aliases_hash==0){
1341                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc address hashtable\n");
1342                 shm_free(connection_id);
1343                 connection_id=0;
1344                 lock_destroy(tcpconn_lock);
1345                 lock_dealloc((void*)tcpconn_lock);
1346                 tcpconn_lock=0;
1347                 goto error;
1348         }
1349         
1350         tcpconn_id_hash=(struct tcp_connection**)shm_malloc(TCP_ID_HASH_SIZE*
1351                                                                 sizeof(struct tcp_connection*));
1352         if (tcpconn_id_hash==0){
1353                 LOG(L_CRIT, "ERROR: init_tcp: could not alloc id hashtable\n");
1354                 shm_free(connection_id);
1355                 connection_id=0;
1356                 shm_free(tcpconn_aliases_hash);
1357                 tcpconn_aliases_hash=0;
1358                 lock_destroy(tcpconn_lock);
1359                 lock_dealloc((void*)tcpconn_lock);
1360                 tcpconn_lock=0;
1361                 goto error;
1362         }
1363         /* init hashtables*/
1364         memset((void*)tcpconn_aliases_hash, 0, 
1365                         TCP_ALIAS_HASH_SIZE * sizeof(struct tcp_conn_alias*));
1366         memset((void*)tcpconn_id_hash, 0, 
1367                         TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*));
1368         return 0;
1369 error:
1370                 return -1;
1371 }
1372
1373
1374
1375 /* cleanup before exit */
1376 void destroy_tcp()
1377 {
1378         if (tcpconn_lock){
1379                 lock_destroy(tcpconn_lock);
1380                 lock_dealloc((void*)tcpconn_lock);
1381                 tcpconn_lock=0;
1382         }
1383         if(tcpconn_aliases_hash){
1384                 shm_free(tcpconn_aliases_hash);
1385                 tcpconn_aliases_hash=0;
1386         }
1387         if(tcpconn_id_hash){
1388                 shm_free(tcpconn_id_hash);
1389                 tcpconn_id_hash=0;
1390         }
1391         
1392         if(connection_id){
1393                 shm_free(connection_id);
1394                 connection_id=0;
1395         }
1396 }
1397
1398
1399
1400 /* starts the tcp processes */
1401 int tcp_init_children()
1402 {
1403         int r;
1404         int sockfd[2];
1405         int reader_fd[2]; /* for comm. with the tcp children read  */
1406         pid_t pid;
1407         
1408         
1409         /* create the tcp sock_info structures */
1410         /* copy the sockets --moved to main_loop*/
1411         
1412         /* fork children & create the socket pairs*/
1413         for(r=0; r<tcp_children_no; r++){
1414                 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
1415                         LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1416                                         strerror(errno));
1417                         goto error;
1418                 }
1419                 if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
1420                         LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
1421                                         strerror(errno));
1422                         goto error;
1423                 }
1424                 
1425                 process_no++;
1426                 pid=fork();
1427                 if (pid<0){
1428                         LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
1429                                         strerror(errno));
1430                         goto error;
1431                 }else if (pid>0){
1432                         /* parent */
1433                         close(sockfd[1]);
1434                         close(reader_fd[1]);
1435                         tcp_children[r].pid=pid;
1436                         tcp_children[r].proc_no=process_no;
1437                         tcp_children[r].busy=0;
1438                         tcp_children[r].n_reqs=0;
1439                         tcp_children[r].unix_sock=reader_fd[0];
1440                         pt[process_no].pid=pid;
1441                         pt[process_no].unix_sock=sockfd[0];
1442                         pt[process_no].idx=r;
1443                         strncpy(pt[process_no].desc, "tcp receiver", MAX_PT_DESC);
1444                 }else{
1445                         /* child */
1446                         close(sockfd[0]);
1447                         unix_tcp_sock=sockfd[1];
1448                         bind_address=0; /* force a SEGFAULT if someone uses a non-init.
1449                                                            bind address on tcp */
1450                         if (init_child(r+children_no+1) < 0) {
1451                                 LOG(L_ERR, "init_children failed\n");
1452                                 goto error;
1453                         }
1454                         tcp_receive_loop(reader_fd[1]);
1455                 }
1456         }
1457         return 0;
1458 error:
1459         return -1;
1460 }
1461
1462 #endif