int get_fdset_size(void) { unsigned int MaxNumDescriptors = 0; int NumFDSetsNeeded = 0; int NumBytesInFDSet = 0; int Result = 0; MaxNumDescriptors = get_max_num_descriptors(); NumBytesInFDSet = sizeof(fd_set); NumFDSetsNeeded = MaxNumDescriptors / FD_SETSIZE; if (MaxNumDescriptors < FD_SETSIZE) { /* the default size already provides sufficient space */ Result = NumBytesInFDSet; } else if ((MaxNumDescriptors % FD_SETSIZE) > 0) { /* we need to allocate more memory to cover extra * bits--add an extra FDSet worth of memory to the size */ Result = (NumFDSetsNeeded + 1) * NumBytesInFDSet; } else { /* division was exact--we know exactly how many bytes we need */ Result = NumFDSetsNeeded * NumBytesInFDSet; } return(Result); } /* END get_fdset_size() */
int wait_request( struct timeval *timeout, /* I (seconds) */ long *SState) /* I (optional) */ { extern char *PAddrToString(pbs_net_t *); void close_conn(); int i; int n; time_t now; fd_set *SelectSet = NULL; int SelectSetSize = 0; int MaxNumDescriptors = 0; char id[] = "wait_request"; char tmpLine[1024]; long OrigState = 0; if (SState != NULL) OrigState = *SState; SelectSetSize = sizeof(char) * get_fdset_size(); SelectSet = (fd_set *)calloc(1,SelectSetSize); memcpy(SelectSet,GlobalSocketReadSet,SelectSetSize); /* selset = readset;*/ /* readset is global */ MaxNumDescriptors = get_max_num_descriptors(); n = select(MaxNumDescriptors, SelectSet, (fd_set *)0, (fd_set *)0, timeout); if (n == -1) { if (errno == EINTR) { n = 0; /* interrupted, cycle around */ } else { int i; struct stat fbuf; /* check all file descriptors to verify they are valid */ /* NOTE: selset may be modified by failed select() */ for (i = 0;i < MaxNumDescriptors;i++) { if (FD_ISSET(i, GlobalSocketReadSet) == 0) continue; if (fstat(i, &fbuf) == 0) continue; /* clean up SdList and bad sd... */ FD_CLR(i, GlobalSocketReadSet); } /* END for (i) */ free(SelectSet); return(-1); } /* END else (errno == EINTR) */ } /* END if (n == -1) */ for (i = 0;(i < max_connection) && (n != 0);i++) { if (FD_ISSET(i, SelectSet)) { /* this socket has data */ n--; svr_conn[i].cn_lasttime = time((time_t *)0); if (svr_conn[i].cn_active != Idle) { netcounter_incr(); if (svr_conn[i].cn_func != NULL) { svr_conn[i].cn_func(i); } /* NOTE: breakout if state changed (probably received shutdown request) */ if ((SState != NULL) && (OrigState != *SState)) break; } else { FD_CLR(i, GlobalSocketReadSet); close_conn(i); sprintf(tmpLine,"closed connection to fd %d - num_connections=%d (select bad socket)", i, num_connections); log_err(-1,id,tmpLine); } } } /* END for (i) */ /* NOTE: break out if shutdown request received */ if ((SState != NULL) && (OrigState != *SState)) { free(SelectSet); return(0); } /* have any connections timed out ?? */ now = time((time_t *)0); for (i = 0;i < max_connection;i++) { struct connection *cp; cp = &svr_conn[i]; if (cp->cn_active != FromClientDIS) continue; if ((now - cp->cn_lasttime) <= PBS_NET_MAXCONNECTIDLE) continue; if (cp->cn_authen & PBS_NET_CONN_NOTIMEOUT) continue; /* do not time-out this connection */ /* NOTE: add info about node associated with connection - NYI */ snprintf(tmpLine, sizeof(tmpLine), "connection %d to host %s has timed out after %d seconds - closing stale connection\n", i, PAddrToString(&cp->cn_addr), PBS_NET_MAXCONNECTIDLE); log_err(-1, "wait_request", tmpLine); /* locate node associated with interface, mark node as down until node responds */ /* NYI */ close_conn(i); } /* END for (i) */ free(SelectSet); return(0); } /* END wait_request() */
int init_network( unsigned int port, void (*readfunc)()) { int i; static int initialized = 0; int sock; int MaxNumDescriptors = 0; struct sockaddr_in socname; enum conn_type type; #ifdef ENABLE_UNIX_SOCKETS struct sockaddr_un unsocname; int unixsocket; memset(&unsocname, 0, sizeof(unsocname)); #endif MaxNumDescriptors = get_max_num_descriptors(); memset(&socname, 0, sizeof(socname)); if (initialized == 0) { for (i = 0;i < PBS_NET_MAX_CONNECTIONS;i++) svr_conn[i].cn_active = Idle; /* initialize global "read" socket FD bitmap */ GlobalSocketReadSet = (fd_set *)calloc(1,sizeof(char) * get_fdset_size()); type = Primary; } else if (initialized == 1) { type = Secondary; } else { /* FAILURE */ return(-1); /* too many main connections */ } /* save the routine which should do the reading on connections */ /* accepted from the parent socket */ read_func[initialized++] = readfunc; if (port != 0) { sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { /* FAILURE */ return(-1); } if (MaxNumDescriptors < PBS_NET_MAX_CONNECTIONS) max_connection = MaxNumDescriptors; i = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)); i = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)); /* name that socket "in three notes" */ socname.sin_port = htons((unsigned short)port); socname.sin_addr.s_addr = INADDR_ANY; socname.sin_family = AF_INET; if (bind(sock, (struct sockaddr *)&socname, sizeof(socname)) < 0) { /* FAILURE */ close(sock); return(-1); } /* record socket in connection structure and select set */ add_conn(sock, type, (pbs_net_t)0, 0, PBS_SOCK_INET, accept_conn); /* start listening for connections */ if (listen(sock, 512) < 0) { /* FAILURE */ return(-1); } } /* END if (port != 0) */ #ifdef ENABLE_UNIX_SOCKETS if (port == 0) { /* setup unix domain socket */ unixsocket = socket(AF_UNIX, SOCK_STREAM, 0); if (unixsocket < 0) { return(-1); } unsocname.sun_family = AF_UNIX; strncpy(unsocname.sun_path, TSOCK_PATH, sizeof(unsocname.sun_path) - 1); unlink(TSOCK_PATH); /* don't care if this fails */ if (bind(unixsocket, (struct sockaddr *)&unsocname, sizeof(unsocname)) < 0) { close(unixsocket); return(-1); } if (chmod(TSOCK_PATH, S_IRUSR | S_IWUSR) != 0) { close(unixsocket); return(-1); } add_conn(unixsocket, type, (pbs_net_t)0, 0, PBS_SOCK_UNIX, accept_conn); if (listen(unixsocket, 512) < 0) { /* FAILURE */ return(-1); } } /* END if (port == 0) */ #endif /* END ENABLE_UNIX_SOCKETS */ if (port != 0) { /* allocate a minute's worth of counter structs */ for (i = 0;i < 60;i++) { nc_list[i].time = 0; nc_list[i].counter = 0; } } return(0); } /* END init_network() */