root/webserver/example/freeRTOS/Demo/Common/ethernet/uIP/uip-1.0/uip/psock.c

Revision 14, 10.0 kB (checked in by phil, 15 years ago)

added unmodified FreeRTOS package V5.4.1 with only web srv demo source for LPC2368 for CrossWorks?

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,v 1.2 2006/06/12 08:00:30 adam Exp $
34  */
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "uipopt.h"
40 #include "psock.h"
41 #include "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 /*---------------------------------------------------------------------------*/
74 static void
75 buf_setup(struct psock_buf *buf,
76           u8_t *bufptr, u16_t bufsize)
77 {
78   buf->ptr = bufptr;
79   buf->left = bufsize;
80 }
81 /*---------------------------------------------------------------------------*/
82 static u8_t
83 buf_bufdata(struct psock_buf *buf, u16_t len,
84             u8_t **dataptr, u16_t *datalen)
85 {
86   ( void ) len;
87   if(*datalen < buf->left) {
88     memcpy(buf->ptr, *dataptr, *datalen);
89     buf->ptr += *datalen;
90     buf->left -= *datalen;
91     *dataptr += *datalen;
92     *datalen = 0;
93     return BUF_NOT_FULL;
94   } else if(*datalen == buf->left) {
95     memcpy(buf->ptr, *dataptr, *datalen);
96     buf->ptr += *datalen;
97     buf->left = 0;
98     *dataptr += *datalen;
99     *datalen = 0;
100     return BUF_FULL;
101   } else {
102     memcpy(buf->ptr, *dataptr, buf->left);
103     buf->ptr += buf->left;
104     *datalen -= buf->left;
105     *dataptr += buf->left;
106     buf->left = 0;
107     return BUF_FULL;
108   }
109 }
110 /*---------------------------------------------------------------------------*/
111 static u8_t
112 buf_bufto(register struct psock_buf *buf, u8_t endmarker,
113           register u8_t **dataptr, register u16_t *datalen)
114 {
115   u8_t c;
116   while(buf->left > 0 && *datalen > 0) {
117     c = *buf->ptr = **dataptr;
118     ++*dataptr;
119     ++buf->ptr;
120     --*datalen;
121     --buf->left;
122    
123     if(c == endmarker) {
124       return BUF_FOUND;
125     }
126   }
127
128   if(*datalen == 0) {
129     return BUF_NOT_FOUND;
130   }
131
132   while(*datalen > 0) {
133     c = **dataptr;
134     --*datalen;
135     ++*dataptr;
136    
137     if(c == endmarker) {
138       return BUF_FOUND | BUF_FULL;
139     }
140   }
141  
142   return BUF_FULL;
143 }
144 /*---------------------------------------------------------------------------*/
145 static char
146 send_data(register struct psock *s)
147 {
148   if(s->state != STATE_DATA_SENT || uip_rexmit()) {
149     if(s->sendlen > uip_mss()) {
150       uip_send(s->sendptr, uip_mss());
151     } else {
152       uip_send(s->sendptr, s->sendlen);
153     }
154     s->state = STATE_DATA_SENT;
155     return 1;
156   }
157   return 0;
158 }
159 /*---------------------------------------------------------------------------*/
160 static char
161 data_acked(register struct psock *s)
162 {
163   if(s->state == STATE_DATA_SENT && uip_acked()) {
164     if(s->sendlen > uip_mss()) {
165       s->sendlen -= uip_mss();
166       s->sendptr += uip_mss();
167     } else {
168       s->sendptr += s->sendlen;
169       s->sendlen = 0;
170     }
171     s->state = STATE_ACKED;
172     return 1;
173   }
174   return 0;
175 }
176 /*---------------------------------------------------------------------------*/
177 PT_THREAD(psock_send(register struct psock *s, const char *buf,
178                      unsigned int len))
179 {
180   PT_BEGIN(&s->psockpt);
181
182   /* If there is no data to send, we exit immediately. */
183   if(len == 0) {
184     PT_EXIT(&s->psockpt);
185   }
186
187   /* Save the length of and a pointer to the data that is to be
188      sent. */
189   s->sendptr = (unsigned char*)buf;
190   s->sendlen = len;
191
192   s->state = STATE_NONE;
193
194   /* We loop here until all data is sent. The s->sendlen variable is
195      updated by the data_sent() function. */
196   while(s->sendlen > 0) {
197
198     /*
199      * The condition for this PT_WAIT_UNTIL is a little tricky: the
200      * protothread will wait here until all data has been acknowledged
201      * (data_acked() returns true) and until all data has been sent
202      * (send_data() returns true). The two functions data_acked() and
203      * send_data() must be called in succession to ensure that all
204      * data is sent. Therefore the & operator is used instead of the
205      * && operator, which would cause only the data_acked() function
206      * to be called when it returns false.
207      */
208     PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
209   }
210
211   s->state = STATE_NONE;
212  
213   PT_END(&s->psockpt);
214 }
215 /*---------------------------------------------------------------------------*/
216 PT_THREAD(psock_generator_send(register struct psock *s,
217                                unsigned short (*generate)(void *), void *arg))
218 {
219   PT_BEGIN(&s->psockpt);
220
221   /* Ensure that there is a generator function to call. */
222   if(generate == NULL) {
223     PT_EXIT(&s->psockpt);
224   }
225
226   /* Call the generator function to generate the data in the
227      uip_appdata buffer. */
228   s->sendlen = generate(arg);
229   s->sendptr = uip_appdata;
230
231   s->state = STATE_NONE; 
232   do {
233     /* Call the generator function again if we are called to perform a
234        retransmission. */
235     if(uip_rexmit()) {
236       generate(arg);
237     }
238     /* Wait until all data is sent and acknowledged. */
239     PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
240   } while(s->sendlen > 0);
241  
242   s->state = STATE_NONE;
243  
244   PT_END(&s->psockpt);
245 }
246 /*---------------------------------------------------------------------------*/
247 u16_t
248 psock_datalen(struct psock *psock)
249 {
250   return psock->bufsize - psock->buf.left;
251 }
252 /*---------------------------------------------------------------------------*/
253 char
254 psock_newdata(struct psock *s)
255 {
256   if(s->readlen > 0) {
257     /* There is data in the uip_appdata buffer that has not yet been
258        read with the PSOCK_READ functions. */
259     return 1;
260   } else if(s->state == STATE_READ) {
261     /* All data in uip_appdata buffer already consumed. */
262     s->state = STATE_BLOCKED_NEWDATA;
263     return 0;
264   } else if(uip_newdata()) {
265     /* There is new data that has not been consumed. */
266     return 1;
267   } else {
268     /* There is no new data. */
269     return 0;
270   }
271 }
272 /*---------------------------------------------------------------------------*/
273 PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
274 {
275   PT_BEGIN(&psock->psockpt);
276
277   buf_setup(&psock->buf, (unsigned char*)psock->bufptr, psock->bufsize);
278  
279   /* XXX: Should add buf_checkmarker() before do{} loop, if
280      incoming data has been handled while waiting for a write. */
281
282   do {
283     if(psock->readlen == 0) {
284       PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
285       psock->state = STATE_READ;
286       psock->readptr = (u8_t *)uip_appdata;
287       psock->readlen = uip_datalen();
288     }
289   } while((buf_bufto(&psock->buf, c,
290                      &psock->readptr,
291                      &psock->readlen) & BUF_FOUND) == 0);
292  
293   if(psock_datalen(psock) == 0) {
294     psock->state = STATE_NONE;
295     PT_RESTART(&psock->psockpt);
296   }
297   PT_END(&psock->psockpt);
298 }
299 /*---------------------------------------------------------------------------*/
300 PT_THREAD(psock_readbuf(register struct psock *psock))
301 {
302   PT_BEGIN(&psock->psockpt);
303
304   buf_setup(&psock->buf, (unsigned char * ) psock->bufptr, psock->bufsize);
305  
306   /* XXX: Should add buf_checkmarker() before do{} loop, if
307      incoming data has been handled while waiting for a write. */
308
309   do {
310     if(psock->readlen == 0) {
311       PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
312       printf("Waited for newdata\n");
313       psock->state = STATE_READ;
314       psock->readptr = (u8_t *)uip_appdata;
315       psock->readlen = uip_datalen();
316     }
317   } while(buf_bufdata(&psock->buf, psock->bufsize,
318                          &psock->readptr,
319                          &psock->readlen) != BUF_FULL);
320
321   if(psock_datalen(psock) == 0) {
322     psock->state = STATE_NONE;
323     PT_RESTART(&psock->psockpt);
324   }
325   PT_END(&psock->psockpt);
326 }
327 /*---------------------------------------------------------------------------*/
328 void
329 psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
330 {
331   psock->state = STATE_NONE;
332   psock->readlen = 0;
333   psock->bufptr = buffer;
334   psock->bufsize = buffersize;
335   buf_setup(&psock->buf, (unsigned char*) buffer, buffersize);
336   PT_INIT(&psock->pt);
337   PT_INIT(&psock->psockpt);
338 }
339 /*---------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the browser.