blob: 11d412b51f7c715a9a33f9b49db53232823f54b9 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2014 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <app.h>
24#include <err.h>
25#include <debug.h>
26#include <trace.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <compiler.h>
30#include <kernel/thread.h>
31#include <lib/minip.h>
32#include <lib/tftp.h>
33#include <lib/cksum.h>
34#include <platform.h>
35
36#include "inetsrv.h"
37
38static int chargen_worker(void *socket)
39{
40 uint64_t count = 0;
41 tcp_socket_t *s = socket;
42
43/* enough buffer to hold an entire defacto chargen sequences */
44#define CHARGEN_BUFSIZE (0x5f * 0x5f) // 9025 bytes
45
46 uint8_t *buf = malloc(CHARGEN_BUFSIZE);
47 if (!buf)
48 return ERR_NO_MEMORY;
49
50 /* generate the sequence */
51 uint8_t c = '!';
52 for (size_t i = 0; i < CHARGEN_BUFSIZE; i++) {
53 buf[i] = c++;
54 if (c == 0x7f)
55 c = ' ';
56 }
57
58 lk_time_t t = current_time();
59 for (;;) {
60 ssize_t ret = tcp_write(s, buf, CHARGEN_BUFSIZE);
61 //TRACEF("tcp_write returns %d\n", ret);
62 if (ret < 0)
63 break;
64
65 count += ret;
66 }
67 t = current_time() - t;
68
69 TRACEF("chargen worker exiting, wrote %llu bytes in %u msecs (%llu bytes/sec)\n",
70 count, (uint32_t)t, count * 1000 / t);
71 free(buf);
72 tcp_close(s);
73
74 return 0;
75}
76
77static int chargen_server(void *arg)
78{
79 status_t err;
80 tcp_socket_t *listen_socket;
81
82 err = tcp_open_listen(&listen_socket, 19);
83 if (err < 0) {
84 TRACEF("error opening chargen listen socket\n");
85 return -1;
86 }
87
88 for (;;) {
89 tcp_socket_t *accept_socket;
90
91 err = tcp_accept(listen_socket, &accept_socket);
92 TRACEF("tcp_accept returns returns %d, handle %p\n", err, accept_socket);
93 if (err < 0) {
94 TRACEF("error accepting socket, retrying\n");
95 continue;
96 }
97
98 TRACEF("starting chargen worker\n");
99 thread_detach_and_resume(thread_create("chargen_worker", &chargen_worker, accept_socket, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
100 }
101}
102
103static int discard_worker(void *socket)
104{
105 uint64_t count = 0;
106 uint32_t crc = 0;
107 tcp_socket_t *s = socket;
108
109#define DISCARD_BUFSIZE 1024
110
111 uint8_t *buf = malloc(DISCARD_BUFSIZE);
112 if (!buf) {
113 TRACEF("error allocating buffer\n");
114 }
115
116 lk_time_t t = current_time();
117 for (;;) {
118 ssize_t ret = tcp_read(s, buf, DISCARD_BUFSIZE);
119 if (ret <= 0)
120 break;
121
122 crc = crc32(crc, buf, ret);
123
124 count += ret;
125 }
126 t = current_time() - t;
127
128 TRACEF("discard worker exiting, read %llu bytes in %u msecs (%llu bytes/sec), crc32 0x%x\n",
129 count, (uint32_t)t, count * 1000 / t, crc);
130 tcp_close(s);
131
132 free(buf);
133
134 return 0;
135}
136
137static int discard_server(void *arg)
138{
139 status_t err;
140 tcp_socket_t *listen_socket;
141
142 err = tcp_open_listen(&listen_socket, 9);
143 if (err < 0) {
144 TRACEF("error opening discard listen socket\n");
145 return -1;
146 }
147
148 for (;;) {
149 tcp_socket_t *accept_socket;
150
151 err = tcp_accept(listen_socket, &accept_socket);
152 TRACEF("tcp_accept returns returns %d, handle %p\n", err, accept_socket);
153 if (err < 0) {
154 TRACEF("error accepting socket, retrying\n");
155 continue;
156 }
157
158 TRACEF("starting discard worker\n");
159 thread_detach_and_resume(thread_create("discard_worker", &discard_worker, accept_socket, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
160 }
161}
162
163static int echo_worker(void *socket)
164{
165 tcp_socket_t *s = socket;
166
167#define ECHO_BUFSIZE 1024
168
169 uint8_t *buf = malloc(ECHO_BUFSIZE);
170 if (!buf) {
171 TRACEF("error allocating buffer\n");
172 return ERR_NO_MEMORY;
173 }
174
175 for (;;) {
176 ssize_t ret = tcp_read(s, buf, sizeof(buf));
177 if (ret <= 0)
178 break;
179
180 tcp_write(s, buf, ret);
181 if (ret <= 0)
182 break;
183 }
184
185 TRACEF("echo worker exiting\n");
186 tcp_close(s);
187 free(buf);
188
189 return 0;
190}
191
192static int echo_server(void *arg)
193{
194 status_t err;
195 tcp_socket_t *listen_socket;
196
197 err = tcp_open_listen(&listen_socket, 7);
198 if (err < 0) {
199 TRACEF("error opening echo listen socket\n");
200 return -1;
201 }
202
203 for (;;) {
204 tcp_socket_t *accept_socket;
205
206 err = tcp_accept(listen_socket, &accept_socket);
207 TRACEF("tcp_accept returns returns %d, handle %p\n", err, accept_socket);
208 if (err < 0) {
209 TRACEF("error accepting socket, retrying\n");
210 continue;
211 }
212
213 TRACEF("starting echo worker\n");
214 thread_detach_and_resume(thread_create("echo_worker", &echo_worker, accept_socket, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
215 }
216}
217
218static void inetsrv_init(const struct app_descriptor *app)
219{
220}
221
222static void inetsrv_entry(const struct app_descriptor *app, void *args)
223{
224 /* XXX wait for the stack to initialize */
225
226 printf("starting internet servers\n");
227
228 thread_detach_and_resume(thread_create("chargen", &chargen_server, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
229 thread_detach_and_resume(thread_create("discard", &discard_server, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
230 thread_detach_and_resume(thread_create("echo", &echo_server, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
231 tftp_server_init(NULL);
232}
233
234APP_START(inetsrv)
235 .init = inetsrv_init,
236 .entry = inetsrv_entry,
237 .flags = 0,
238APP_END