• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- linux-c -*- */
2 /*
3  *
4  *
5  *   Copyright (c) International Business Machines  Corp., 2000
6  *
7  *   This program is free software;  you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15  *   the GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program;  if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  *
22  */
23 /*
24  * ltpServer.c
25  *
26  * LTP Network Socket Test Server
27  *
28  *
29  */
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netdb.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <pthread.h>
39 #include <unistd.h>
40 
41 #define LOCAL_UDP_SERVER_PORT   10000
42 #define LOCAL_TCP_SERVER_PORT   10001
43 #define LOCAL_MULTI_SERVER_PORT 10002
44 #define MAX_MSG_LEN             256
45 #define MAX_HOSTNAME_LEN        256
46 #define ERROR -1
47 #define END_LINE                0x0A
48 
49 int udpSocketHandle,
50     rc, msg_bytes, tcpSocketHandle, newTcpSocketHandle, multiSocketHandle;
51 
52 socklen_t udpClientLen, tcpClientLen, multiClientLen;
53 
54 struct sockaddr_in udpClientAddr,
55     udpServerAddr,
56     tcpClientAddr, tcpServerAddr, multiClientAddr, multiServerAddr;
57 
58 struct ip_mreq multiCastReq;
59 struct in_addr multiCastAddr;
60 struct hostent *hostEntry;
61 
62 char message[MAX_MSG_LEN];
63 char hostname[MAX_HOSTNAME_LEN];
64 char ServerProg[MAX_HOSTNAME_LEN];
65 
66 void *ltp_udp_server_queue(void *);
67 void *ltp_tcp_server_queue(void *);
68 void *ltp_multi_server_queue(void *);
69 int tcp_receive_buffer(int, char *);
70 
main(int argc,char * argv[])71 int main(int argc, char *argv[])
72 {
73 
74 	pthread_t udp_server_queue, tcp_server_queue, multi_server_queue;
75 
76 	pthread_attr_t udpthread_attr, tcpthread_attr, multithread_attr;
77 
78 	if (argc != 2) {
79 		printf
80 		    ("Server arguments : %s <multiCast I.P.address/hostname>\n",
81 		     argv[0]);
82 		exit(0);
83 	}
84 
85 	strncpy(hostname, argv[1], 255);
86 	strncpy(ServerProg, argv[0], 255);
87 
88 	/* get mcast address to listen to */
89 
90 	hostEntry = gethostbyname(argv[1]);
91 
92 	if (hostEntry == NULL) {
93 		printf("Server %s : You need to pass a multiCast group '%s'\n",
94 		       argv[0], argv[1]);
95 		exit(1);
96 	}
97 
98 	memcpy(&multiCastAddr, hostEntry->h_addr_list[0], hostEntry->h_length);
99 
100 	/* check given address is multicast */
101 	if (!IN_MULTICAST(ntohl(multiCastAddr.s_addr))) {
102 		printf
103 		    ("%s : Hostname [%s] passed [%s] is not a multicast server\n",
104 		     argv[0], hostname, inet_ntoa(multiCastAddr));
105 		printf("The multiCast Server will not be started \n");
106 	} else {
107 
108 		/* create multiCast socket */
109 		multiSocketHandle = socket(AF_INET, SOCK_DGRAM, 0);
110 
111 		if (multiSocketHandle < 0) {
112 			printf("%s : cannot create multiCast socket\n",
113 			       argv[0]);
114 		} else {
115 			/* bind multiCast port */
116 			multiServerAddr.sin_family = AF_INET;
117 			multiServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
118 			multiServerAddr.sin_port =
119 			    htons(LOCAL_MULTI_SERVER_PORT);
120 
121 			if (bind
122 			    (multiSocketHandle,
123 			     (struct sockaddr *)&multiServerAddr,
124 			     sizeof(multiServerAddr)) < 0) {
125 				printf("%s : cannot bind Multicast port %d \n",
126 				       argv[0], LOCAL_MULTI_SERVER_PORT);
127 			} else {
128 				/* join multicast group */
129 				multiCastReq.imr_multiaddr.s_addr =
130 				    multiCastAddr.s_addr;
131 				multiCastReq.imr_interface.s_addr =
132 				    htonl(INADDR_ANY);
133 
134 				rc = setsockopt(multiSocketHandle, IPPROTO_IP,
135 						IP_ADD_MEMBERSHIP,
136 						(void *)&multiCastReq,
137 						sizeof(multiCastReq));
138 				if (rc < 0) {
139 					printf
140 					    ("%s : cannot join multicast group '%s'",
141 					     argv[0], inet_ntoa(multiCastAddr));
142 				} else {
143 					printf
144 					    ("%s : listening to mgroup %s:%d\n",
145 					     argv[0], inet_ntoa(multiCastAddr),
146 					     LOCAL_MULTI_SERVER_PORT);
147 				}
148 			}
149 		}
150 
151 		rc = pthread_attr_init(&multithread_attr);
152 		rc = pthread_create(&multi_server_queue, &multithread_attr,
153 				    ltp_multi_server_queue, NULL);
154 	}
155 
156 	/* udp socket creation */
157 	udpSocketHandle = socket(AF_INET, SOCK_DGRAM, 0);
158 
159 	if (udpSocketHandle < 0) {
160 		printf("%s: cannot open socket \n", argv[0]);
161 		exit(1);
162 	}
163 
164 	/* tcp socket creation */
165 	tcpSocketHandle = socket(AF_INET, SOCK_STREAM, 0);
166 
167 	if (tcpSocketHandle < 0) {
168 		printf("Error: cannot open socket %d \n", tcpSocketHandle);
169 		return ERROR;
170 	}
171 
172 	/* bind local udp server port */
173 	udpServerAddr.sin_family = AF_INET;
174 	udpServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
175 	udpServerAddr.sin_port = htons(LOCAL_UDP_SERVER_PORT);
176 
177 	rc = bind(udpSocketHandle, (struct sockaddr *)&udpServerAddr,
178 		  sizeof(udpServerAddr));
179 
180 	if (rc < 0) {
181 		printf("%s: Error binding port number %d \n",
182 		       argv[0], LOCAL_UDP_SERVER_PORT);
183 		exit(1);
184 	} else {
185 		printf("%s: bound port number %d \n",
186 		       argv[0], LOCAL_UDP_SERVER_PORT);
187 	}
188 
189 	/* bind local tcp server port */
190 	tcpServerAddr.sin_family = AF_INET;
191 	tcpServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
192 	tcpServerAddr.sin_port = htons(LOCAL_TCP_SERVER_PORT);
193 
194 	rc = bind(tcpSocketHandle, (struct sockaddr *)&tcpServerAddr,
195 		  sizeof(tcpServerAddr));
196 
197 	if (rc < 0) {
198 		printf("%s: Error binding port number %d \n",
199 		       argv[0], LOCAL_TCP_SERVER_PORT);
200 		exit(1);
201 	} else {
202 		printf("%s: bound port number %d \n",
203 		       argv[0], LOCAL_TCP_SERVER_PORT);
204 	}
205 
206 	rc = pthread_attr_init(&udpthread_attr);
207 	rc = pthread_create(&udp_server_queue, &udpthread_attr,
208 			    ltp_udp_server_queue, NULL);
209 
210 	rc = pthread_attr_init(&tcpthread_attr);
211 	rc = pthread_create(&tcp_server_queue, &tcpthread_attr,
212 			    ltp_tcp_server_queue, NULL);
213 
214 	while (1) ;
215 
216 	return 0;
217 }
218 
219 /*
220  * Function:     ltp_udp_server_queue
221  * Description:  This function grabs the udp message from the queue and outputs to stdio
222  */
ltp_udp_server_queue(void * junk)223 void *ltp_udp_server_queue(void *junk)
224 {
225 
226 	printf("%s: waiting for data on port UDP %u\n",
227 	       hostname, LOCAL_UDP_SERVER_PORT);
228 
229 	/* server infinite loop */
230 	while (1) {
231 
232 		/* init buffer */
233 		memset(message, 0, MAX_MSG_LEN);
234 
235 		/* receive message */
236 		udpClientLen = sizeof(udpClientAddr);
237 
238 		msg_bytes =
239 		    recvfrom(udpSocketHandle, message, MAX_MSG_LEN, 0,
240 			     (struct sockaddr *)&udpClientAddr, &udpClientLen);
241 
242 		printf("msg_bytes:%d \n", msg_bytes);
243 
244 		if (msg_bytes < 0) {
245 			printf("%s: Error receiving data \n", hostname);
246 		} else {
247 			/* print message */
248 			printf("%s: from %s:UDP%u : %s \n",
249 			       hostname, inet_ntoa(udpClientAddr.sin_addr),
250 			       ntohs(udpClientAddr.sin_port), message);
251 		}
252 
253 	}			/* end of server infinite loop */
254 
255 	return NULL;
256 
257 }
258 
259 /*
260  * Function:     ltp_tcp_server_queue
261  * Description:  This function grabs the tcp message from the queue and outputs to stdio
262  */
ltp_tcp_server_queue(void * junk)263 void *ltp_tcp_server_queue(void *junk)
264 {
265 
266 	listen(tcpSocketHandle, 5);
267 
268 	while (1) {
269 
270 		printf("%s: waiting for data on port TCP %u\n", hostname,
271 		       LOCAL_TCP_SERVER_PORT);
272 
273 		tcpClientLen = sizeof(tcpClientAddr);
274 		newTcpSocketHandle =
275 		    accept(tcpSocketHandle, (struct sockaddr *)&tcpClientAddr,
276 			   &tcpClientLen);
277 
278 		if (newTcpSocketHandle < 0) {
279 			printf("cannot accept TCP connection ");
280 			break;
281 		}
282 
283 		/* init line */
284 		memset(message, 0x0, MAX_MSG_LEN);
285 
286 		/* receive segments */
287 		while (tcp_receive_buffer(newTcpSocketHandle, message) != ERROR) {
288 
289 			printf("%s: received from %s:TCP%d : %s\n", hostname,
290 			       inet_ntoa(tcpClientAddr.sin_addr),
291 			       ntohs(tcpClientAddr.sin_port), message);
292 
293 			/* init line */
294 			memset(message, 0x0, MAX_MSG_LEN);
295 
296 		}		/* while (read_line) */
297 		printf("looping in TCP \n");
298 
299 	}			/* while (1) */
300 
301 	return NULL;
302 
303 }
304 
305 /*
306  * Function:     tcp_receive_buffer
307  * Description:  This function grabs the message from the tcp queue and
308  *               returns it to the calling function in the buffer.
309  */
tcp_receive_buffer(int newSocket,char * return_buffer)310 int tcp_receive_buffer(int newSocket, char *return_buffer)
311 {
312 
313 	static int bytes_received = 0;
314 	static char message_received[MAX_MSG_LEN];
315 	static int count = 0;
316 	int offset;
317 
318 	offset = 0;
319 
320 	while (1) {
321 
322 		if (bytes_received == 0) {
323 			/* read data from socket */
324 
325 			memset(message_received, 0x0, MAX_MSG_LEN);	/* init buffer */
326 
327 			count =
328 			    recvfrom(newSocket, message_received, MAX_MSG_LEN,
329 				     0, (struct sockaddr *)&tcpClientAddr,
330 				     &tcpClientLen);
331 
332 			if (count < 0) {
333 				perror(" cannot receive data ");
334 				return ERROR;
335 			} else if (count == 0) {
336 				printf(" connection closed by client\n");
337 				close(newSocket);
338 				if (count) {
339 				}
340 				return ERROR;
341 			}
342 		}
343 
344 		/* Check for new data read on socket or */
345 		/* if still more data in buffer       */
346 
347 		/* copy line into 'return_buffer' */
348 		while (*(message_received + bytes_received) != END_LINE
349 		       && bytes_received < count) {
350 			memcpy(return_buffer + offset,
351 			       message_received + bytes_received, 1);
352 			offset++;
353 			bytes_received++;
354 		}
355 
356 		/* end of line + end of buffer => return line */
357 		if (bytes_received == count - 1) {
358 			/* set last byte to END_LINE */
359 			*(return_buffer + offset) = END_LINE;
360 			bytes_received = 0;
361 			return ++offset;
362 		}
363 
364 		/* end of line but still some data in buffer => return line */
365 		if (bytes_received < count - 1) {
366 			/* set last byte to END_LINE */
367 			*(return_buffer + offset) = END_LINE;
368 			bytes_received++;
369 			return ++offset;
370 		}
371 
372 		/* end of buffer but line is not ended => */
373 		/*  wait for more data to arrive on socket */
374 		if (bytes_received == count) {
375 			bytes_received = 0;
376 			return offset;
377 		}
378 
379 	}			/* while */
380 
381 }
382 
383 /*
384  * Function:     ltp_multi_server_queue
385  * Description:  This function grabs the multiCast message from the queue and outputs to stdio
386  */
ltp_multi_server_queue(void * junk)387 void *ltp_multi_server_queue(void *junk)
388 {
389 
390 	printf("%s: waiting for data on port Multicast %u\n",
391 	       hostname, LOCAL_MULTI_SERVER_PORT);
392 
393 	/* infinite server loop */
394 	while (1) {
395 
396 		multiClientLen = sizeof(multiClientAddr);
397 
398 		msg_bytes =
399 		    recvfrom(multiSocketHandle, message, MAX_MSG_LEN, 0,
400 			     (struct sockaddr *)&multiClientAddr,
401 			     &multiClientLen);
402 
403 		if (msg_bytes < 0) {
404 			printf("%s : cannot receive data\n", hostname);
405 			continue;
406 		}
407 
408 		printf("%s : from %s:%d on %s : %s\n", ServerProg,
409 		       inet_ntoa(multiClientAddr.sin_addr),
410 		       ntohs(multiClientAddr.sin_port), hostname, message);
411 
412 	}			/* end of infinite server loop */
413 
414 	return NULL;
415 
416 }
417