ReactOS 0.4.16-dev-927-g467dec4
lwiperf.c
Go to the documentation of this file.
1
21/*
22 * Copyright (c) 2014 Simon Goldschmidt
23 * All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without modification,
26 * are permitted provided that the following conditions are met:
27 *
28 * 1. Redistributions of source code must retain the above copyright notice,
29 * this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright notice,
31 * this list of conditions and the following disclaimer in the documentation
32 * and/or other materials provided with the distribution.
33 * 3. The name of the author may not be used to endorse or promote products
34 * derived from this software without specific prior written permission.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
39 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
41 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
44 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
45 * OF SUCH DAMAGE.
46 *
47 * This file is part of the lwIP TCP/IP stack.
48 *
49 * Author: Simon Goldschmidt
50 */
51
52#include "lwip/apps/lwiperf.h"
53
54#include "lwip/tcp.h"
55#include "lwip/sys.h"
56#include "lwip/inet.h"
57
58#include <string.h>
59
60/* Currently, only TCP is implemented */
61#if LWIP_TCP && LWIP_CALLBACK_API
62
64#ifndef LWIPERF_TCP_MAX_IDLE_SEC
65#define LWIPERF_TCP_MAX_IDLE_SEC 10U
66#endif
67#if LWIPERF_TCP_MAX_IDLE_SEC > 255
68#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t
69#endif
70
72#ifndef LWIPERF_SERVER_IP_TYPE
73#define LWIPERF_SERVER_IP_TYPE IPADDR_TYPE_ANY
74#endif
75
76/* File internal memory allocation (struct lwiperf_*): this defaults to
77 the heap */
78#ifndef LWIPERF_ALLOC
79#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type))
80#define LWIPERF_FREE(type, item) mem_free(item)
81#endif
82
84#ifndef LWIPERF_CHECK_RX_DATA
85#define LWIPERF_CHECK_RX_DATA 0
86#endif
87
89typedef struct _lwiperf_settings {
90#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000
91#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001
93 u32_t num_threads; /* unused for now */
94 u32_t remote_port;
95 u32_t buffer_len; /* unused for now */
96 u32_t win_band; /* TCP window / UDP rate: unused for now */
97 u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */
98} lwiperf_settings_t;
99
101struct _lwiperf_state_base;
102typedef struct _lwiperf_state_base lwiperf_state_base_t;
103struct _lwiperf_state_base {
104 /* linked list */
105 lwiperf_state_base_t *next;
106 /* 1=tcp, 0=udp */
107 u8_t tcp;
108 /* 1=server, 0=client */
109 u8_t server;
110 /* master state used to abort sessions (e.g. listener, main client) */
111 lwiperf_state_base_t *related_master_state;
112};
113
115typedef struct _lwiperf_state_tcp {
116 lwiperf_state_base_t base;
117 struct tcp_pcb *server_pcb;
118 struct tcp_pcb *conn_pcb;
119 u32_t time_started;
120 lwiperf_report_fn report_fn;
121 void *report_arg;
122 u8_t poll_count;
123 u8_t next_num;
124 /* 1=start server when client is closed */
125 u8_t client_tradeoff_mode;
126 u32_t bytes_transferred;
127 lwiperf_settings_t settings;
128 u8_t have_settings_buf;
129 u8_t specific_remote;
130 ip_addr_t remote_addr;
131} lwiperf_state_tcp_t;
132
134static lwiperf_state_base_t *lwiperf_all_connections;
136static const u8_t lwiperf_txbuf_const[1600] = {
137 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
138 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
139 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
140 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
141 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
142 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
144 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
145 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
146 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
147 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
148 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
149 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
150 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
151 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
152 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
153 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
154 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
155 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
156 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
157 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
158 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
159 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
160 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
161 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
163 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
164 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
165 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
166 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
167 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
168 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
169 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
170 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
171 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
172 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
173 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
174 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
175 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
176 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
177};
178
179static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb);
180static void lwiperf_tcp_err(void *arg, err_t err);
181static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port,
182 lwiperf_report_fn report_fn, void *report_arg,
183 lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state);
184
185
187static void
188lwiperf_list_add(lwiperf_state_base_t *item)
189{
190 item->next = lwiperf_all_connections;
191 lwiperf_all_connections = item;
192}
193
195static void
196lwiperf_list_remove(lwiperf_state_base_t *item)
197{
198 lwiperf_state_base_t *prev = NULL;
199 lwiperf_state_base_t *iter;
200 for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) {
201 if (iter == item) {
202 if (prev == NULL) {
203 lwiperf_all_connections = iter->next;
204 } else {
205 prev->next = iter->next;
206 }
207 /* @debug: ensure this item is listed only once */
208 for (iter = iter->next; iter != NULL; iter = iter->next) {
209 LWIP_ASSERT("duplicate entry", iter != item);
210 }
211 break;
212 }
213 }
214}
215
216static lwiperf_state_base_t *
217lwiperf_list_find(lwiperf_state_base_t *item)
218{
219 lwiperf_state_base_t *iter;
220 for (iter = lwiperf_all_connections; iter != NULL; iter = iter->next) {
221 if (iter == item) {
222 return item;
223 }
224 }
225 return NULL;
226}
227
229static void
230lwip_tcp_conn_report(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type)
231{
232 if ((conn != NULL) && (conn->report_fn != NULL)) {
233 u32_t now, duration_ms, bandwidth_kbitpsec;
234 now = sys_now();
235 duration_ms = now - conn->time_started;
236 if (duration_ms == 0) {
237 bandwidth_kbitpsec = 0;
238 } else {
239 bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U;
240 }
241 conn->report_fn(conn->report_arg, report_type,
242 &conn->conn_pcb->local_ip, conn->conn_pcb->local_port,
243 &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port,
244 conn->bytes_transferred, duration_ms, bandwidth_kbitpsec);
245 }
246}
247
249static void
250lwiperf_tcp_close(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type)
251{
252 err_t err;
253
254 lwiperf_list_remove(&conn->base);
255 lwip_tcp_conn_report(conn, report_type);
256 if (conn->conn_pcb != NULL) {
257 tcp_arg(conn->conn_pcb, NULL);
258 tcp_poll(conn->conn_pcb, NULL, 0);
259 tcp_sent(conn->conn_pcb, NULL);
260 tcp_recv(conn->conn_pcb, NULL);
261 tcp_err(conn->conn_pcb, NULL);
262 err = tcp_close(conn->conn_pcb);
263 if (err != ERR_OK) {
264 /* don't want to wait for free memory here... */
265 tcp_abort(conn->conn_pcb);
266 }
267 } else if (conn->server_pcb != NULL) {
268 /* no conn pcb, this is the listener pcb */
269 err = tcp_close(conn->server_pcb);
270 LWIP_ASSERT("error", err == ERR_OK);
271 }
272 LWIPERF_FREE(lwiperf_state_tcp_t, conn);
273}
274
276static err_t
277lwiperf_tcp_client_send_more(lwiperf_state_tcp_t *conn)
278{
279 int send_more;
280 err_t err;
281 u16_t txlen;
282 u16_t txlen_max;
283 void *txptr;
284 u8_t apiflags;
285
286 LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0));
287
288 do {
289 send_more = 0;
290 if (conn->settings.amount & PP_HTONL(0x80000000)) {
291 /* this session is time-limited */
292 u32_t now = sys_now();
293 u32_t diff_ms = now - conn->time_started;
294 u32_t time = (u32_t) - (s32_t)lwip_htonl(conn->settings.amount);
295 u32_t time_ms = time * 10;
296 if (diff_ms >= time_ms) {
297 /* time specified by the client is over -> close the connection */
298 lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
299 return ERR_OK;
300 }
301 } else {
302 /* this session is byte-limited */
303 u32_t amount_bytes = lwip_htonl(conn->settings.amount);
304 /* @todo: this can send up to 1*MSS more than requested... */
305 if (amount_bytes >= conn->bytes_transferred) {
306 /* all requested bytes transferred -> close the connection */
307 lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT);
308 return ERR_OK;
309 }
310 }
311
312 if (conn->bytes_transferred < 24) {
313 /* transmit the settings a first time */
314 txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred];
315 txlen_max = (u16_t)(24 - conn->bytes_transferred);
316 apiflags = TCP_WRITE_FLAG_COPY;
317 } else if (conn->bytes_transferred < 48) {
318 /* transmit the settings a second time */
319 txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred - 24];
320 txlen_max = (u16_t)(48 - conn->bytes_transferred);
321 apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;
322 send_more = 1;
323 } else {
324 /* transmit data */
325 /* @todo: every x bytes, transmit the settings again */
326 txptr = LWIP_CONST_CAST(void *, &lwiperf_txbuf_const[conn->bytes_transferred % 10]);
327 txlen_max = TCP_MSS;
328 if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */
329 txlen_max = TCP_MSS - 24;
330 }
331 apiflags = 0; /* no copying needed */
332 send_more = 1;
333 }
334 txlen = txlen_max;
335 do {
336 err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags);
337 if (err == ERR_MEM) {
338 txlen /= 2;
339 }
340 } while ((err == ERR_MEM) && (txlen >= (TCP_MSS / 2)));
341
342 if (err == ERR_OK) {
343 conn->bytes_transferred += txlen;
344 } else {
345 send_more = 0;
346 }
347 } while (send_more);
348
349 tcp_output(conn->conn_pcb);
350 return ERR_OK;
351}
352
354static err_t
355lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
356{
357 lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
358 /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */
359 LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
360 LWIP_UNUSED_ARG(tpcb);
362
363 conn->poll_count = 0;
364
365 return lwiperf_tcp_client_send_more(conn);
366}
367
369static err_t
370lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
371{
372 lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
373 LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb);
374 LWIP_UNUSED_ARG(tpcb);
375 if (err != ERR_OK) {
376 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
377 return ERR_OK;
378 }
379 conn->poll_count = 0;
380 conn->time_started = sys_now();
381 return lwiperf_tcp_client_send_more(conn);
382}
383
387static err_t
388lwiperf_tx_start_impl(const ip_addr_t *remote_ip, u16_t remote_port, lwiperf_settings_t *settings, lwiperf_report_fn report_fn,
389 void *report_arg, lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **new_conn)
390{
391 err_t err;
392 lwiperf_state_tcp_t *client_conn;
393 struct tcp_pcb *newpcb;
394 ip_addr_t remote_addr;
395
396 LWIP_ASSERT("remote_ip != NULL", remote_ip != NULL);
397 LWIP_ASSERT("remote_ip != NULL", settings != NULL);
398 LWIP_ASSERT("new_conn != NULL", new_conn != NULL);
399 *new_conn = NULL;
400
401 client_conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
402 if (client_conn == NULL) {
403 return ERR_MEM;
404 }
405 newpcb = tcp_new_ip_type(IP_GET_TYPE(remote_ip));
406 if (newpcb == NULL) {
407 LWIPERF_FREE(lwiperf_state_tcp_t, client_conn);
408 return ERR_MEM;
409 }
410 memset(client_conn, 0, sizeof(lwiperf_state_tcp_t));
411 client_conn->base.tcp = 1;
412 client_conn->base.related_master_state = related_master_state;
413 client_conn->conn_pcb = newpcb;
414 client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */
415 client_conn->report_fn = report_fn;
416 client_conn->report_arg = report_arg;
417 client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */
418 client_conn->bytes_transferred = 0;
419 memcpy(&client_conn->settings, settings, sizeof(*settings));
420 client_conn->have_settings_buf = 1;
421
422 tcp_arg(newpcb, client_conn);
423 tcp_sent(newpcb, lwiperf_tcp_client_sent);
424 tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
425 tcp_err(newpcb, lwiperf_tcp_err);
426
427 ip_addr_copy(remote_addr, *remote_ip);
428
429 err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected);
430 if (err != ERR_OK) {
431 lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL);
432 return err;
433 }
434 lwiperf_list_add(&client_conn->base);
435 *new_conn = client_conn;
436 return ERR_OK;
437}
438
439static err_t
440lwiperf_tx_start_passive(lwiperf_state_tcp_t *conn)
441{
442 err_t ret;
443 lwiperf_state_tcp_t *new_conn = NULL;
444 u16_t remote_port = (u16_t)lwip_htonl(conn->settings.remote_port);
445
446 ret = lwiperf_tx_start_impl(&conn->conn_pcb->remote_ip, remote_port, &conn->settings, conn->report_fn, conn->report_arg,
447 conn->base.related_master_state, &new_conn);
448 if (ret == ERR_OK) {
449 LWIP_ASSERT("new_conn != NULL", new_conn != NULL);
450 new_conn->settings.flags = 0; /* prevent the remote side starting back as client again */
451 }
452 return ret;
453}
454
456static err_t
457lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
458{
459 u8_t tmp;
460 u16_t tot_len;
461 u32_t packet_idx;
462 struct pbuf *q;
463 lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
464
465 LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
466 LWIP_UNUSED_ARG(tpcb);
467
468 if (err != ERR_OK) {
469 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
470 return ERR_OK;
471 }
472 if (p == NULL) {
473 /* connection closed -> test done */
474 if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
475 if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) == 0) {
476 /* client requested transmission after end of test */
477 lwiperf_tx_start_passive(conn);
478 }
479 }
480 lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER);
481 return ERR_OK;
482 }
483 tot_len = p->tot_len;
484
485 conn->poll_count = 0;
486
487 if ((!conn->have_settings_buf) || ((conn->bytes_transferred - 24) % (1024 * 128) == 0)) {
488 /* wait for 24-byte header */
489 if (p->tot_len < sizeof(lwiperf_settings_t)) {
490 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
491 pbuf_free(p);
492 return ERR_OK;
493 }
494 if (!conn->have_settings_buf) {
495 if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) {
496 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
497 pbuf_free(p);
498 return ERR_OK;
499 }
500 conn->have_settings_buf = 1;
501 if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
502 if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) {
503 /* client requested parallel transmission test */
504 err_t err2 = lwiperf_tx_start_passive(conn);
505 if (err2 != ERR_OK) {
506 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR);
507 pbuf_free(p);
508 return ERR_OK;
509 }
510 }
511 }
512 } else {
513 if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) {
514 if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) {
515 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
516 pbuf_free(p);
517 return ERR_OK;
518 }
519 }
520 }
521 conn->bytes_transferred += sizeof(lwiperf_settings_t);
522 if (conn->bytes_transferred <= 24) {
523 conn->time_started = sys_now();
524 tcp_recved(tpcb, p->tot_len);
525 pbuf_free(p);
526 return ERR_OK;
527 }
528 conn->next_num = 4; /* 24 bytes received... */
529 tmp = pbuf_remove_header(p, 24);
530 LWIP_ASSERT("pbuf_remove_header failed", tmp == 0);
531 LWIP_UNUSED_ARG(tmp); /* for LWIP_NOASSERT */
532 }
533
534 packet_idx = 0;
535 for (q = p; q != NULL; q = q->next) {
536#if LWIPERF_CHECK_RX_DATA
537 const u8_t *payload = (const u8_t *)q->payload;
538 u16_t i;
539 for (i = 0; i < q->len; i++) {
540 u8_t val = payload[i];
541 u8_t num = val - '0';
542 if (num == conn->next_num) {
543 conn->next_num++;
544 if (conn->next_num == 10) {
545 conn->next_num = 0;
546 }
547 } else {
548 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR);
549 pbuf_free(p);
550 return ERR_OK;
551 }
552 }
553#endif
554 packet_idx += q->len;
555 }
556 LWIP_ASSERT("count mismatch", packet_idx == p->tot_len);
557 conn->bytes_transferred += packet_idx;
558 tcp_recved(tpcb, tot_len);
559 pbuf_free(p);
560 return ERR_OK;
561}
562
564static void
565lwiperf_tcp_err(void *arg, err_t err)
566{
567 lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
569
570 /* pcb is already deallocated, prevent double-free */
571 conn->conn_pcb = NULL;
572 conn->server_pcb = NULL;
573
574 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE);
575}
576
578static err_t
579lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb)
580{
581 lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg;
582 LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb);
583 LWIP_UNUSED_ARG(tpcb);
584 if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) {
585 lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL);
586 return ERR_OK; /* lwiperf_tcp_close frees conn */
587 }
588
589 if (!conn->base.server) {
590 lwiperf_tcp_client_send_more(conn);
591 }
592
593 return ERR_OK;
594}
595
597static err_t
598lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
599{
600 lwiperf_state_tcp_t *s, *conn;
601 if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) {
602 return ERR_VAL;
603 }
604
605 s = (lwiperf_state_tcp_t *)arg;
606 LWIP_ASSERT("invalid session", s->base.server);
607 LWIP_ASSERT("invalid listen pcb", s->server_pcb != NULL);
608 LWIP_ASSERT("invalid conn pcb", s->conn_pcb == NULL);
609 if (s->specific_remote) {
610 LWIP_ASSERT("s->base.related_master_state != NULL", s->base.related_master_state != NULL);
611 if (!ip_addr_eq(&newpcb->remote_ip, &s->remote_addr)) {
612 /* this listener belongs to a client session, and this is not the correct remote */
613 return ERR_VAL;
614 }
615 } else {
616 LWIP_ASSERT("s->base.related_master_state == NULL", s->base.related_master_state == NULL);
617 }
618
619 conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
620 if (conn == NULL) {
621 return ERR_MEM;
622 }
623 memset(conn, 0, sizeof(lwiperf_state_tcp_t));
624 conn->base.tcp = 1;
625 conn->base.server = 1;
626 conn->base.related_master_state = &s->base;
627 conn->conn_pcb = newpcb;
628 conn->time_started = sys_now();
629 conn->report_fn = s->report_fn;
630 conn->report_arg = s->report_arg;
631
632 /* setup the tcp rx connection */
633 tcp_arg(newpcb, conn);
634 tcp_recv(newpcb, lwiperf_tcp_recv);
635 tcp_poll(newpcb, lwiperf_tcp_poll, 2U);
636 tcp_err(conn->conn_pcb, lwiperf_tcp_err);
637
638 if (s->specific_remote) {
639 /* this listener belongs to a client, so make the client the master of the newly created connection */
640 conn->base.related_master_state = s->base.related_master_state;
641 /* if dual mode or (tradeoff mode AND client is done): close the listener */
642 if (!s->client_tradeoff_mode || !lwiperf_list_find(s->base.related_master_state)) {
643 /* prevent report when closing: this is expected */
644 s->report_fn = NULL;
645 lwiperf_tcp_close(s, LWIPERF_TCP_ABORTED_LOCAL);
646 }
647 }
648 lwiperf_list_add(&conn->base);
649 return ERR_OK;
650}
651
660void *
661lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg)
662{
664 report_fn, report_arg);
665}
666
675void *
676lwiperf_start_tcp_server(const ip_addr_t *local_addr, u16_t local_port,
677 lwiperf_report_fn report_fn, void *report_arg)
678{
679 err_t err;
680 lwiperf_state_tcp_t *state = NULL;
681
682 err = lwiperf_start_tcp_server_impl(local_addr, local_port, report_fn, report_arg,
683 NULL, &state);
684 if (err == ERR_OK) {
685 return state;
686 }
687 return NULL;
688}
689
690static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port,
691 lwiperf_report_fn report_fn, void *report_arg,
692 lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state)
693{
694 err_t err;
695 struct tcp_pcb *pcb;
696 lwiperf_state_tcp_t *s;
697
699
700 LWIP_ASSERT("state != NULL", state != NULL);
701
702 if (local_addr == NULL) {
703 return ERR_ARG;
704 }
705
706 s = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t);
707 if (s == NULL) {
708 return ERR_MEM;
709 }
710 memset(s, 0, sizeof(lwiperf_state_tcp_t));
711 s->base.tcp = 1;
712 s->base.server = 1;
713 s->base.related_master_state = related_master_state;
714 s->report_fn = report_fn;
715 s->report_arg = report_arg;
716
717 pcb = tcp_new_ip_type(LWIPERF_SERVER_IP_TYPE);
718 if (pcb == NULL) {
719 return ERR_MEM;
720 }
721 err = tcp_bind(pcb, local_addr, local_port);
722 if (err != ERR_OK) {
723 return err;
724 }
725 s->server_pcb = tcp_listen_with_backlog(pcb, 1);
726 if (s->server_pcb == NULL) {
727 if (pcb != NULL) {
728 tcp_close(pcb);
729 }
730 LWIPERF_FREE(lwiperf_state_tcp_t, s);
731 return ERR_MEM;
732 }
733 pcb = NULL;
734
735 tcp_arg(s->server_pcb, s);
736 tcp_accept(s->server_pcb, lwiperf_tcp_accept);
737
738 lwiperf_list_add(&s->base);
739 *state = s;
740 return ERR_OK;
741}
742
750void* lwiperf_start_tcp_client_default(const ip_addr_t* remote_addr,
751 lwiperf_report_fn report_fn, void* report_arg)
752{
754 report_fn, report_arg);
755}
756
764void* lwiperf_start_tcp_client(const ip_addr_t* remote_addr, u16_t remote_port,
765 enum lwiperf_client_type type, lwiperf_report_fn report_fn, void* report_arg)
766{
767 err_t ret;
768 lwiperf_settings_t settings;
769 lwiperf_state_tcp_t *state = NULL;
770
771 memset(&settings, 0, sizeof(settings));
772 switch (type) {
773 case LWIPERF_CLIENT:
774 /* Unidirectional tx only test */
775 settings.flags = 0;
776 break;
777 case LWIPERF_DUAL:
778 /* Do a bidirectional test simultaneously */
779 settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST | LWIPERF_FLAGS_ANSWER_NOW);
780 break;
781 case LWIPERF_TRADEOFF:
782 /* Do a bidirectional test individually */
783 settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST);
784 break;
785 default:
786 /* invalid argument */
787 return NULL;
788 }
789 settings.num_threads = htonl(1);
791 /* TODO: implement passing duration/amount of bytes to transfer */
792 settings.amount = htonl((u32_t)-1000);
793
794 ret = lwiperf_tx_start_impl(remote_addr, remote_port, &settings, report_fn, report_arg, NULL, &state);
795 if (ret == ERR_OK) {
796 LWIP_ASSERT("state != NULL", state != NULL);
797 if (type != LWIPERF_CLIENT) {
798 /* start corresponding server now */
799 lwiperf_state_tcp_t *server = NULL;
800 ret = lwiperf_start_tcp_server_impl(&state->conn_pcb->local_ip, LWIPERF_TCP_PORT_DEFAULT,
801 report_fn, report_arg, (lwiperf_state_base_t *)state, &server);
802 if (ret != ERR_OK) {
803 /* starting server failed, abort client */
805 return NULL;
806 }
807 /* make this server accept one connection only */
808 server->specific_remote = 1;
809 server->remote_addr = state->conn_pcb->remote_ip;
810 if (type == LWIPERF_TRADEOFF) {
811 /* tradeoff means that the remote host connects only after the client is done,
812 so keep the listen pcb open until the client is done */
813 server->client_tradeoff_mode = 1;
814 }
815 }
816 return state;
817 }
818 return NULL;
819}
820
825void
826lwiperf_abort(void *lwiperf_session)
827{
828 lwiperf_state_base_t *i, *dealloc, *last = NULL;
829
831
832 for (i = lwiperf_all_connections; i != NULL; ) {
833 if ((i == lwiperf_session) || (i->related_master_state == lwiperf_session)) {
834 dealloc = i;
835 i = i->next;
836 if (last != NULL) {
837 last->next = i;
838 }
839 LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */
840 } else {
841 last = i;
842 i = i->next;
843 }
844 }
845}
846
847#endif /* LWIP_TCP && LWIP_CALLBACK_API */
struct mke2fs_defaults settings[]
static int state
Definition: maze.c:121
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
#define lwip_htonl(x)
Definition: def.h:88
#define PP_HTONL(x)
Definition: def.h:92
#define NULL
Definition: types.h:112
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
void dealloc(int i, int no_throw)
Definition: ehthrow.cxx:33
time_t now
Definition: finger.c:65
#define ERR_MEM
Definition: fontsub.h:52
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int32_t s32_t
Definition: arch.h:130
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
#define LWIP_CONST_CAST(target_type, val)
Definition: arch.h:240
s8_t err_t
Definition: err.h:96
@ ERR_OK
Definition: err.h:55
@ ERR_VAL
Definition: err.h:67
@ ERR_ARG
Definition: err.h:88
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
u16_t pbuf_memcmp(const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
Definition: pbuf.c:1465
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
u32_t sys_now(void)
Definition: sys_arch.c:23
#define TCP_MSS
Definition: lwipopts.h:46
#define ip_addr_eq(addr1, addr2)
Definition: ip_addr.h:374
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:360
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
#define IP_GET_TYPE(ipaddr)
Definition: ip_addr.h:354
void * lwiperf_start_tcp_client(const ip_addr_t *remote_addr, u16_t remote_port, enum lwiperf_client_type type, lwiperf_report_fn report_fn, void *report_arg)
void(* lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port, u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
Definition: lwiperf.h:89
void * lwiperf_start_tcp_server(const ip_addr_t *local_addr, u16_t local_port, lwiperf_report_fn report_fn, void *report_arg)
void * lwiperf_start_tcp_client_default(const ip_addr_t *remote_addr, lwiperf_report_fn report_fn, void *report_arg)
#define LWIPERF_TCP_PORT_DEFAULT
Definition: lwiperf.h:47
lwiperf_client_type
Definition: lwiperf.h:68
@ LWIPERF_DUAL
Definition: lwiperf.h:72
@ LWIPERF_TRADEOFF
Definition: lwiperf.h:74
@ LWIPERF_CLIENT
Definition: lwiperf.h:70
lwiperf_report_type
Definition: lwiperf.h:51
@ LWIPERF_TCP_ABORTED_LOCAL_TXERROR
Definition: lwiperf.h:61
@ LWIPERF_TCP_DONE_CLIENT
Definition: lwiperf.h:55
@ LWIPERF_TCP_DONE_SERVER
Definition: lwiperf.h:53
@ LWIPERF_TCP_ABORTED_LOCAL
Definition: lwiperf.h:57
@ LWIPERF_TCP_ABORTED_LOCAL_DATAERROR
Definition: lwiperf.h:59
@ LWIPERF_TCP_ABORTED_REMOTE
Definition: lwiperf.h:63
void lwiperf_abort(void *lwiperf_session)
void * lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg)
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define htonl(x)
Definition: module.h:214
#define for
Definition: utility.h:88
static UINT UINT last
Definition: font.c:45
static ATOM item
Definition: dde.c:856
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
struct define * next
Definition: compiler.c:65
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
void * payload
Definition: pbuf.h:191
void tcp_close(struct sock *sk, long timeout)
struct sock * tcp_accept(struct sock *sk, int flags, int *err)
unsigned int tcp_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait)
static rfbScreenInfoPtr server
Definition: vnc.c:74
int ret
report_type
Definition: winetest.h:46