source: uKadecot/trunk/uip/net/ip/psock.c

Last change on this file was 158, checked in by coas-nagasima, 8 years ago

インクルードのパス指定をContikiに合わせ変更。
整数型の型名をContikiに合わせ変更。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 9.7 KB
Line 
1/*
2 * Copyright (c) 2004, Swedish Institute of Computer Science.
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 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the uIP TCP/IP stack
30 *
31 * Author: Adam Dunkels <adam@sics.se>
32 *
33 * $Id: psock.c 158 2016-02-20 13:43:32Z coas-nagasima $
34 */
35
36#include <stdio.h>
37#include <string.h>
38
39#include "net/ip/uipopt.h"
40#include "net/ip/psock.h"
41#include "net/ip/uip.h"
42
43#define STATE_NONE 0
44#define STATE_ACKED 1
45#define STATE_READ 2
46#define STATE_BLOCKED_NEWDATA 3
47#define STATE_BLOCKED_CLOSE 4
48#define STATE_BLOCKED_SEND 5
49#define STATE_DATA_SENT 6
50
51/*
52 * Return value of the buffering functions that indicates that a
53 * buffer was not filled by incoming data.
54 *
55 */
56#define BUF_NOT_FULL 0
57#define BUF_NOT_FOUND 0
58
59/*
60 * Return value of the buffering functions that indicates that a
61 * buffer was completely filled by incoming data.
62 *
63 */
64#define BUF_FULL 1
65
66/*
67 * Return value of the buffering functions that indicates that an
68 * end-marker byte was found.
69 *
70 */
71#define BUF_FOUND 2
72
73/*---------------------------------------------------------------------------*/
74static void
75buf_setup(struct psock_buf *buf,
76 uint8_t *bufptr, uint16_t bufsize)
77{
78 buf->ptr = bufptr;
79 buf->left = bufsize;
80}
81/*---------------------------------------------------------------------------*/
82static uint8_t
83buf_bufdata(struct psock_buf *buf, uint16_t len,
84 uint8_t **dataptr, uint16_t *datalen)
85{
86 if(*datalen < buf->left) {
87 memcpy(buf->ptr, *dataptr, *datalen);
88 buf->ptr += *datalen;
89 buf->left -= *datalen;
90 *dataptr += *datalen;
91 *datalen = 0;
92 return BUF_NOT_FULL;
93 } else if(*datalen == buf->left) {
94 memcpy(buf->ptr, *dataptr, *datalen);
95 buf->ptr += *datalen;
96 buf->left = 0;
97 *dataptr += *datalen;
98 *datalen = 0;
99 return BUF_FULL;
100 } else {
101 memcpy(buf->ptr, *dataptr, buf->left);
102 buf->ptr += buf->left;
103 *datalen -= buf->left;
104 *dataptr += buf->left;
105 buf->left = 0;
106 return BUF_FULL;
107 }
108}
109/*---------------------------------------------------------------------------*/
110static uint8_t
111buf_bufto(register struct psock_buf *buf, uint8_t endmarker,
112 register uint8_t **dataptr, register uint16_t *datalen)
113{
114 uint8_t c;
115 while(buf->left > 0 && *datalen > 0) {
116 c = *buf->ptr = **dataptr;
117 ++*dataptr;
118 ++buf->ptr;
119 --*datalen;
120 --buf->left;
121
122 if(c == endmarker) {
123 return BUF_FOUND;
124 }
125 }
126
127 if(*datalen == 0) {
128 return BUF_NOT_FOUND;
129 }
130
131 while(*datalen > 0) {
132 c = **dataptr;
133 --*datalen;
134 ++*dataptr;
135
136 if(c == endmarker) {
137 return BUF_FOUND | BUF_FULL;
138 }
139 }
140
141 return BUF_FULL;
142}
143/*---------------------------------------------------------------------------*/
144static char
145send_data(register struct psock *s)
146{
147 if(s->state != STATE_DATA_SENT || uip_rexmit()) {
148 if(s->sendlen > uip_mss()) {
149 uip_send(s->sendptr, uip_mss());
150 } else {
151 uip_send(s->sendptr, s->sendlen);
152 }
153 s->state = STATE_DATA_SENT;
154 return 1;
155 }
156 return 0;
157}
158/*---------------------------------------------------------------------------*/
159static char
160data_acked(register struct psock *s)
161{
162 if(s->state == STATE_DATA_SENT && uip_acked()) {
163 if(s->sendlen > uip_mss()) {
164 s->sendlen -= uip_mss();
165 s->sendptr += uip_mss();
166 } else {
167 s->sendptr += s->sendlen;
168 s->sendlen = 0;
169 }
170 s->state = STATE_ACKED;
171 return 1;
172 }
173 return 0;
174}
175/*---------------------------------------------------------------------------*/
176PT_THREAD(psock_send(register struct psock *s, const char *buf,
177 unsigned int len))
178{
179 PT_BEGIN(&s->psockpt);
180
181 /* If there is no data to send, we exit immediately. */
182 if(len == 0) {
183 PT_EXIT(&s->psockpt);
184 }
185
186 /* Save the length of and a pointer to the data that is to be
187 sent. */
188 s->sendptr = buf;
189 s->sendlen = len;
190
191 s->state = STATE_NONE;
192
193 /* We loop here until all data is sent. The s->sendlen variable is
194 updated by the data_sent() function. */
195 while(s->sendlen > 0) {
196
197 /*
198 * The condition for this PT_WAIT_UNTIL is a little tricky: the
199 * protothread will wait here until all data has been acknowledged
200 * (data_acked() returns true) and until all data has been sent
201 * (send_data() returns true). The two functions data_acked() and
202 * send_data() must be called in succession to ensure that all
203 * data is sent. Therefore the & operator is used instead of the
204 * && operator, which would cause only the data_acked() function
205 * to be called when it returns false.
206 */
207 PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
208 }
209
210 s->state = STATE_NONE;
211
212 PT_END(&s->psockpt);
213}
214/*---------------------------------------------------------------------------*/
215PT_THREAD(psock_generator_send(register struct psock *s,
216 unsigned short (*generate)(void *), void *arg))
217{
218 PT_BEGIN(&s->psockpt);
219
220 /* Ensure that there is a generator function to call. */
221 if(generate == NULL) {
222 PT_EXIT(&s->psockpt);
223 }
224
225 /* Call the generator function to generate the data in the
226 uip_appdata buffer. */
227 s->sendlen = generate(arg);
228 s->sendptr = uip_appdata;
229
230 s->state = STATE_NONE;
231 do {
232 /* Call the generator function again if we are called to perform a
233 retransmission. */
234 if(uip_rexmit()) {
235 generate(arg);
236 }
237 /* Wait until all data is sent and acknowledged. */
238 PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
239 } while(s->sendlen > 0);
240
241 s->state = STATE_NONE;
242
243 PT_END(&s->psockpt);
244}
245/*---------------------------------------------------------------------------*/
246uint16_t
247psock_datalen(struct psock *psock)
248{
249 return psock->bufsize - psock->buf.left;
250}
251/*---------------------------------------------------------------------------*/
252char
253psock_newdata(struct psock *s)
254{
255 if(s->readlen > 0) {
256 /* There is data in the uip_appdata buffer that has not yet been
257 read with the PSOCK_READ functions. */
258 return 1;
259 } else if(s->state == STATE_READ) {
260 /* All data in uip_appdata buffer already consumed. */
261 s->state = STATE_BLOCKED_NEWDATA;
262 return 0;
263 } else if(uip_newdata()) {
264 /* There is new data that has not been consumed. */
265 return 1;
266 } else {
267 /* There is no new data. */
268 return 0;
269 }
270}
271/*---------------------------------------------------------------------------*/
272PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
273{
274 PT_BEGIN(&psock->psockpt);
275
276 buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
277
278 /* XXX: Should add buf_checkmarker() before do{} loop, if
279 incoming data has been handled while waiting for a write. */
280
281 do {
282 if(psock->readlen == 0) {
283 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
284 psock->state = STATE_READ;
285 psock->readptr = (uint8_t *)uip_appdata;
286 psock->readlen = uip_datalen();
287 }
288 } while((buf_bufto(&psock->buf, c,
289 &psock->readptr,
290 &psock->readlen) & BUF_FOUND) == 0);
291
292 if(psock_datalen(psock) == 0) {
293 psock->state = STATE_NONE;
294 PT_RESTART(&psock->psockpt);
295 }
296 PT_END(&psock->psockpt);
297}
298/*---------------------------------------------------------------------------*/
299PT_THREAD(psock_readbuf(register struct psock *psock))
300{
301 PT_BEGIN(&psock->psockpt);
302
303 buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
304
305 /* XXX: Should add buf_checkmarker() before do{} loop, if
306 incoming data has been handled while waiting for a write. */
307
308 do {
309 if(psock->readlen == 0) {
310 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
311 printf("Waited for newdata\n");
312 psock->state = STATE_READ;
313 psock->readptr = (uint8_t *)uip_appdata;
314 psock->readlen = uip_datalen();
315 }
316 } while(buf_bufdata(&psock->buf, psock->bufsize,
317 &psock->readptr,
318 &psock->readlen) != BUF_FULL);
319
320 if(psock_datalen(psock) == 0) {
321 psock->state = STATE_NONE;
322 PT_RESTART(&psock->psockpt);
323 }
324 PT_END(&psock->psockpt);
325}
326/*---------------------------------------------------------------------------*/
327void
328psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
329{
330 psock->state = STATE_NONE;
331 psock->readlen = 0;
332 psock->bufptr = buffer;
333 psock->bufsize = buffersize;
334 buf_setup(&psock->buf, buffer, buffersize);
335 PT_INIT(&psock->pt);
336 PT_INIT(&psock->psockpt);
337}
338/*---------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.