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
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
00101
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
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
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
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