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

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

Cstyle.

  • 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 } else {
96 conn_sd = listen_sd;
97 }
98
99 while (true) {
100 rc = recvfrom(conn_sd, buf, bufsize, 0, (struct sockaddr *) &raddr,
101 &raddr_len);
102 if (rc <= 0) {
103 if (rc < 0)
104 fprintf(stderr, "recvfrom failed: %s\n", str_error(rc));
105 break;
106 }
107 }
108
109 if (sock_type == SOCK_STREAM)
110 closesocket(conn_sd);
111 closesocket(listen_sd);
112
113 return rc;
114}
115
116static int client(sock_type_t sock_type, const char *address, unsigned port,
117 unsigned long count, char *buf, size_t bufsize)
118{
119 struct sockaddr_in addr;
120
121 addr.sin_family = AF_INET;
122 addr.sin_port = htons(port);
123
124 int rc = inet_pton(AF_INET, address, (void *) &addr.sin_addr.s_addr);
125 if (rc != EOK) {
126 fprintf(stderr, "inet_pton failed: %s\n", str_error(rc));
127 return rc;
128 }
129
130 int conn_sd = socket(PF_INET, sock_type, 0);
131 if (conn_sd < 0) {
132 fprintf(stderr, "socket failed: %s\n", str_error(rc));
133 return rc;
134 }
135
136 if (sock_type == SOCK_STREAM) {
137 rc = connect(conn_sd, (struct sockaddr *) &addr, sizeof(addr));
138 if (rc != EOK) {
139 fprintf(stderr, "connect failed: %s\n", str_error(rc));
140 closesocket(conn_sd);
141 return rc;
142 }
143 }
144
145 for (size_t pos = 0; pos < bufsize; pos++) {
146 buf[pos] = '0' + (pos % 10);
147 }
148
149 for (unsigned long i = 0; i < count; i++) {
150 if (sock_type == SOCK_STREAM) {
151 rc = send(conn_sd, buf, bufsize, 0);
152 } else {
153 rc = sendto(conn_sd, buf, bufsize, 0,
154 (struct sockaddr *) &addr, sizeof(addr));
155 }
156 if (rc != EOK) {
157 fprintf(stderr, "send failed: %s\n", str_error(rc));
158 break;
159 }
160 }
161
162 closesocket(conn_sd);
163 return rc;
164}
165
166static void syntax_print(void)
167{
168 fprintf(stderr, "Usage: netspeed <tcp|udp> server [port] <buffer size>\n");
169 fprintf(stderr, " netspeed <tcp|udp> client <ip> <port> <count> <buffer size>\n");
170}
171
172int main(int argc, char *argv[])
173{
174 if (argc < 3) {
175 syntax_print();
176 return 2;
177 }
178
179 sock_type_t sock_type;
180 if (str_cmp(argv[1], "tcp") == 0) {
181 sock_type = SOCK_STREAM;
182 } else if (str_cmp(argv[1], "udp") == 0) {
183 sock_type = SOCK_DGRAM;
184 } else {
185 fprintf(stderr, "Invalid socket type\n");
186 syntax_print();
187 return 1;
188 }
189
190 char *endptr;
191 int arg = 3;
192 unsigned long port = 5001;
193 const char *address;
194 bool is_server;
195 unsigned long count = 0;
196
197 if (str_cmp(argv[2], "server") == 0) {
198 is_server = true;
199 if (argc < 4) {
200 syntax_print();
201 return 2;
202 }
203 if (argc > 4) {
204 port = strtoul(argv[3], &endptr, 0);
205 if (*endptr != 0) {
206 fprintf(stderr, "Invalid port number\n");
207 syntax_print();
208 return 1;
209 }
210 arg = 4;
211 }
212 }
213 else if (str_cmp(argv[2], "client") == 0) {
214 is_server = false;
215 if (argc < 6) {
216 syntax_print();
217 return 2;
218 }
219 address = argv[3];
220 port = strtoul(argv[4], &endptr, 0);
221 if (*endptr != 0) {
222 fprintf(stderr, "Invalid port number\n");
223 syntax_print();
224 return 1;
225 }
226
227 count = strtoul(argv[5], &endptr, 0);
228 if (*endptr != 0) {
229 fprintf(stderr, "Invalid count\n");
230 syntax_print();
231 return 1;
232 }
233
234 arg = 6;
235 }
236 else {
237 fprintf(stderr, "Invalid client/server mode\n");
238 syntax_print();
239 return 2;
240 }
241
242 if (argc < arg + 1) {
243 syntax_print();
244 return 2;
245 }
246
247 unsigned long bufsize = strtoul(argv[arg], &endptr, 0);
248 if (*endptr != 0 || bufsize == 0) {
249 fprintf(stderr, "Invalid buffer size\n");
250 syntax_print();
251 return 1;
252 }
253
254 void *buf = malloc(bufsize);
255 if (buf == NULL) {
256 fprintf(stderr, "Cannot allocate buffer\n");
257 return ENOMEM;
258 }
259
260 int rc = EOK;
261 if (is_server) {
262 rc = server(sock_type, port, buf, bufsize);
263 if (rc != EOK)
264 fprintf(stderr, "Server failed: %s\n", str_error(rc));
265 } else {
266 rc = client(sock_type, address, port, count, buf, bufsize);
267 if (rc != EOK)
268 fprintf(stderr, "Client failed: %s\n", str_error(rc));
269 }
270
271 free(buf);
272
273 return rc;
274}
275
276/** @}
277 */
Note: See TracBrowser for help on using the repository browser.