OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [FreeTCPIP/] [psock.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*
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 2 2011-07-17 20:13:17Z filepang@gmail.com $
34
 */
35
 
36
#include <stdio.h>
37
#include <string.h>
38
 
39
#include "net/uipopt.h"
40
#include "net/psock.h"
41
#include "net/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
  ( void ) PT_YIELD_FLAG;
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 = (unsigned short)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
  ( void ) PT_YIELD_FLAG;
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
  ( void ) PT_YIELD_FLAG;
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
  ( void ) PT_YIELD_FLAG;
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
      psock->state = STATE_READ;
313
      psock->readptr = (u8_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
/*---------------------------------------------------------------------------*/
327
void
328
psock_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, (unsigned char*) buffer, buffersize);
335
  PT_INIT(&psock->pt);
336
  PT_INIT(&psock->psockpt);
337
}
338
/*---------------------------------------------------------------------------*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.