source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/contrib-2.1.0/apps/tcpecho_raw/tcpecho_raw.c

Last change on this file was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 7.5 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25 * OF SUCH DAMAGE.
26 *
27 * This file is part of and a contribution to the lwIP TCP/IP stack.
28 *
29 * Credits go to Adam Dunkels (and the current maintainers) of this software.
30 *
31 * Christiaan Simons rewrote this file to get a more stable echo example.
32 */
33
34/**
35 * @file
36 * TCP echo server example using raw API.
37 *
38 * Echos all bytes sent by connecting client,
39 * and passively closes when client is done.
40 *
41 */
42
43#include "lwip/opt.h"
44#include "lwip/debug.h"
45#include "lwip/stats.h"
46#include "lwip/tcp.h"
47#include "tcpecho_raw.h"
48
49#if LWIP_TCP && LWIP_CALLBACK_API
50
51static struct tcp_pcb *tcpecho_raw_pcb;
52
53enum tcpecho_raw_states
54{
55 ES_NONE = 0,
56 ES_ACCEPTED,
57 ES_RECEIVED,
58 ES_CLOSING
59};
60
61struct tcpecho_raw_state
62{
63 u8_t state;
64 u8_t retries;
65 struct tcp_pcb *pcb;
66 /* pbuf (chain) to recycle */
67 struct pbuf *p;
68};
69
70static void
71tcpecho_raw_free(struct tcpecho_raw_state *es)
72{
73 if (es != NULL) {
74 if (es->p) {
75 /* free the buffer chain if present */
76 pbuf_free(es->p);
77 }
78
79 mem_free(es);
80 }
81}
82
83static void
84tcpecho_raw_close(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es)
85{
86 tcp_arg(tpcb, NULL);
87 tcp_sent(tpcb, NULL);
88 tcp_recv(tpcb, NULL);
89 tcp_err(tpcb, NULL);
90 tcp_poll(tpcb, NULL, 0);
91
92 tcpecho_raw_free(es);
93
94 tcp_close(tpcb);
95}
96
97static void
98tcpecho_raw_send(struct tcp_pcb *tpcb, struct tcpecho_raw_state *es)
99{
100 struct pbuf *ptr;
101 err_t wr_err = ERR_OK;
102
103 while ((wr_err == ERR_OK) &&
104 (es->p != NULL) &&
105 (es->p->len <= tcp_sndbuf(tpcb))) {
106 ptr = es->p;
107
108 /* enqueue data for transmission */
109 wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
110 if (wr_err == ERR_OK) {
111 u16_t plen;
112
113 plen = ptr->len;
114 /* continue with next pbuf in chain (if any) */
115 es->p = ptr->next;
116 if(es->p != NULL) {
117 /* new reference! */
118 pbuf_ref(es->p);
119 }
120 /* chop first pbuf from chain */
121 pbuf_free(ptr);
122 /* we can read more data now */
123 tcp_recved(tpcb, plen);
124 } else if(wr_err == ERR_MEM) {
125 /* we are low on memory, try later / harder, defer to poll */
126 es->p = ptr;
127 } else {
128 /* other problem ?? */
129 }
130 }
131}
132
133static void
134tcpecho_raw_error(void *arg, err_t err)
135{
136 struct tcpecho_raw_state *es;
137
138 LWIP_UNUSED_ARG(err);
139
140 es = (struct tcpecho_raw_state *)arg;
141
142 tcpecho_raw_free(es);
143}
144
145static err_t
146tcpecho_raw_poll(void *arg, struct tcp_pcb *tpcb)
147{
148 err_t ret_err;
149 struct tcpecho_raw_state *es;
150
151 es = (struct tcpecho_raw_state *)arg;
152 if (es != NULL) {
153 if (es->p != NULL) {
154 /* there is a remaining pbuf (chain) */
155 tcpecho_raw_send(tpcb, es);
156 } else {
157 /* no remaining pbuf (chain) */
158 if(es->state == ES_CLOSING) {
159 tcpecho_raw_close(tpcb, es);
160 }
161 }
162 ret_err = ERR_OK;
163 } else {
164 /* nothing to be done */
165 tcp_abort(tpcb);
166 ret_err = ERR_ABRT;
167 }
168 return ret_err;
169}
170
171static err_t
172tcpecho_raw_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
173{
174 struct tcpecho_raw_state *es;
175
176 LWIP_UNUSED_ARG(len);
177
178 es = (struct tcpecho_raw_state *)arg;
179 es->retries = 0;
180
181 if(es->p != NULL) {
182 /* still got pbufs to send */
183 tcp_sent(tpcb, tcpecho_raw_sent);
184 tcpecho_raw_send(tpcb, es);
185 } else {
186 /* no more pbufs to send */
187 if(es->state == ES_CLOSING) {
188 tcpecho_raw_close(tpcb, es);
189 }
190 }
191 return ERR_OK;
192}
193
194static err_t
195tcpecho_raw_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
196{
197 struct tcpecho_raw_state *es;
198 err_t ret_err;
199
200 LWIP_ASSERT("arg != NULL",arg != NULL);
201 es = (struct tcpecho_raw_state *)arg;
202 if (p == NULL) {
203 /* remote host closed connection */
204 es->state = ES_CLOSING;
205 if(es->p == NULL) {
206 /* we're done sending, close it */
207 tcpecho_raw_close(tpcb, es);
208 } else {
209 /* we're not done yet */
210 tcpecho_raw_send(tpcb, es);
211 }
212 ret_err = ERR_OK;
213 } else if(err != ERR_OK) {
214 /* cleanup, for unknown reason */
215 if (p != NULL) {
216 pbuf_free(p);
217 }
218 ret_err = err;
219 }
220 else if(es->state == ES_ACCEPTED) {
221 /* first data chunk in p->payload */
222 es->state = ES_RECEIVED;
223 /* store reference to incoming pbuf (chain) */
224 es->p = p;
225 tcpecho_raw_send(tpcb, es);
226 ret_err = ERR_OK;
227 } else if (es->state == ES_RECEIVED) {
228 /* read some more data */
229 if(es->p == NULL) {
230 es->p = p;
231 tcpecho_raw_send(tpcb, es);
232 } else {
233 struct pbuf *ptr;
234
235 /* chain pbufs to the end of what we recv'ed previously */
236 ptr = es->p;
237 pbuf_cat(ptr,p);
238 }
239 ret_err = ERR_OK;
240 } else {
241 /* unkown es->state, trash data */
242 tcp_recved(tpcb, p->tot_len);
243 pbuf_free(p);
244 ret_err = ERR_OK;
245 }
246 return ret_err;
247}
248
249static err_t
250tcpecho_raw_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
251{
252 err_t ret_err;
253 struct tcpecho_raw_state *es;
254
255 LWIP_UNUSED_ARG(arg);
256 if ((err != ERR_OK) || (newpcb == NULL)) {
257 return ERR_VAL;
258 }
259
260 /* Unless this pcb should have NORMAL priority, set its priority now.
261 When running out of pcbs, low priority pcbs can be aborted to create
262 new pcbs of higher priority. */
263 tcp_setprio(newpcb, TCP_PRIO_MIN);
264
265 es = (struct tcpecho_raw_state *)mem_malloc(sizeof(struct tcpecho_raw_state));
266 if (es != NULL) {
267 es->state = ES_ACCEPTED;
268 es->pcb = newpcb;
269 es->retries = 0;
270 es->p = NULL;
271 /* pass newly allocated es to our callbacks */
272 tcp_arg(newpcb, es);
273 tcp_recv(newpcb, tcpecho_raw_recv);
274 tcp_err(newpcb, tcpecho_raw_error);
275 tcp_poll(newpcb, tcpecho_raw_poll, 0);
276 tcp_sent(newpcb, tcpecho_raw_sent);
277 ret_err = ERR_OK;
278 } else {
279 ret_err = ERR_MEM;
280 }
281 return ret_err;
282}
283
284void
285tcpecho_raw_init(void)
286{
287 tcpecho_raw_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
288 if (tcpecho_raw_pcb != NULL) {
289 err_t err;
290
291 err = tcp_bind(tcpecho_raw_pcb, IP_ANY_TYPE, 7);
292 if (err == ERR_OK) {
293 tcpecho_raw_pcb = tcp_listen(tcpecho_raw_pcb);
294 tcp_accept(tcpecho_raw_pcb, tcpecho_raw_accept);
295 } else {
296 /* abort? output diagnostic? */
297 }
298 } else {
299 /* abort? output diagnostic? */
300 }
301}
302
303#endif /* LWIP_TCP && LWIP_CALLBACK_API */
Note: See TracBrowser for help on using the repository browser.