| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iperf_server.c
Go to the documentation of this file.
1 #include "lwip/debug.h"
2 #include "lwip/stats.h"
3 #include "lwip/tcp.h"
4
5 /*---------------------------------------------------------------------------*/
6 /* local defines */
7 /*---------------------------------------------------------------------------*/
8 #define IPERF_SERVER_PORT 5001
9
10 /*---------------------------------------------------------------------------*/
11 /* local data */
12 /*---------------------------------------------------------------------------*/
13 #if LWIP_TCP
14
15 static struct tcp_pcb *iperf_pcb;
16
17 enum iperfserver_states
18 {
19 ES_NONE = 0,
20 ES_ACCEPTED,
21 ES_RECEIVED,
22 ES_CLOSING
23 };
24
25 struct iperfserver_state
26 {
27 u8_t state;
28 u8_t retries;
29 struct tcp_pcb *pcb;
30 /* pbuf (chain) to recycle */
31 struct pbuf *p;
32 };
33
34 /*---------------------------------------------------------------------------*/
35 /* local functions */
36 /*---------------------------------------------------------------------------*/
37 static err_t iperfserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
38 static err_t iperfserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
39 static void iperfserver_error(void *arg, err_t err);
40 static err_t iperfserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
41 static void iperfserver_send(struct tcp_pcb *tpcb, struct iperfserver_state *es);
42 static void iperfserver_close(struct tcp_pcb *tpcb, struct iperfserver_state *es);
43
44 void
45 iperf_server_init(void)
46 {
47 iperf_pcb = tcp_new();
48 if (iperf_pcb != NULL)
49 {
50 err_t err;
51
52 err = tcp_bind(iperf_pcb, IP_ADDR_ANY, IPERF_SERVER_PORT);
53 if (err == ERR_OK)
54 {
55 iperf_pcb = tcp_listen(iperf_pcb);
56 tcp_accept(iperf_pcb, iperfserver_accept);
57 }
58 else
59 {
60 /* abort? output diagnostic? */
61 }
62 }
63 else
64 {
65 /* abort? output diagnostic? */
66 }
67 }
68
69
70 err_t
71 iperfserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
72 {
73 err_t ret_err;
74 struct iperfserver_state *es;
75
76 LWIP_UNUSED_ARG(arg);
77 LWIP_UNUSED_ARG(err);
78
79 /* commonly observed practive to call tcp_setprio(), why? */
80 tcp_setprio(newpcb, TCP_PRIO_MIN);
81
82 es = (struct iperfserver_state *)mem_malloc(sizeof(struct iperfserver_state));
83 if (es != NULL)
84 {
85 es->state = ES_ACCEPTED;
86 es->pcb = newpcb;
87 es->retries = 0;
88 es->p = NULL;
89 /* pass newly allocated es to our callbacks */
90 tcp_arg(newpcb, es);
91 tcp_recv(newpcb, iperfserver_recv);
92 tcp_err(newpcb, iperfserver_error);
93
94 ret_err = ERR_OK;
95 }
96 else
97 {
98 ret_err = ERR_MEM;
99 }
100 return ret_err;
101 }
102
103 err_t
104 iperfserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
105 {
106 struct iperfserver_state *es;
107 err_t ret_err;
108 u16_t plen;
109
110 LWIP_ASSERT("arg != NULL",arg != NULL);
111 es = (struct iperfserver_state *)arg;
112 if (p == NULL)
113 {
114 /* remote host closed connection */
115 es->state = ES_CLOSING;
116 iperfserver_close(tpcb, es);
117 ret_err = ERR_OK;
118 }
119 else if(err != ERR_OK)
120 {
121 /* cleanup, for unkown reason */
122 if (p != NULL)
123 {
124 es->p = NULL;
125 pbuf_free(p);
126 }
127 ret_err = err;
128 }
129 else if(es->state == ES_ACCEPTED)
130 {
131 es->p = p;
132 plen = es->p->len;
133 pbuf_free(es->p); //receive the package and discard it silently for testing reception bandwidth
134 tcp_recved(tpcb, plen);
135
136 ret_err = ERR_OK;
137 }
138 else if(es->state == ES_CLOSING)
139 {
140 /* odd case, remote side closing twice, trash data */
141 tcp_recved(tpcb, p->tot_len);
142 es->p = NULL;
143 pbuf_free(p);
144 ret_err = ERR_OK;
145 }
146 else
147 {
148 /* unkown es->state, trash data */
149 tcp_recved(tpcb, p->tot_len);
150 es->p = NULL;
151 pbuf_free(p);
152 ret_err = ERR_OK;
153 }
154 return ret_err;
155 }
156
157 void
158 iperfserver_error(void *arg, err_t err)
159 {
160 struct iperfserver_state *es;
161
162 LWIP_UNUSED_ARG(err);
163
164 es = (struct iperfserver_state *)arg;
165 if (es != NULL)
166 {
167 mem_free(es);
168 }
169 }
170
171 err_t
172 iperfserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
173 {
174 struct iperfserver_state *es;
175
176 LWIP_UNUSED_ARG(len);
177
178 es = (struct iperfserver_state *)arg;
179 es->retries = 0;
180
181 if(es->p != NULL)
182 {
183 /* still got pbufs to send */
184 tcp_sent(tpcb, iperfserver_sent);
185 iperfserver_send(tpcb, es);
186 }
187 else
188 {
189 /* no more pbufs to send */
190 if(es->state == ES_CLOSING)
191 {
192 iperfserver_close(tpcb, es);
193 }
194 }
195 return ERR_OK;
196 }
197
198 void
199 iperfserver_send(struct tcp_pcb *tpcb, struct iperfserver_state *es)
200 {
201 struct pbuf *ptr;
202 err_t wr_err = ERR_OK;
203
204 while ((wr_err == ERR_OK) &&
205 (es->p != NULL) &&
206 (es->p->len <= tcp_sndbuf(tpcb)))
207 {
208 ptr = es->p;
209
210 /* enqueue data for transmission */
211 wr_err = tcp_write(tpcb, ptr->payload, ptr->len, TCP_WRITE_FLAG_COPY);
212 if (wr_err == ERR_OK)
213 {
214 u16_t plen;
215 u8_t freed;
216
217 plen = ptr->len;
218 /* continue with next pbuf in chain (if any) */
219 es->p = ptr->next;
220 if(es->p != NULL)
221 {
222 /* new reference! */
223 pbuf_ref(es->p);
224 }
225 /* chop first pbuf from chain */
226 do
227 {
228 /* try hard to free pbuf */
229 freed = pbuf_free(ptr);
230 }
231 while(freed == 0);
232 /* we can read more data now */
233 tcp_recved(tpcb, plen);
234 }
235 else if(wr_err == ERR_MEM)
236 {
237 /* we are low on memory, try later / harder, defer to poll */
238 es->p = ptr;
239 }
240 else
241 {
242 /* other problem ?? */
243 }
244 }
245 }
246
247 void
248 iperfserver_close(struct tcp_pcb *tpcb, struct iperfserver_state *es)
249 {
250 tcp_arg(tpcb, NULL);
251 tcp_sent(tpcb, NULL);
252 tcp_recv(tpcb, NULL);
253 tcp_err(tpcb, NULL);
254
255
256 if (es != NULL)
257 {
258 mem_free(es);
259 }
260 tcp_close(tpcb);
261 }
262
263 #endif /* LWIP_TCP */
264 /*****************************************************************************/
265 /* END OF FILE */
266