tcp_main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  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. * [email protected]
  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. #ifdef USE_TCP
  28. #ifndef SHM_MEM
  29. #error "shared memory support needed (add -DSHM_MEM to Makefile.defs)"
  30. #endif
  31. #include <sys/select.h>
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #include <sys/socket.h>
  35. #include <unistd.h>
  36. #include <errno.h>
  37. #include <string.h>
  38. #include "ip_addr.h"
  39. #include "pass_fd.h"
  40. #include "tcp_conn.h"
  41. #include "globals.h"
  42. #include "pt.h"
  43. #include "mem/mem.h"
  44. #include "mem/shm_mem.h"
  45. #include "timer.h"
  46. #include "tcp_server.h"
  47. #include "tcp_init.h"
  48. #define local_malloc pkg_malloc
  49. #define local_free pkg_free
  50. #define MAX_TCP_CHILDREN 100
  51. struct tcp_child{
  52. pid_t pid;
  53. int unix_sock; /* unix sock fd, copied from pt*/
  54. int busy;
  55. int n_reqs; /* number of requests serviced so far */
  56. };
  57. struct tcp_connection** conn_list=0;
  58. struct tcp_child tcp_children[MAX_TCP_CHILDREN];
  59. static int connection_id=1; /* unique for each connection, used for
  60. quickly finding the corresponding connection
  61. for a reply */
  62. int unix_tcp_sock;
  63. struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
  64. struct socket_info* ba)
  65. {
  66. struct tcp_connection *c;
  67. c=(struct tcp_connection*)shm_malloc(sizeof(struct tcp_connection));
  68. if (c==0){
  69. LOG(L_ERR, "ERROR: tcpconn_add: mem. allocation failure\n");
  70. goto error;
  71. }
  72. c->s=sock;
  73. c->fd=sock;
  74. c->rcv.src_su=*su;
  75. c->refcnt=0;
  76. su2ip_addr(&c->rcv.src_ip, su);
  77. c->rcv.src_port=su_getport(su);
  78. c->rcv.proto=PROTO_TCP;
  79. c->rcv.bind_address=ba;
  80. if (ba){
  81. c->rcv.dst_ip=ba->address;
  82. c->rcv.dst_port=ba->port_no;
  83. }
  84. init_tcp_req(&c->req);
  85. c->timeout=get_ticks()+TCP_CON_TIMEOUT;
  86. c->id=connection_id++;
  87. c->rcv.proto_reserved1=0; /* this will be filled before receive_message*/
  88. c->rcv.proto_reserved2=0;
  89. return c;
  90. error:
  91. return 0;
  92. }
  93. struct tcp_connection* tcpconn_connect(union sockaddr_union* server)
  94. {
  95. int s;
  96. s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
  97. if (s<0){
  98. LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
  99. errno, strerror(errno));
  100. goto error;
  101. }
  102. if (connect(s, &server->s, sockaddru_len(*server))<0){
  103. LOG(L_ERR, "ERROR: tcpconn_connect: connect: (%d) %s\n",
  104. errno, strerror(errno));
  105. goto error;
  106. }
  107. return tcpconn_new(s, server, 0); /*FIXME: set sock idx! */
  108. error:
  109. return 0;
  110. }
  111. struct tcp_connection* tcpconn_add(struct tcp_connection *c)
  112. {
  113. TCPCONN_LOCK;
  114. /* add it at the begining of the list*/
  115. if (c) tcpconn_listadd(*conn_list, c, next, prev);
  116. TCPCONN_UNLOCK;
  117. return c;
  118. }
  119. void tcpconn_rm(struct tcp_connection* c)
  120. {
  121. TCPCONN_LOCK;
  122. tcpconn_listrm(*conn_list, c, next, prev);
  123. TCPCONN_UNLOCK;
  124. shm_free(c);
  125. }
  126. /* finds a connection, if id=0 uses the ip addr & port */
  127. struct tcp_connection* tcpconn_find(int id, struct ip_addr* ip, int port)
  128. {
  129. struct tcp_connection *c;
  130. DBG("tcpconn_find: %d ",id ); print_ip(ip); DBG(" %d\n", ntohs(port));
  131. for (c=*conn_list; c; c=c->next){
  132. DBG("c=%p, c->id=%d, ip=",c, c->id);
  133. print_ip(&c->rcv.src_ip);
  134. DBG(" port=%d\n", ntohs(c->rcv.src_port));
  135. if (id){
  136. if (id==c->id) return c;
  137. }else if (ip && (port==c->rcv.src_port)&&
  138. (ip_addr_cmp(ip, &c->rcv.src_ip)))
  139. return c;
  140. }
  141. return 0;
  142. }
  143. struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port)
  144. {
  145. struct tcp_connection* c;
  146. TCPCONN_LOCK;
  147. c=tcpconn_find(id, ip, port);
  148. if (c) c->refcnt++;
  149. TCPCONN_UNLOCK;
  150. return c;
  151. }
  152. void tcpconn_put(struct tcp_connection* c)
  153. {
  154. c->refcnt--; /* FIXME: atomic_dec */
  155. }
  156. /* finds a tcpconn & sends on it */
  157. int tcp_send(char* buf, unsigned len, union sockaddr_union* to, int id)
  158. {
  159. struct tcp_connection *c;
  160. struct ip_addr ip;
  161. int port;
  162. long response[2];
  163. int n;
  164. port=0;
  165. if (to){
  166. su2ip_addr(&ip, to);
  167. port=su_getport(to);
  168. c=tcpconn_get(id, &ip, port); /* lock ;inc refcnt; unlock */
  169. }else if (id){
  170. c=tcpconn_get(id, 0, 0);
  171. }else{
  172. LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
  173. return -1;
  174. }
  175. if (id){
  176. if (c==0) {
  177. if (to){
  178. c=tcpconn_get(0, &ip, port); /* try again w/o id */
  179. goto no_id;
  180. }else{
  181. LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
  182. id);
  183. return -1;
  184. }
  185. }else goto get_fd;
  186. }
  187. no_id:
  188. if (c==0){
  189. DBG("tcp_send: no open tcp connection found, opening new one\n");
  190. /* create tcp connection */
  191. if ((c=tcpconn_connect(to))==0){
  192. LOG(L_ERR, "ERROR: tcp_send: connect failed\n");
  193. return 0;
  194. }
  195. c->refcnt++;
  196. /* send the new tcpconn to "tcp main" */
  197. response[0]=(long)c;
  198. response[1]=CONN_NEW;
  199. n=write(unix_tcp_sock, response, sizeof(response));
  200. n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s);
  201. goto send_it;
  202. }
  203. get_fd:
  204. DBG("tcp_send: tcp connection found, acquiring fd\n");
  205. /* get the fd */
  206. response[0]=(long)c;
  207. response[1]=CONN_GET_FD;
  208. n=write(unix_tcp_sock, response, sizeof(response));
  209. DBG("tcp_send, c= %p, n=%d\n", c, n);
  210. n=receive_fd(unix_tcp_sock, &c, sizeof(c), &c->fd);
  211. DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, c->fd);
  212. send_it:
  213. DBG("tcp_send: sending...\n");
  214. n=write(c->fd, buf, len);
  215. DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, c->fd);
  216. close(c->fd);
  217. tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
  218. return n;
  219. }
  220. /* very ineficient for now, use hashtable some day - FIXME*/
  221. void tcpconn_timeout(fd_set* set)
  222. {
  223. struct tcp_connection *c, *next;
  224. int ticks;;
  225. ticks=get_ticks();
  226. c=*conn_list;
  227. while(c){
  228. next=c->next;
  229. if ((c->refcnt==0) && (ticks>c->timeout)) {
  230. DBG("tcpconn_timeout: timeout for %p (%d > %d)\n",
  231. c, ticks, c->timeout);
  232. if (c->s>0) {
  233. FD_CLR(c->s, set);
  234. close(c->s);
  235. }
  236. tcpconn_rm(c);
  237. }
  238. c=next;
  239. }
  240. }
  241. int tcp_init(struct socket_info* sock_info)
  242. {
  243. union sockaddr_union* addr;
  244. addr=&sock_info->su;
  245. sock_info->proto=PROTO_TCP;
  246. if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
  247. LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n");
  248. goto error;
  249. }
  250. sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0);
  251. if (sock_info->socket==-1){
  252. LOG(L_ERR, "ERROR: tcp_init: socket: %s\n", strerror(errno));
  253. goto error;
  254. }
  255. if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){
  256. LOG(L_ERR, "ERROR: tcp_init: bind(%x, %p, %d) on %s: %s\n",
  257. sock_info->socket, &addr->s,
  258. sockaddru_len(*addr),
  259. sock_info->address_str.s,
  260. strerror(errno));
  261. goto error;
  262. }
  263. if (listen(sock_info->socket, 10)==-1){
  264. LOG(L_ERR, "ERROR: tcp_init: listen(%x, %p, %d) on %s: %s\n",
  265. sock_info->socket, &addr->s,
  266. sockaddru_len(*addr),
  267. sock_info->address_str.s,
  268. strerror(errno));
  269. goto error;
  270. }
  271. return 0;
  272. error:
  273. if (sock_info->socket!=-1){
  274. close(sock_info->socket);
  275. sock_info->socket=-1;
  276. }
  277. return -1;
  278. }
  279. static int send2child(struct tcp_connection* tcpconn)
  280. {
  281. int i;
  282. int min_busy;
  283. int idx;
  284. min_busy=tcp_children[0].busy;
  285. idx=0;
  286. for (i=0; i<tcp_children_no; i++){
  287. if (!tcp_children[i].busy){
  288. idx=i;
  289. min_busy=0;
  290. break;
  291. return 0;
  292. }else if (min_busy>tcp_children[i].busy){
  293. min_busy=tcp_children[i].busy;
  294. idx=i;
  295. }
  296. }
  297. tcp_children[idx].busy++;
  298. tcp_children[idx].n_reqs++;
  299. tcpconn->refcnt++;
  300. if (min_busy){
  301. LOG(L_WARN, "WARNING: send2child:no free tcp receiver, "
  302. " connection passed to the least busy one (%d)\n",
  303. min_busy);
  304. }
  305. DBG("send2child: to child %d, %ld\n", idx, (long)tcpconn);
  306. send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn),
  307. tcpconn->s);
  308. return 0; /* just to fix a warning*/
  309. }
  310. void tcp_main_loop()
  311. {
  312. int r;
  313. int n;
  314. fd_set master_set;
  315. fd_set sel_set;
  316. int maxfd;
  317. int new_sock;
  318. union sockaddr_union su;
  319. struct tcp_connection* tcpconn;
  320. long response[2];
  321. int cmd;
  322. int bytes;
  323. socklen_t su_len;
  324. struct timeval timeout;
  325. /*init */
  326. maxfd=0;
  327. FD_ZERO(&master_set);
  328. /* set all the listen addresses */
  329. for (r=0; r<sock_no; r++){
  330. if ((tcp_info[r].proto==PROTO_TCP) &&(tcp_info[r].socket!=-1)){
  331. FD_SET(tcp_info[r].socket, &master_set);
  332. if (tcp_info[r].socket>maxfd) maxfd=tcp_info[r].socket;
  333. }
  334. }
  335. /* set all the unix sockets used for child comm */
  336. for (r=1; r<process_no; r++){
  337. if (pt[r].unix_sock>0){ /* we can't have 0, we never close it!*/
  338. FD_SET(pt[r].unix_sock, &master_set);
  339. if (pt[r].unix_sock>maxfd) maxfd=pt[r].unix_sock;
  340. }
  341. }
  342. /* main loop*/
  343. while(1){
  344. sel_set=master_set;
  345. timeout.tv_sec=TCP_MAIN_SELECT_TIMEOUT;
  346. timeout.tv_usec=0;
  347. n=select(maxfd+1, &sel_set, 0 ,0 , &timeout);
  348. if (n<0){
  349. if (errno==EINTR) continue; /* just a signal */
  350. /* errors */
  351. LOG(L_ERR, "ERROR: tcp_main_loop: select:(%d) %s\n", errno,
  352. strerror(errno));
  353. n=0;
  354. }
  355. for (r=0; r<sock_no && n; r++){
  356. if ((FD_ISSET(tcp_info[r].socket, &sel_set))){
  357. /* got a connection on r */
  358. su_len=sizeof(su);
  359. new_sock=accept(tcp_info[r].socket, &(su.s), &su_len);
  360. n--;
  361. if (new_sock<0){
  362. LOG(L_ERR, "WARNING: tcp_main_loop: error while accepting"
  363. " connection(%d): %s\n", errno, strerror(errno));
  364. continue;
  365. }
  366. /* add socket to list */
  367. tcpconn=tcpconn_new(new_sock, &su, &tcp_info[r]);
  368. if (tcpconn){
  369. tcpconn_add(tcpconn);
  370. DBG("tcp_main_loop: new connection: %p %d\n",
  371. tcpconn, tcpconn->s);
  372. /* pass it to a child */
  373. if(send2child(tcpconn)<0){
  374. LOG(L_ERR,"ERROR: tcp_main_loop: no children "
  375. "available\n");
  376. close(tcpconn->s);
  377. tcpconn_rm(tcpconn);
  378. }
  379. }
  380. }
  381. }
  382. /* check all the read fds (from the tcpconn list) */
  383. for(tcpconn=*conn_list; tcpconn && n; tcpconn=tcpconn->next){
  384. if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
  385. /* new data available */
  386. n--;
  387. /* pass it to child, so remove it from select list */
  388. DBG("tcp_main_loop: data available on %p %d\n",
  389. tcpconn, tcpconn->s);
  390. FD_CLR(tcpconn->s, &master_set);
  391. if (send2child(tcpconn)<0){
  392. LOG(L_ERR,"ERROR: tcp_main_loop: no children available\n");
  393. close(tcpconn->s);
  394. tcpconn_rm(tcpconn);
  395. }
  396. }
  397. }
  398. /* check unix sockets & listen | destroy connections */
  399. /* start from 1, the "main" process does not transmit anything*/
  400. for (r=1; r<process_no && n; r++){
  401. if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){
  402. /* (we can't have a fd==0, 0 i s never closed )*/
  403. n--;
  404. /* errno==EINTR !!! TODO*/
  405. read_again:
  406. bytes=read(pt[r].unix_sock, response, sizeof(response));
  407. if (bytes==0){
  408. /* EOF -> bad, child has died */
  409. LOG(L_CRIT, "BUG: tcp_main_loop: dead child %d\n", r);
  410. /* don't listen on it any more */
  411. FD_CLR(pt[r].unix_sock, &master_set);
  412. /*exit(-1)*/;
  413. }else if (bytes<0){
  414. if (errno==EINTR) goto read_again;
  415. else{
  416. LOG(L_CRIT, "ERROR: tcp_main_loop: read from child: "
  417. " %s\n", strerror(errno));
  418. /* try to continue ? */
  419. }
  420. }
  421. DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n",
  422. response[0], response[1], r, pt[r].pid);
  423. cmd=response[1];
  424. switch(cmd){
  425. case CONN_RELEASE:
  426. if (pt[r].idx>=0){
  427. tcp_children[pt[r].idx].busy--;
  428. }else{
  429. LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
  430. }
  431. tcpconn=(struct tcp_connection*)response[0];
  432. if (tcpconn){
  433. tcpconn->refcnt--;
  434. DBG("tcp_main_loop: %p refcnt= %d\n",
  435. tcpconn, tcpconn->refcnt);
  436. FD_SET(tcpconn->s, &master_set);
  437. if (maxfd<tcpconn->s) maxfd=tcpconn->s;
  438. /* update the timeout*/
  439. tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
  440. }
  441. break;
  442. case CONN_ERROR:
  443. case CONN_DESTROY:
  444. case CONN_EOF:
  445. if (pt[r].idx>=0){
  446. tcp_children[pt[r].idx].busy--;
  447. }else{
  448. LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n");
  449. }
  450. tcpconn=(struct tcp_connection*)response[0];
  451. if (tcpconn){
  452. tcpconn->refcnt--;
  453. if (tcpconn->refcnt==0){
  454. DBG("tcp_main_loop: destroying connection\n");
  455. close(tcpconn->s);
  456. tcpconn_rm(tcpconn);
  457. }else{
  458. DBG("tcp_main_loop: delaying ...\n");
  459. }
  460. }
  461. break;
  462. case CONN_GET_FD:
  463. /* send the requested FD */
  464. tcpconn=(struct tcp_connection*)response[0];
  465. /* WARNING: take care of setting refcnt properly to
  466. * avoid race condition */
  467. if (tcpconn){
  468. send_fd(pt[r].unix_sock, &tcpconn,
  469. sizeof(tcpconn), tcpconn->s);
  470. }else{
  471. LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
  472. }
  473. break;
  474. case CONN_NEW:
  475. /* update the fd in the requested tcpconn*/
  476. tcpconn=(struct tcp_connection*)response[0];
  477. /* WARNING: take care of setting refcnt properly to
  478. * avoid race condition */
  479. if (tcpconn){
  480. receive_fd(pt[r].unix_sock, &tcpconn,
  481. sizeof(tcpconn), &tcpconn->s);
  482. /* add tcpconn to the list*/
  483. tcpconn_add(tcpconn);
  484. FD_SET(tcpconn->s, &master_set);
  485. if (maxfd<tcpconn->s) maxfd=tcpconn->s;
  486. /* update the timeout*/
  487. tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
  488. }else{
  489. LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n");
  490. }
  491. break;
  492. default:
  493. LOG(L_CRIT, "BUG: tcp_main_loop: unknown cmd %d\n",
  494. cmd);
  495. }
  496. }
  497. }
  498. /* remove old connections */
  499. tcpconn_timeout(&master_set);
  500. }
  501. }
  502. int init_tcp()
  503. {
  504. /* allocate list head*/
  505. conn_list=shm_malloc(sizeof(struct tcp_connection*));
  506. if (conn_list==0){
  507. LOG(L_CRIT, "ERROR: init_tcp: memory allocation failure\n");
  508. goto error;
  509. }
  510. *conn_list=0;
  511. return 0;
  512. error:
  513. return -1;
  514. }
  515. /* starts the tcp processes */
  516. int tcp_init_children()
  517. {
  518. int r;
  519. int sockfd[2];
  520. pid_t pid;
  521. /* create the tcp sock_info structures */
  522. /* copy the sockets --moved to main_loop*/
  523. /* fork children & create the socket pairs*/
  524. for(r=0; r<tcp_children_no; r++){
  525. if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)<0){
  526. LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
  527. strerror(errno));
  528. goto error;
  529. }
  530. process_no++;
  531. pid=fork();
  532. if (pid<0){
  533. LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
  534. strerror(errno));
  535. goto error;
  536. }else if (pid>0){
  537. /* parent */
  538. close(sockfd[1]);
  539. tcp_children[r].pid=pid;
  540. tcp_children[r].busy=0;
  541. tcp_children[r].n_reqs=0;
  542. tcp_children[r].unix_sock=sockfd[0];
  543. pt[process_no].pid=pid;
  544. pt[process_no].unix_sock=sockfd[0];
  545. pt[process_no].idx=r;
  546. strncpy(pt[process_no].desc, "tcp receiver", MAX_PT_DESC);
  547. }else{
  548. /* child */
  549. close(sockfd[0]);
  550. unix_tcp_sock=sockfd[1];
  551. tcp_receive_loop(sockfd[1]);
  552. }
  553. }
  554. return 0;
  555. error:
  556. return -1;
  557. }
  558. #endif