1 #define _GNU_SOURCE 2 #include <sched.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <netinet/in.h> 7 #include <arpa/inet.h> 8 #include <stdlib.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <string.h> 12 #include <stdio.h> 13 #include <netdb.h> 14 #include <ctype.h> 15 16 #include "netlib.h" 17 18 /*----------------------------------------------------------------------------*/ 19 int 20 GetNumCPUCores(void) 21 { 22 return (int)sysconf(_SC_NPROCESSORS_ONLN); 23 } 24 /*----------------------------------------------------------------------------*/ 25 int 26 AffinitizeThreadToCore(int core) 27 { 28 cpu_set_t *cmask; 29 int n, ret; 30 31 n = sysconf(_SC_NPROCESSORS_ONLN); 32 33 if (core < 0 || core >= n) { 34 fprintf(stderr, "%d: invalid CPU number.\n", core); 35 return -1; 36 } 37 38 cmask = CPU_ALLOC(n); 39 if (cmask == NULL) { 40 fprintf(stderr, "%d: uexpected cmask.\n", n); 41 return -1; 42 } 43 44 CPU_ZERO_S(n, cmask); 45 CPU_SET_S(core, n, cmask); 46 47 ret = sched_setaffinity(0, n, cmask); 48 49 CPU_FREE(cmask); 50 return ret; 51 } 52 /*----------------------------------------------------------------------------*/ 53 int 54 CreateServerSocket(int port, int isNonBlocking) 55 { 56 int s; 57 struct sockaddr_in addr; 58 struct linger doLinger; 59 int doReuse = 1; 60 61 if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 62 fprintf(stderr, "socket() failed, errno=%d msg=%s\n", 63 errno, strerror(errno)); 64 return(-1); 65 } 66 67 /* don't linger on close */ 68 doLinger.l_onoff = doLinger.l_linger = 0; 69 if (setsockopt(s, SOL_SOCKET, SO_LINGER, 70 &doLinger, sizeof(doLinger)) == -1) { 71 close(s); 72 return(-1); 73 } 74 75 /* reuse addresses */ 76 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 77 &doReuse, sizeof(doReuse)) == -1) { 78 close(s); 79 return(-1); 80 } 81 82 /* make the listening socket nonblocking */ 83 if (isNonBlocking) { 84 if (fcntl(s, F_SETFL, O_NDELAY) < 0) { 85 fprintf(stderr, "fcntl() failed, errno=%d msg=%s\n", 86 errno, strerror(errno)); 87 close(s); 88 return(-1); 89 } 90 } 91 92 memset(&addr, 0, sizeof(addr)); 93 addr.sin_family = AF_INET; 94 addr.sin_addr.s_addr = htonl(INADDR_ANY); 95 addr.sin_port = htons(port); 96 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 97 fprintf(stderr, "bind() failed, errno=%d msg=%s\n", 98 errno, strerror(errno)); 99 close(s); 100 return(-1); 101 } 102 103 if (listen(s, 1024) < 0) { 104 close(s); 105 return(-1); 106 } 107 108 return(s); 109 } 110 /*-------------------------------------------------------------------------*/ 111 int 112 CreateConnectionSocket(in_addr_t netAddr, int portNum, int nonBlocking) 113 { 114 struct sockaddr_in saddr; 115 int fd; 116 struct linger doLinger; 117 int doReuse = 1; 118 119 if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 120 fprintf(stderr, "failed creating socket - %d\n", errno); 121 return(-1); 122 } 123 124 /* don't linger on close */ 125 doLinger.l_onoff = doLinger.l_linger = 0; 126 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, 127 &doLinger, sizeof(doLinger)) == -1) { 128 close(fd); 129 return(-1); 130 } 131 132 /* reuse addresses */ 133 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 134 &doReuse, sizeof(doReuse)) == -1) { 135 close(fd); 136 return(-1); 137 } 138 139 if (nonBlocking) { 140 if (fcntl(fd, F_SETFL, O_NDELAY) < 0) { 141 fprintf(stderr, "failed fcntl'ing socket - %d\n", errno); 142 close(fd); 143 return(-1); 144 } 145 } 146 147 saddr.sin_family = AF_INET; 148 saddr.sin_addr.s_addr = netAddr; 149 saddr.sin_port = htons(portNum); 150 151 if (connect(fd, (struct sockaddr *) &saddr, 152 sizeof(struct sockaddr_in)) < 0) { 153 if (errno == EINPROGRESS) 154 return(fd); 155 fprintf(stderr, "failed connecting socket addr=%s port %d - errno %d\n", 156 inet_ntoa(saddr.sin_addr), portNum, errno); 157 close(fd); 158 return(-1); 159 } 160 161 return(fd); 162 } 163 /*----------------------------------------------------------------------------*/ 164 void 165 ParseOptions(int argc, const char** argv, struct Options* ops) 166 { 167 int i, j; 168 169 for (i = 1; i < argc; i++) { 170 for (j = 0; ops[j].op_name; j++) { 171 if (strcmp(ops[j].op_name, argv[i]) == 0) { 172 if (i + 1 >= argc) { 173 fprintf(stderr, "no value provided for %s option\n", 174 argv[i]); 175 exit(-1); 176 } 177 *(ops[j].op_varptr) = (char *)argv[++i]; 178 break; 179 } 180 } 181 if (ops[j].op_name == NULL) { 182 fprintf(stderr, "option %s is not supported\n", argv[i]); 183 exit(-1); 184 } 185 } 186 } 187 /*----------------------------------------------------------------------------*/ 188 void 189 PrintOptions(const struct Options* ops, int printVal) 190 { 191 int i; 192 193 if (printVal) { 194 /* for printing option values */ 195 printf("The value for each option is as follows:\n"); 196 } else { 197 /* for explaining the options */ 198 printf("Here is the list of allowable options:\n"); 199 } 200 for (i = 0; ops[i].op_name; i++) { 201 printf("%s: %s\n", 202 ops[i].op_name, printVal? *ops[i].op_varptr:ops[i].op_comment); 203 } 204 } 205 /*----------------------------------------------------------------------------*/ 206 char * 207 GetHeaderString(const char *buf, const char* header, int hdrsize) 208 { 209 #define SKIP_SPACE(x) while ((*(x)) && isspace((*(x)))) (x)++; 210 char *temp = strstr(buf, header); 211 212 if (temp) { 213 temp += hdrsize; 214 SKIP_SPACE(temp); 215 if (*temp) 216 return (temp); 217 } 218 return (NULL); 219 } 220 /*----------------------------------------------------------------------------*/ 221 int 222 GetHeaderLong(const char* buf, const char* header, int hdrsize, long int *val) 223 { 224 long int temp_val; 225 char *temp; 226 227 if ((temp = GetHeaderString(buf, header, hdrsize)) != NULL) { 228 temp_val = strtol(temp, NULL, 10); 229 if (errno != ERANGE && errno != EINVAL) { 230 *val = temp_val; 231 return (TRUE); 232 } 233 } 234 return (FALSE); 235 } 236