root/webserver/example/freeRTOSexample/EnergyMeters/Common/ethernet/FreeRTOS-uIP/psock.c

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