tcp_accept.c File Reference


Detailed Description

CDiameterPeer TCP Acceptor Process.

Author:
Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de

Definition in file tcp_accept.c.

#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include "utils.h"
#include "globals.h"
#include "tcp_accept.h"
#include "receiver.h"

Go to the source code of this file.

Functions

int dp_add_pid (pid_t pid)
 Add a pid to the local process list.
int create_socket (int listen_port, str bind_to, unsigned int *sock)
 Creates a socket and binds it.
static int accept_connection (int server_sock, int *new_sock)
 Accepts an incoming connection by forking a receiver process.
void accept_loop ()
 Accept loop that listens for incoming connections on all listening sockets.

Variables

unsigned int * listening_socks = 0
 array of sockets listening for connections
int h_errno


Function Documentation

int dp_add_pid ( pid_t  pid  )  [inline]

Add a pid to the local process list.

Parameters:
pid newly forked pid
Returns:
1 on success or 0 on error

Definition at line 95 of file diameter_peer.c.

00096 {
00097     pid_list_t *n;
00098     lock_get(pid_list_lock);
00099     n = shm_malloc(sizeof(pid_list_t));
00100     if (!n){
00101         LOG_NO_MEM("shm",sizeof(pid_list_t));
00102         lock_release(pid_list_lock);
00103         return 0;
00104     }
00105     n->pid = pid;
00106     n->next = 0;
00107     n->prev = pid_list->tail;
00108     if (!pid_list->head) pid_list->head = n;
00109     if (pid_list->tail) pid_list->tail->next = n;
00110     pid_list->tail = n;
00111     lock_release(pid_list_lock);
00112     return 1;
00113 }

int create_socket ( int  listen_port,
str  bind_to,
unsigned int *  sock 
)

Creates a socket and binds it.

Parameters:
listen_port - port to listen to
bind_to - IP address to bind to - if empty, will bind to :: (0.0.0.0) (all)
sock - socket to be update with the identifier of the opened one
Returns:
1 on success, 0 on error

Definition at line 91 of file tcp_accept.c.

References errno, and NULL.

Referenced by acceptor_process().

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 }

static int accept_connection ( int  server_sock,
int *  new_sock 
) [inline, static]

Accepts an incoming connection by forking a receiver process.

Parameters:
server_sock - socket that this connection came in to
new_sock - socket to be update with the value of the accepter socket
Returns:
1 on success, 0 on error

Definition at line 172 of file tcp_accept.c.

References dp_add_pid(), errno, listening_socks, receiver_init(), and receiver_process().

Referenced by accept_loop().

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 }

void accept_loop (  ) 

Accept loop that listens for incoming connections on all listening sockets.

When a connection is received, accept_connection() is called.

Returns:
only on shutdown

Definition at line 226 of file tcp_accept.c.

References accept_connection(), errno, listening_socks, select, and shutdownx.

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 }


Variable Documentation

unsigned int* listening_socks = 0

array of sockets listening for connections

Definition at line 79 of file tcp_accept.c.

Referenced by accept_connection(), accept_loop(), and acceptor_process().

int h_errno


Generated on Tue Oct 14 04:11:26 2008 for Open IMS Core CSCFs by  doxygen 1.5.2