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