Statistics
| Branch: | Tag: | Revision:

root / fon-flash / psock.cpp @ master

History | View | Annotate | Download (9.7 KB)

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 2008/05/07 06:59:32 sven-ola 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
  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
/*---------------------------------------------------------------------------*/
110
static u8_t
111
buf_bufto(register struct psock_buf *buf, u8_t endmarker,
112
          register u8_t **dataptr, register u16_t *datalen)
113
{
114
  u8_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
/*---------------------------------------------------------------------------*/
144
static char
145
send_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
/*---------------------------------------------------------------------------*/
159
static char
160
data_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
/*---------------------------------------------------------------------------*/
176
PT_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 = (unsigned char*)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(207, &s->psockpt, data_acked(s) & send_data(s));
208
  }
209
210
  s->state = STATE_NONE;
211
  
212
  PT_END(&s->psockpt);
213
}
214
/*---------------------------------------------------------------------------*/
215
PT_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 = (u8_t*)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(238, &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
/*---------------------------------------------------------------------------*/
246
u16_t
247
psock_datalen(struct psock *psock)
248
{
249
  return psock->bufsize - psock->buf.left;
250
}
251
/*---------------------------------------------------------------------------*/
252
char
253
psock_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
/*---------------------------------------------------------------------------*/
272
PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
273
{
274
  PT_BEGIN(&psock->psockpt);
275
276
  buf_setup(&psock->buf, (unsigned char*)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(283, &psock->psockpt, psock_newdata(psock));
284
      psock->state = STATE_READ;
285
      psock->readptr = (u8_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
/*---------------------------------------------------------------------------*/
299
PT_THREAD(psock_readbuf(register struct psock *psock))
300
{
301
  PT_BEGIN(&psock->psockpt);
302
303
  buf_setup(&psock->buf, (unsigned char*)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(310, &psock->psockpt, psock_newdata(psock));
311
      printf("Waited for newdata\n");
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
/*---------------------------------------------------------------------------*/