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
GetNumCPUCores(void)20 GetNumCPUCores(void)
21 {
22 return (int)sysconf(_SC_NPROCESSORS_ONLN);
23 }
24 /*----------------------------------------------------------------------------*/
25 int
AffinitizeThreadToCore(int core)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
CreateServerSocket(int port,int isNonBlocking)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
CreateConnectionSocket(in_addr_t netAddr,int portNum,int nonBlocking)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
ParseOptions(int argc,const char ** argv,struct Options * ops)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
PrintOptions(const struct Options * ops,int printVal)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 *
GetHeaderString(const char * buf,const char * header,int hdrsize)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
GetHeaderLong(const char * buf,const char * header,int hdrsize,long int * val)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