Contiki 2.5
psock.c
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 Contiki operating system.
30  *
31  * Author: Adam Dunkels <adam@sics.se>
32  *
33  * $Id: psock.c,v 1.12 2010/06/15 14:19:22 nifi Exp $
34  */
35 
36 #include <string.h>
37 
38 #include "net/psock.h"
39 
40 #define STATE_NONE 0
41 #define STATE_ACKED 1
42 #define STATE_READ 2
43 #define STATE_BLOCKED_NEWDATA 3
44 #define STATE_BLOCKED_CLOSE 4
45 #define STATE_BLOCKED_SEND 5
46 #define STATE_DATA_SENT 6
47 
48 /*
49  * Return value of the buffering functions that indicates that a
50  * buffer was not filled by incoming data.
51  *
52  */
53 #define BUF_NOT_FULL 0
54 #define BUF_NOT_FOUND 0
55 
56 /*
57  * Return value of the buffering functions that indicates that a
58  * buffer was completely filled by incoming data.
59  *
60  */
61 #define BUF_FULL 1
62 
63 /*
64  * Return value of the buffering functions that indicates that an
65  * end-marker byte was found.
66  *
67  */
68 #define BUF_FOUND 2
69 
70 /*---------------------------------------------------------------------------*/
71 static void
72 buf_setup(struct psock_buf *buf,
73  u8_t *bufptr, u16_t bufsize)
74 {
75  buf->ptr = bufptr;
76  buf->left = bufsize;
77 }
78 /*---------------------------------------------------------------------------*/
79 static u8_t
80 buf_bufdata(struct psock_buf *buf, u16_t len,
81  u8_t **dataptr, u16_t *datalen)
82 {
83  if(*datalen < buf->left) {
84  memcpy(buf->ptr, *dataptr, *datalen);
85  buf->ptr += *datalen;
86  buf->left -= *datalen;
87  *dataptr += *datalen;
88  *datalen = 0;
89  return BUF_NOT_FULL;
90  } else if(*datalen == buf->left) {
91  memcpy(buf->ptr, *dataptr, *datalen);
92  buf->ptr += *datalen;
93  buf->left = 0;
94  *dataptr += *datalen;
95  *datalen = 0;
96  return BUF_FULL;
97  } else {
98  memcpy(buf->ptr, *dataptr, buf->left);
99  buf->ptr += buf->left;
100  *datalen -= buf->left;
101  *dataptr += buf->left;
102  buf->left = 0;
103  return BUF_FULL;
104  }
105 }
106 /*---------------------------------------------------------------------------*/
107 static u8_t
108 buf_bufto(CC_REGISTER_ARG struct psock_buf *buf, u8_t endmarker,
109  CC_REGISTER_ARG u8_t **dataptr, CC_REGISTER_ARG u16_t *datalen)
110 {
111  u8_t c;
112  while(buf->left > 0 && *datalen > 0) {
113  c = *buf->ptr = **dataptr;
114  ++*dataptr;
115  ++buf->ptr;
116  --*datalen;
117  --buf->left;
118 
119  if(c == endmarker) {
120  return BUF_FOUND;
121  }
122  }
123 
124  if(*datalen == 0) {
125  return BUF_NOT_FOUND;
126  }
127 
128  while(*datalen > 0) {
129  c = **dataptr;
130  --*datalen;
131  ++*dataptr;
132 
133  if(c == endmarker) {
134  return BUF_FOUND | BUF_FULL;
135  }
136  }
137 
138  return BUF_FULL;
139 }
140 /*---------------------------------------------------------------------------*/
141 static char
142 data_is_sent_and_acked(CC_REGISTER_ARG struct psock *s)
143 {
144  /* If data has previously been sent, and the data has been acked, we
145  increase the send pointer and call send_data() to send more
146  data. */
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 0;
155  } else if(s->state == STATE_DATA_SENT && uip_acked()) {
156  if(s->sendlen > uip_mss()) {
157  s->sendlen -= uip_mss();
158  s->sendptr += uip_mss();
159  } else {
160  s->sendptr += s->sendlen;
161  s->sendlen = 0;
162  }
163  s->state = STATE_ACKED;
164  return 1;
165  }
166  return 0;
167 }
168 /*---------------------------------------------------------------------------*/
169 PT_THREAD(psock_send(CC_REGISTER_ARG struct psock *s, const uint8_t *buf,
170  unsigned int len))
171 {
172  PT_BEGIN(&s->psockpt);
173 
174  /* If there is no data to send, we exit immediately. */
175  if(len == 0) {
176  PT_EXIT(&s->psockpt);
177  }
178 
179  /* Save the length of and a pointer to the data that is to be
180  sent. */
181  s->sendptr = buf;
182  s->sendlen = len;
183 
184  s->state = STATE_NONE;
185 
186  /* We loop here until all data is sent. The s->sendlen variable is
187  updated by the data_sent() function. */
188  while(s->sendlen > 0) {
189 
190  /*
191  * The protothread will wait here until all data has been
192  * acknowledged and sent (data_is_acked_and_send() returns 1).
193  */
194  PT_WAIT_UNTIL(&s->psockpt, data_is_sent_and_acked(s));
195  }
196 
197  s->state = STATE_NONE;
198 
199  PT_END(&s->psockpt);
200 }
201 /*---------------------------------------------------------------------------*/
202 PT_THREAD(psock_generator_send(CC_REGISTER_ARG struct psock *s,
203  unsigned short (*generate)(void *), void *arg))
204 {
205  PT_BEGIN(&s->psockpt);
206 
207  /* Ensure that there is a generator function to call. */
208  if(generate == NULL) {
209  PT_EXIT(&s->psockpt);
210  }
211 
212  s->state = STATE_NONE;
213  do {
214  /* Call the generator function to generate the data in the
215  uip_appdata buffer. */
216  s->sendlen = generate(arg);
217  s->sendptr = uip_appdata;
218 
219  if(s->sendlen > uip_mss()) {
220  uip_send(s->sendptr, uip_mss());
221  } else {
222  uip_send(s->sendptr, s->sendlen);
223  }
224  s->state = STATE_DATA_SENT;
225 
226  /* Wait until all data is sent and acknowledged. */
227  // if (!s->sendlen) break; //useful debugging aid
228  PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit());
229  } while(!uip_acked());
230 
231  s->state = STATE_NONE;
232 
233  PT_END(&s->psockpt);
234 }
235 /*---------------------------------------------------------------------------*/
236 u16_t
237 psock_datalen(struct psock *psock)
238 {
239  return psock->bufsize - psock->buf.left;
240 }
241 /*---------------------------------------------------------------------------*/
242 char
243 psock_newdata(struct psock *s)
244 {
245  if(s->readlen > 0) {
246  /* There is data in the uip_appdata buffer that has not yet been
247  read with the PSOCK_READ functions. */
248  return 1;
249  } else if(s->state == STATE_READ) {
250  /* All data in uip_appdata buffer already consumed. */
251  s->state = STATE_BLOCKED_NEWDATA;
252  return 0;
253  } else if(uip_newdata()) {
254  /* There is new data that has not been consumed. */
255  return 1;
256  } else {
257  /* There is no new data. */
258  return 0;
259  }
260 }
261 /*---------------------------------------------------------------------------*/
262 PT_THREAD(psock_readto(CC_REGISTER_ARG struct psock *psock, unsigned char c))
263 {
264  PT_BEGIN(&psock->psockpt);
265 
266  buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
267 
268  /* XXX: Should add buf_checkmarker() before do{} loop, if
269  incoming data has been handled while waiting for a write. */
270 
271  do {
272  if(psock->readlen == 0) {
273  PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
274  psock->state = STATE_READ;
275  psock->readptr = (u8_t *)uip_appdata;
276  psock->readlen = uip_datalen();
277  }
278  } while((buf_bufto(&psock->buf, c,
279  &psock->readptr,
280  &psock->readlen) & BUF_FOUND) == 0);
281 
282  if(psock_datalen(psock) == 0) {
283  psock->state = STATE_NONE;
284  PT_RESTART(&psock->psockpt);
285  }
286  PT_END(&psock->psockpt);
287 }
288 /*---------------------------------------------------------------------------*/
289 PT_THREAD(psock_readbuf_len(CC_REGISTER_ARG struct psock *psock, uint16_t len))
290 {
291  PT_BEGIN(&psock->psockpt);
292 
293  buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
294 
295  /* XXX: Should add buf_checkmarker() before do{} loop, if
296  incoming data has been handled while waiting for a write. */
297 
298  /* read len bytes or to end of data */
299  do {
300  if(psock->readlen == 0) {
301  PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
302  psock->state = STATE_READ;
303  psock->readptr = (u8_t *)uip_appdata;
304  psock->readlen = uip_datalen();
305  }
306  } while(buf_bufdata(&psock->buf, psock->bufsize,
307  &psock->readptr, &psock->readlen) == BUF_NOT_FULL &&
308  psock_datalen(psock) < len);
309 
310  if(psock_datalen(psock) == 0) {
311  psock->state = STATE_NONE;
312  PT_RESTART(&psock->psockpt);
313  }
314  PT_END(&psock->psockpt);
315 }
316 
317 /*---------------------------------------------------------------------------*/
318 void
319 psock_init(CC_REGISTER_ARG struct psock *psock,
320  uint8_t *buffer, unsigned int buffersize)
321 {
322  psock->state = STATE_NONE;
323  psock->readlen = 0;
324  psock->bufptr = buffer;
325  psock->bufsize = buffersize;
326  buf_setup(&psock->buf, buffer, buffersize);
327  PT_INIT(&psock->pt);
328  PT_INIT(&psock->psockpt);
329 }
330 /*---------------------------------------------------------------------------*/