xref: /mOS-networking-stack/util/netlib.c (revision 76404edc)
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