1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe, zooey@hirschkaefer.de 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include <arpa/inet.h> 12 #include <ctype.h> 13 #include <errno.h> 14 #include <netinet/in.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <sys/socket.h> 19 20 #define MAXLEN 65535 21 22 23 #ifndef HAIKU_TARGET_PLATFORM_HAIKU 24 typedef int socklen_t; 25 #endif 26 27 extern const char* __progname; 28 29 30 static void 31 udp_echo_client(int sockFD, const struct sockaddr_in* serverAddr) 32 { 33 char buf[MAXLEN]; 34 unsigned int len; 35 long status; 36 37 while (fgets(buf, MAXLEN, stdin) != NULL) { 38 len = strlen(buf); 39 if (len > 0) 40 len--; 41 printf("trying to send %u bytes...\n", len); 42 status = sendto(sockFD, buf, len, 0, 43 (struct sockaddr*)serverAddr, sizeof(struct sockaddr_in)); 44 if (status < 0) { 45 printf("sendto(): %x (%s)\n", errno, strerror(errno)); 46 exit(5); 47 } 48 len = 0; 49 status = recvfrom(sockFD, buf, MAXLEN-1, 0, NULL, NULL); 50 if (status < 0) { 51 printf("recvfrom(): %x (%s)\n", errno, strerror(errno)); 52 exit(5); 53 } 54 buf[status] = 0; 55 printf("-> %s\n", buf); 56 } 57 } 58 59 60 static void 61 udp_broadcast(int sockFD, const struct sockaddr_in* serverAddr) 62 { 63 char buf[MAXLEN]; 64 int option = 1; 65 int len; 66 int status; 67 68 strcpy(buf, "broadcast"); 69 len = strlen(buf); 70 71 setsockopt(sockFD, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)); 72 73 status = sendto(sockFD, buf, len, 0, 74 (struct sockaddr*)serverAddr, sizeof(struct sockaddr_in)); 75 if (status < 0) { 76 printf("sendto(): %s\n", strerror(errno)); 77 exit(5); 78 } 79 80 status = recvfrom(sockFD, buf, MAXLEN-1, 0, NULL, NULL); 81 if (status < 0) { 82 printf("recvfrom(): %x (%s)\n", errno, strerror(errno)); 83 exit(5); 84 } 85 buf[status] = 0; 86 printf("-> %s\n", buf); 87 } 88 89 90 static void 91 udp_echo_server(int sockFD) 92 { 93 char buf[MAXLEN]; 94 long status; 95 socklen_t len; 96 long i; 97 struct sockaddr_in clientAddr; 98 99 while (1) { 100 len = sizeof(clientAddr); 101 status = recvfrom(sockFD, buf, MAXLEN-1, 0, (struct sockaddr*)&clientAddr, &len); 102 if (status < 0) { 103 printf("recvfrom(): %x (%s)\n", errno, strerror(errno)); 104 exit(5); 105 } 106 buf[status] = 0; 107 printf("got <%s> from client(%08x:%u)\n", buf, clientAddr.sin_addr.s_addr, clientAddr.sin_port); 108 for (i = 0; i < status; ++i) { 109 if (islower(buf[i])) 110 buf[i] = toupper(buf[i]); 111 else if (isupper(buf[i])) 112 buf[i] = tolower(buf[i]); 113 } 114 printf("sending <%s>\n", buf); 115 status = sendto(sockFD, buf, status, 0, 116 (struct sockaddr*)&clientAddr, sizeof(clientAddr)); 117 if (status < 0) { 118 printf("sendto(): %x (%s)\n", errno, strerror(errno)); 119 exit(5); 120 } 121 } 122 } 123 124 125 int 126 main(int argc, char** argv) 127 { 128 unsigned long status; 129 int sockFD; 130 struct sockaddr_in serverAddr, localAddr; 131 enum { 132 CLIENT_MODE, 133 BROADCAST_MODE, 134 SERVER_MODE, 135 } mode = 0; 136 unsigned short bindPort = 0; 137 const char* bindAddr = NULL; 138 139 if (argc < 2) { 140 printf("usage: %s client <IP-address> <port> [local-port]\n", __progname); 141 printf("or %s broadcast <port> <local-port>\n", __progname); 142 printf("or %s server <local-port>\n", __progname); 143 exit(5); 144 } 145 146 if (!strcmp(argv[1], "client")) { 147 mode = CLIENT_MODE; 148 if (argc < 4) { 149 printf("usage: %s client <IP-address> <port> [local-port]\n", __progname); 150 exit(5); 151 } 152 memset(&serverAddr, 0, sizeof(struct sockaddr_in)); 153 serverAddr.sin_family = AF_INET; 154 serverAddr.sin_port = htons(atoi(argv[3])); 155 serverAddr.sin_addr.s_addr = inet_addr(argv[2]); 156 if (argc > 4) 157 bindPort = atoi(argv[4]); 158 printf("client connected to server(%08x:%u)\n", serverAddr.sin_addr.s_addr, 159 ntohs(serverAddr.sin_port)); 160 } else if (!strcmp(argv[1], "broadcast")) { 161 mode = BROADCAST_MODE; 162 if (argc < 3) { 163 printf("usage: %s broadcast <port> [local-addr] [broadcast-addr] [local-port]\n", __progname); 164 exit(5); 165 } 166 167 if (argc > 3) 168 bindAddr = argv[3]; 169 170 memset(&serverAddr, 0, sizeof(struct sockaddr_in)); 171 serverAddr.sin_family = AF_INET; 172 serverAddr.sin_port = htons(atoi(argv[2])); 173 if (argc > 4) 174 serverAddr.sin_addr.s_addr = inet_addr(argv[4]); 175 else 176 serverAddr.sin_addr.s_addr = INADDR_BROADCAST; 177 178 if (argc > 5) 179 bindPort = atoi(argv[5]); 180 } else if (!strcmp(argv[1], "server")) { 181 mode = SERVER_MODE; 182 if (argc < 3) { 183 printf("usage: %s server <local-port>\n", argv[0]); 184 exit(5); 185 } 186 bindPort = atoi(argv[2]); 187 } 188 189 sockFD = socket(AF_INET, SOCK_DGRAM, 0); 190 191 if (bindAddr != NULL || bindPort > 0) { 192 memset(&localAddr, 0, sizeof(struct sockaddr_in)); 193 localAddr.sin_family = AF_INET; 194 if (bindAddr != NULL) { 195 localAddr.sin_addr.s_addr = inet_addr(bindAddr); 196 printf("binding to addr %s\n", bindAddr); 197 } 198 if (bindPort > 0) { 199 localAddr.sin_port = htons(bindPort); 200 printf("binding to port %u\n", bindPort); 201 } 202 status = bind(sockFD, (struct sockaddr *)&localAddr, sizeof(localAddr)); 203 if (status < 0) { 204 printf("bind(): %x (%s)\n", errno, strerror(errno)); 205 exit(5); 206 } 207 } 208 209 switch (mode) { 210 case CLIENT_MODE: 211 udp_echo_client(sockFD, &serverAddr); 212 break; 213 case BROADCAST_MODE: 214 udp_broadcast(sockFD, &serverAddr); 215 break; 216 case SERVER_MODE: 217 udp_echo_server(sockFD); 218 break; 219 } 220 221 return 0; 222 } 223