source: mainline/uspace/app/netspeed/netspeed.c@ fbb2d0d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fbb2d0d was 8c5ba67, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Add missing curly braces.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Sucha
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup netspeed
30 * @{
31 */
32
33/** @file
34 * Network speed measurement (iperf counterpart)
35 *
36 */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <str.h>
41#include <str_error.h>
42#include <task.h>
43
44#include <net/in.h>
45#include <net/inet.h>
46#include <net/socket.h>
47
48#define NAME "netspeed"
49
50static int server(sock_type_t sock_type, unsigned port, void *buf, size_t bufsize)
51{
52 struct sockaddr_in addr;
53
54 addr.sin_family = AF_INET;
55 addr.sin_port = htons(port);
56
57 int rc = inet_pton(AF_INET, "127.0.0.1", (void *)
58 &addr.sin_addr.s_addr);
59 if (rc != EOK) {
60 fprintf(stderr, "inet_pton failed: %s\n", str_error(rc));
61 return rc;
62 }
63
64 int listen_sd = socket(PF_INET, sock_type, 0);
65 if (listen_sd < 0) {
66 fprintf(stderr, "socket failed: %s\n", str_error(rc));
67 return rc;
68 }
69
70 rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr));
71 if (rc != EOK) {
72 fprintf(stderr, "bind failed: %s\n", str_error(rc));
73 closesocket(listen_sd);
74 return rc;
75 }
76
77 rc = listen(listen_sd, 2);
78 if (rc != EOK) {
79 fprintf(stderr, "listen failed: %s\n", str_error(rc));
80 closesocket(listen_sd);
81 return rc;
82 }
83
84 int conn_sd;
85 struct sockaddr_in raddr;
86 socklen_t raddr_len = sizeof(raddr);
87 if (sock_type == SOCK_STREAM) {
88 conn_sd = accept(listen_sd, (struct sockaddr *) &raddr,
89 &raddr_len);
90 if (conn_sd < 0) {
91 fprintf(stderr, "accept failed: %s\n", str_error(conn_sd));
92 closesocket(listen_sd);
93 return conn_sd;
94 }
95 }
96 else {
97 conn_sd = listen_sd;
98 }
99
100 while (true) {
101 rc = recvfrom(conn_sd, buf, bufsize, 0, (struct sockaddr *) &raddr,
102 &raddr_len);
103 if (rc <= 0) {
104 if (rc < 0)
105 fprintf(stderr, "recvfrom failed: %s\n", str_error(rc));
106 break;
107 }
108 }
109
110 if (sock_type == SOCK_STREAM)
111 closesocket(conn_sd);
112 closesocket(listen_sd);
113
114 return rc;
115}
116
117static int client(sock_type_t sock_type, const char *address, unsigned port,
118 unsigned long count, char *buf, size_t bufsize)
119{
120 struct sockaddr_in addr;
121
122 addr.sin_family = AF_INET;
123 addr.sin_port = htons(port);
124
125 int rc = inet_pton(AF_INET, address, (void *) &addr.sin_addr.s_addr);
126 if (rc != EOK) {
127 fprintf(stderr, "inet_pton failed: %s\n", str_error(rc));
128 return rc;
129 }
130
131 int conn_sd = socket(PF_INET, sock_type, 0);
132 if (conn_sd < 0) {
133 fprintf(stderr, "socket failed: %s\n", str_error(rc));
134 return rc;
135 }
136
137 if (sock_type == SOCK_STREAM) {
138 rc = connect(conn_sd, (struct sockaddr *) &addr, sizeof(addr));
139 if (rc != EOK) {
140 fprintf(stderr, "connect failed: %s\n", str_error(rc));
141 closesocket(conn_sd);
142 return rc;
143 }
144 }
145
146 for (size_t pos = 0; pos < bufsize; pos++) {
147 buf[pos] = '0' + (pos % 10);
148 }
149
150 for (unsigned long i = 0; i < count; i++) {
151 if (sock_type == SOCK_STREAM) {
152 rc = send(conn_sd, buf, bufsize, 0);
153 }
154 else {
155 rc = sendto(conn_sd, buf, bufsize, 0,
156 (struct sockaddr *) &addr, sizeof(addr));
157 }
158 if (rc != EOK) {
159 fprintf(stderr, "send failed: %s\n", str_error(rc));
160 break;
161 }
162 }
163
164 closesocket(conn_sd);
165 return rc;
166}
167
168static void syntax_print(void)
169{
170 fprintf(stderr, "Usage: netspeed <tcp|udp> server [port] <buffer size>\n");
171 fprintf(stderr, " netspeed <tcp|udp> client <ip> <port> <count> <buffer size>\n");
172}
173
174int main(int argc, char *argv[])
175{
176 if (argc < 3) {
177 syntax_print();
178 return 2;
179 }
180
181 sock_type_t sock_type;
182 if (str_cmp(argv[1], "tcp") == 0) {
183 sock_type = SOCK_STREAM;
184 }
185 else if (str_cmp(argv[1], "udp") == 0) {
186 sock_type = SOCK_DGRAM;
187 }
188 else {
189 fprintf(stderr, "Invalid socket type\n");
190 syntax_print();
191 return 1;
192 }
193
194 char *endptr;
195 int arg = 3;
196 unsigned long port = 5001;
197 const char *address;
198 bool is_server;
199 unsigned long count = 0;
200
201 if (str_cmp(argv[2], "server") == 0) {
202 is_server = true;
203 if (argc < 4) {
204 syntax_print();
205 return 2;
206 }
207 if (argc > 4) {
208 port = strtoul(argv[3], &endptr, 0);
209 if (*endptr != 0) {
210 fprintf(stderr, "Invalid port number\n");
211 syntax_print();
212 return 1;
213 }
214 arg = 4;
215 }
216 }
217 else if (str_cmp(argv[2], "client") == 0) {
218 is_server = false;
219 if (argc < 6) {
220 syntax_print();
221 return 2;
222 }
223 address = argv[3];
224 port = strtoul(argv[4], &endptr, 0);
225 if (*endptr != 0) {
226 fprintf(stderr, "Invalid port number\n");
227 syntax_print();
228 return 1;
229 }
230
231 count = strtoul(argv[5], &endptr, 0);
232 if (*endptr != 0) {
233 fprintf(stderr, "Invalid count\n");
234 syntax_print();
235 return 1;
236 }
237
238 arg = 6;
239 }
240 else {
241 fprintf(stderr, "Invalid client/server mode\n");
242 syntax_print();
243 return 2;
244 }
245
246 if (argc < arg + 1) {
247 syntax_print();
248 return 2;
249 }
250
251 unsigned long bufsize = strtoul(argv[arg], &endptr, 0);
252 if (*endptr != 0 || bufsize == 0) {
253 fprintf(stderr, "Invalid buffer size\n");
254 syntax_print();
255 return 1;
256 }
257
258 void *buf = malloc(bufsize);
259 if (buf == NULL) {
260 fprintf(stderr, "Cannot allocate buffer\n");
261 return ENOMEM;
262 }
263
264 int rc = EOK;
265 if (is_server) {
266 rc = server(sock_type, port, buf, bufsize);
267 if (rc != EOK)
268 fprintf(stderr, "Server failed: %s\n", str_error(rc));
269 }
270 else {
271 rc = client(sock_type, address, port, count, buf, bufsize);
272 if (rc != EOK)
273 fprintf(stderr, "Client failed: %s\n", str_error(rc));
274 }
275
276 free(buf);
277
278 return rc;
279}
280
281/** @}
282 */
Note: See TracBrowser for help on using the repository browser.