tcp_accept.c

Go to the documentation of this file.
00001 
00056 #include <unistd.h>
00057 #include <errno.h>
00058 #include <string.h>
00059 #include <assert.h>
00060 #include <sys/time.h>
00061 #include <sys/types.h>
00062 #include <sys/socket.h>
00063 #include <sys/ioctl.h>
00064 #include <signal.h>
00065 #include <netinet/in.h>
00066 #include <netdb.h>
00067 #include <stdlib.h>
00068 #include <stdio.h>
00069 
00070 #include "utils.h"
00071 #include "globals.h"
00072 #include "tcp_accept.h"
00073 #include "receiver.h"
00074 
00075 /* defined in ../diameter_peer.c */
00076 int dp_add_pid(pid_t pid);
00077 
00078 
00079 unsigned int *listening_socks=0;    
00082 extern int h_errno;
00083 
00091 int create_socket(int listen_port,str bind_to,unsigned int *sock)
00092 {
00093     unsigned int server_sock=-1;
00094     struct addrinfo *ainfo=0,*res=0,hints;
00095     char buf[256],host[256],serv[256];
00096     int error=0;
00097     unsigned int option;
00098     
00099     memset (&hints, 0, sizeof(hints));
00100     //hints.ai_protocol = IPPROTO_SCTP;
00101     //hints.ai_protocol = IPPROTO_TCP;
00102     hints.ai_flags = AI_PASSIVE|AI_ADDRCONFIG;
00103     hints.ai_socktype = SOCK_STREAM;
00104 
00105     sprintf(buf,"%d",listen_port);
00106     
00107     if (bind_to.len){
00108         error = getaddrinfo(bind_to.s, buf, &hints, &res);
00109         if (error!=0){
00110             LOG(L_WARN,"WARNING:create_socket(): Error opening %.*s port %d while doing gethostbyname >%s\n",
00111                 bind_to.len,bind_to.s,listen_port,gai_strerror(error));
00112             goto error;
00113         }
00114     }else{
00115         error = getaddrinfo(NULL, buf, &hints, &res);
00116         if (error!=0){
00117             LOG(L_WARN,"WARNING:create_socket(): Error opening ANY port %d while doing gethostbyname >%s\n",
00118                 listen_port,gai_strerror(error));
00119             goto error;
00120         }
00121     }
00122         
00123     LOG(L_DBG,"DBG:create_sockets: create socket and bind for IPv4...\n");
00124 
00125     for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
00126     {
00127         if (getnameinfo(ainfo->ai_addr,ainfo->ai_addrlen,
00128             host,256,serv,256,NI_NUMERICHOST|NI_NUMERICSERV)==0){
00129                 LOG(L_WARN,"INFO:create_socket(): Trying to open/bind/listen on %s port %s\n",
00130                     host,serv);
00131         }               
00132 
00133         if ((server_sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol)) == -1) {
00134             LOG(L_ERR,"ERROR:create_socket(): error creating server socket on %s port %s >"
00135                 " %s\n",host,serv,strerror(errno));
00136             goto error;
00137         }
00138         option = 1;
00139         setsockopt(server_sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
00140         
00141         if (bind(   server_sock,ainfo->ai_addr,ainfo->ai_addrlen)==-1 ) {
00142             LOG(L_ERR,"ERROR:create_socket(): error binding on %s port %s >"
00143                 " %s\n",host,serv,strerror(errno));
00144             goto error;
00145         }
00146     
00147         if (listen( server_sock, 5) == -1) {
00148             LOG(L_ERR,"ERROR:create_socket(): error listening on %s port %s > %s\n",host,serv,strerror(errno) );
00149             goto error;
00150         }
00151     
00152         *sock = server_sock;    
00153         
00154         LOG(L_WARN,"INFO:create_socket(): Successful socket open/bind/listen on %s port %s\n",
00155                     host,serv);
00156     }
00157     if (res) freeaddrinfo(res); 
00158     return 1;
00159 error:
00160     if (res) freeaddrinfo(res);
00161     if (server_sock!=-1) close(server_sock);
00162     return 0;
00163     
00164 }
00165 
00172 inline static int accept_connection(int server_sock,int *new_sock)
00173 {
00174     unsigned int length;
00175     struct sockaddr_in remote;
00176     int pid;
00177         
00178     /* do accept */
00179     length = sizeof( struct sockaddr_in);
00180     *new_sock = accept( server_sock, (struct sockaddr*)&remote, &length);
00181 
00182     if (*new_sock==-1) {
00183         LOG(L_ERR,"ERROR:accept_connection(): accept failed!\n");
00184         goto error;
00185     } else {
00186         LOG(L_INFO,"INFO:accept_connection(): new tcp connection accepted!\n");
00187         
00188     }
00189     
00190     receiver_init(*new_sock,0);
00191 
00192     #ifdef CDP_FOR_SER
00193         pid = fork_process(server_sock,"receiver R",0);
00194     #else
00195         pid = fork();
00196     #endif  
00197     if (pid<0){
00198         LOG(L_ERR,"ERROR:accept_connection(): fork() failed > %s\n",strerror(errno));
00199         goto error;
00200     }
00201     if (pid==0){        
00202         /* child */
00203         if (listening_socks) {
00204             pkg_free(listening_socks);
00205             listening_socks=0;
00206         }
00207         dp_add_pid(pid);
00208         receiver_process(*new_sock);
00209         LOG(L_CRIT,"ERROR:accept_connection(): receiver_process finished without exit!\n");
00210         exit(-1);
00211     }else{
00212         /* parent */
00213         LOG(L_INFO,"INFO:accept_connection(): Receiver process forked [%d]\n",pid);
00214     }
00215     
00216     return 1;
00217 error:
00218     return 0;
00219 }
00220 
00226 void accept_loop()
00227 {
00228     fd_set listen_set;
00229     struct timeval timeout;
00230     int i=0,max_sock=0,nready;
00231     int new_sock;
00232     
00233 
00234     while(listening_socks[i]){
00235         if (listening_socks[i]>max_sock) max_sock=listening_socks[i];
00236         i++;
00237     }
00238 
00239     while(1){
00240         if (shutdownx && *shutdownx) break;
00241         
00242         timeout.tv_sec=2;
00243         timeout.tv_usec=0;  
00244         FD_ZERO(&listen_set);
00245         i=0;
00246         while(listening_socks[i]){
00247             FD_SET(listening_socks[i],&listen_set);                 
00248             i++;
00249         }
00250 
00251         nready = select( max_sock+1, &listen_set, 0, 0, &timeout);
00252         if (nready == 0){
00253             LOG(L_DBG,"DBG:accept_loop(): No connection attempts\n");
00254             continue;
00255         }
00256         if (nready == -1) {
00257             if (errno == EINTR) {
00258                 continue;
00259             } else {
00260                 LOG(L_ERR,"ERROR:accept_loop(): select fails: %s\n",
00261                     strerror(errno));
00262                 sleep(2);
00263                 continue;
00264             }
00265         }
00266 
00267         i=0;
00268         while(listening_socks[i]){
00269             if (FD_ISSET(listening_socks[i],&listen_set)){
00270                 accept_connection(listening_socks[i],&new_sock);
00271             }
00272             i++;
00273         }
00274     }
00275 }
00276 

Generated on Sat Sep 6 04:17:47 2008 for Open IMS Core CSCFs by  doxygen 1.5.2