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 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 */ 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 */ 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 */ 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 */ 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