uIP 1.0 based webserver for LPC1114 + ENC28J60

Dependencies:   mbed TMP102

Committer:
ban4jp
Date:
Mon Jun 30 16:00:08 2014 +0000
Revision:
3:a2715e9c7737
Parent:
0:685224d2f66d
backported from Contiki 2.7

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ban4jp 0:685224d2f66d 1 /*
ban4jp 0:685224d2f66d 2 * Copyright (c) 2004, Swedish Institute of Computer Science.
ban4jp 0:685224d2f66d 3 * All rights reserved.
ban4jp 0:685224d2f66d 4 *
ban4jp 0:685224d2f66d 5 * Redistribution and use in source and binary forms, with or without
ban4jp 0:685224d2f66d 6 * modification, are permitted provided that the following conditions
ban4jp 0:685224d2f66d 7 * are met:
ban4jp 0:685224d2f66d 8 * 1. Redistributions of source code must retain the above copyright
ban4jp 0:685224d2f66d 9 * notice, this list of conditions and the following disclaimer.
ban4jp 0:685224d2f66d 10 * 2. Redistributions in binary form must reproduce the above copyright
ban4jp 0:685224d2f66d 11 * notice, this list of conditions and the following disclaimer in the
ban4jp 0:685224d2f66d 12 * documentation and/or other materials provided with the distribution.
ban4jp 0:685224d2f66d 13 * 3. Neither the name of the Institute nor the names of its contributors
ban4jp 0:685224d2f66d 14 * may be used to endorse or promote products derived from this software
ban4jp 0:685224d2f66d 15 * without specific prior written permission.
ban4jp 0:685224d2f66d 16 *
ban4jp 0:685224d2f66d 17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
ban4jp 0:685224d2f66d 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ban4jp 0:685224d2f66d 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ban4jp 0:685224d2f66d 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
ban4jp 0:685224d2f66d 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ban4jp 0:685224d2f66d 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ban4jp 0:685224d2f66d 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ban4jp 0:685224d2f66d 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ban4jp 0:685224d2f66d 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
ban4jp 0:685224d2f66d 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ban4jp 0:685224d2f66d 27 * SUCH DAMAGE.
ban4jp 0:685224d2f66d 28 *
ban4jp 0:685224d2f66d 29 * This file is part of the uIP TCP/IP stack
ban4jp 0:685224d2f66d 30 *
ban4jp 0:685224d2f66d 31 * Author: Adam Dunkels <adam@sics.se>
ban4jp 0:685224d2f66d 32 *
ban4jp 0:685224d2f66d 33 * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $
ban4jp 0:685224d2f66d 34 */
ban4jp 0:685224d2f66d 35
ban4jp 0:685224d2f66d 36 #include <string.h>
ban4jp 0:685224d2f66d 37
ban4jp 0:685224d2f66d 38 #include "uipopt.h"
ban4jp 0:685224d2f66d 39 #include "psock.h"
ban4jp 0:685224d2f66d 40 #include "uip.h"
ban4jp 0:685224d2f66d 41
ban4jp 0:685224d2f66d 42 #define STATE_NONE 0
ban4jp 0:685224d2f66d 43 #define STATE_ACKED 1
ban4jp 0:685224d2f66d 44 #define STATE_READ 2
ban4jp 0:685224d2f66d 45 #define STATE_BLOCKED_NEWDATA 3
ban4jp 0:685224d2f66d 46 #define STATE_BLOCKED_CLOSE 4
ban4jp 0:685224d2f66d 47 #define STATE_BLOCKED_SEND 5
ban4jp 0:685224d2f66d 48 #define STATE_DATA_SENT 6
ban4jp 0:685224d2f66d 49
ban4jp 0:685224d2f66d 50 /*
ban4jp 0:685224d2f66d 51 * Return value of the buffering functions that indicates that a
ban4jp 0:685224d2f66d 52 * buffer was not filled by incoming data.
ban4jp 0:685224d2f66d 53 *
ban4jp 0:685224d2f66d 54 */
ban4jp 0:685224d2f66d 55 #define BUF_NOT_FULL 0
ban4jp 0:685224d2f66d 56 #define BUF_NOT_FOUND 0
ban4jp 0:685224d2f66d 57
ban4jp 0:685224d2f66d 58 /*
ban4jp 0:685224d2f66d 59 * Return value of the buffering functions that indicates that a
ban4jp 0:685224d2f66d 60 * buffer was completely filled by incoming data.
ban4jp 0:685224d2f66d 61 *
ban4jp 0:685224d2f66d 62 */
ban4jp 0:685224d2f66d 63 #define BUF_FULL 1
ban4jp 0:685224d2f66d 64
ban4jp 0:685224d2f66d 65 /*
ban4jp 0:685224d2f66d 66 * Return value of the buffering functions that indicates that an
ban4jp 0:685224d2f66d 67 * end-marker byte was found.
ban4jp 0:685224d2f66d 68 *
ban4jp 0:685224d2f66d 69 */
ban4jp 0:685224d2f66d 70 #define BUF_FOUND 2
ban4jp 0:685224d2f66d 71
ban4jp 0:685224d2f66d 72 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 73 static void
ban4jp 0:685224d2f66d 74 buf_setup(struct psock_buf *buf,
ban4jp 0:685224d2f66d 75 u8_t *bufptr, u16_t bufsize)
ban4jp 0:685224d2f66d 76 {
ban4jp 0:685224d2f66d 77 buf->ptr = bufptr;
ban4jp 0:685224d2f66d 78 buf->left = bufsize;
ban4jp 0:685224d2f66d 79 }
ban4jp 0:685224d2f66d 80 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 81 static u8_t
ban4jp 0:685224d2f66d 82 buf_bufdata(struct psock_buf *buf, u16_t len,
ban4jp 0:685224d2f66d 83 u8_t **dataptr, u16_t *datalen)
ban4jp 0:685224d2f66d 84 {
ban4jp 0:685224d2f66d 85 if(*datalen < buf->left) {
ban4jp 0:685224d2f66d 86 memcpy(buf->ptr, *dataptr, *datalen);
ban4jp 0:685224d2f66d 87 buf->ptr += *datalen;
ban4jp 0:685224d2f66d 88 buf->left -= *datalen;
ban4jp 0:685224d2f66d 89 *dataptr += *datalen;
ban4jp 0:685224d2f66d 90 *datalen = 0;
ban4jp 0:685224d2f66d 91 return BUF_NOT_FULL;
ban4jp 0:685224d2f66d 92 } else if(*datalen == buf->left) {
ban4jp 0:685224d2f66d 93 memcpy(buf->ptr, *dataptr, *datalen);
ban4jp 0:685224d2f66d 94 buf->ptr += *datalen;
ban4jp 0:685224d2f66d 95 buf->left = 0;
ban4jp 0:685224d2f66d 96 *dataptr += *datalen;
ban4jp 0:685224d2f66d 97 *datalen = 0;
ban4jp 0:685224d2f66d 98 return BUF_FULL;
ban4jp 0:685224d2f66d 99 } else {
ban4jp 0:685224d2f66d 100 memcpy(buf->ptr, *dataptr, buf->left);
ban4jp 0:685224d2f66d 101 buf->ptr += buf->left;
ban4jp 0:685224d2f66d 102 *datalen -= buf->left;
ban4jp 0:685224d2f66d 103 *dataptr += buf->left;
ban4jp 0:685224d2f66d 104 buf->left = 0;
ban4jp 0:685224d2f66d 105 return BUF_FULL;
ban4jp 0:685224d2f66d 106 }
ban4jp 0:685224d2f66d 107 }
ban4jp 0:685224d2f66d 108 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 109 static u8_t
ban4jp 0:685224d2f66d 110 buf_bufto(register struct psock_buf *buf, u8_t endmarker,
ban4jp 0:685224d2f66d 111 register u8_t **dataptr, register u16_t *datalen)
ban4jp 0:685224d2f66d 112 {
ban4jp 0:685224d2f66d 113 u8_t c;
ban4jp 0:685224d2f66d 114 while(buf->left > 0 && *datalen > 0) {
ban4jp 0:685224d2f66d 115 c = *buf->ptr = **dataptr;
ban4jp 0:685224d2f66d 116 ++*dataptr;
ban4jp 0:685224d2f66d 117 ++buf->ptr;
ban4jp 0:685224d2f66d 118 --*datalen;
ban4jp 0:685224d2f66d 119 --buf->left;
ban4jp 0:685224d2f66d 120
ban4jp 0:685224d2f66d 121 if(c == endmarker) {
ban4jp 0:685224d2f66d 122 return BUF_FOUND;
ban4jp 0:685224d2f66d 123 }
ban4jp 0:685224d2f66d 124 }
ban4jp 0:685224d2f66d 125
ban4jp 0:685224d2f66d 126 if(*datalen == 0) {
ban4jp 0:685224d2f66d 127 return BUF_NOT_FOUND;
ban4jp 0:685224d2f66d 128 }
ban4jp 0:685224d2f66d 129
ban4jp 0:685224d2f66d 130 return BUF_FULL;
ban4jp 0:685224d2f66d 131 }
ban4jp 0:685224d2f66d 132 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 133 static char
ban4jp 3:a2715e9c7737 134 data_is_sent_and_acked(register struct psock *s)
ban4jp 0:685224d2f66d 135 {
ban4jp 3:a2715e9c7737 136 /* If data has previously been sent, and the data has been acked, we
ban4jp 3:a2715e9c7737 137 increase the send pointer and call send_data() to send more
ban4jp 3:a2715e9c7737 138 data. */
ban4jp 0:685224d2f66d 139 if(s->state != STATE_DATA_SENT || uip_rexmit()) {
ban4jp 0:685224d2f66d 140 if(s->sendlen > uip_mss()) {
ban4jp 0:685224d2f66d 141 uip_send(s->sendptr, uip_mss());
ban4jp 0:685224d2f66d 142 } else {
ban4jp 0:685224d2f66d 143 uip_send(s->sendptr, s->sendlen);
ban4jp 0:685224d2f66d 144 }
ban4jp 0:685224d2f66d 145 s->state = STATE_DATA_SENT;
ban4jp 3:a2715e9c7737 146 return 0;
ban4jp 3:a2715e9c7737 147 } else if(s->state == STATE_DATA_SENT && uip_acked()) {
ban4jp 0:685224d2f66d 148 if(s->sendlen > uip_mss()) {
ban4jp 0:685224d2f66d 149 s->sendlen -= uip_mss();
ban4jp 0:685224d2f66d 150 s->sendptr += uip_mss();
ban4jp 0:685224d2f66d 151 } else {
ban4jp 0:685224d2f66d 152 s->sendptr += s->sendlen;
ban4jp 0:685224d2f66d 153 s->sendlen = 0;
ban4jp 0:685224d2f66d 154 }
ban4jp 0:685224d2f66d 155 s->state = STATE_ACKED;
ban4jp 0:685224d2f66d 156 return 1;
ban4jp 0:685224d2f66d 157 }
ban4jp 0:685224d2f66d 158 return 0;
ban4jp 0:685224d2f66d 159 }
ban4jp 0:685224d2f66d 160 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 161 PT_THREAD(psock_send(register struct psock *s, const char *buf,
ban4jp 0:685224d2f66d 162 unsigned int len))
ban4jp 0:685224d2f66d 163 {
ban4jp 0:685224d2f66d 164 PT_BEGIN(&s->psockpt);
ban4jp 0:685224d2f66d 165
ban4jp 0:685224d2f66d 166 /* If there is no data to send, we exit immediately. */
ban4jp 0:685224d2f66d 167 if(len == 0) {
ban4jp 0:685224d2f66d 168 PT_EXIT(&s->psockpt);
ban4jp 0:685224d2f66d 169 }
ban4jp 0:685224d2f66d 170
ban4jp 0:685224d2f66d 171 /* Save the length of and a pointer to the data that is to be
ban4jp 0:685224d2f66d 172 sent. */
ban4jp 0:685224d2f66d 173 s->sendptr = buf;
ban4jp 0:685224d2f66d 174 s->sendlen = len;
ban4jp 0:685224d2f66d 175
ban4jp 0:685224d2f66d 176 s->state = STATE_NONE;
ban4jp 0:685224d2f66d 177
ban4jp 0:685224d2f66d 178 /* We loop here until all data is sent. The s->sendlen variable is
ban4jp 0:685224d2f66d 179 updated by the data_sent() function. */
ban4jp 0:685224d2f66d 180 while(s->sendlen > 0) {
ban4jp 0:685224d2f66d 181
ban4jp 0:685224d2f66d 182 /*
ban4jp 3:a2715e9c7737 183 * The protothread will wait here until all data has been
ban4jp 3:a2715e9c7737 184 * acknowledged and sent (data_is_acked_and_send() returns 1).
ban4jp 0:685224d2f66d 185 */
ban4jp 3:a2715e9c7737 186 PT_WAIT_UNTIL(&s->psockpt, data_is_sent_and_acked(s));
ban4jp 0:685224d2f66d 187 }
ban4jp 0:685224d2f66d 188
ban4jp 0:685224d2f66d 189 s->state = STATE_NONE;
ban4jp 0:685224d2f66d 190
ban4jp 0:685224d2f66d 191 PT_END(&s->psockpt);
ban4jp 0:685224d2f66d 192 }
ban4jp 0:685224d2f66d 193 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 194 PT_THREAD(psock_generator_send(register struct psock *s,
ban4jp 0:685224d2f66d 195 unsigned short (*generate)(void *), void *arg))
ban4jp 0:685224d2f66d 196 {
ban4jp 0:685224d2f66d 197 PT_BEGIN(&s->psockpt);
ban4jp 0:685224d2f66d 198
ban4jp 0:685224d2f66d 199 /* Ensure that there is a generator function to call. */
ban4jp 0:685224d2f66d 200 if(generate == NULL) {
ban4jp 0:685224d2f66d 201 PT_EXIT(&s->psockpt);
ban4jp 0:685224d2f66d 202 }
ban4jp 0:685224d2f66d 203
ban4jp 3:a2715e9c7737 204 s->state = STATE_NONE;
ban4jp 0:685224d2f66d 205 do {
ban4jp 3:a2715e9c7737 206 /* Call the generator function to generate the data in the
ban4jp 3:a2715e9c7737 207 uip_appdata buffer. */
ban4jp 3:a2715e9c7737 208 s->sendlen = generate(arg);
ban4jp 3:a2715e9c7737 209 s->sendptr = uip_appdata;
ban4jp 3:a2715e9c7737 210
ban4jp 3:a2715e9c7737 211 if(s->sendlen > uip_mss()) {
ban4jp 3:a2715e9c7737 212 uip_send(s->sendptr, uip_mss());
ban4jp 3:a2715e9c7737 213 } else {
ban4jp 3:a2715e9c7737 214 uip_send(s->sendptr, s->sendlen);
ban4jp 0:685224d2f66d 215 }
ban4jp 3:a2715e9c7737 216 s->state = STATE_DATA_SENT;
ban4jp 3:a2715e9c7737 217
ban4jp 0:685224d2f66d 218 /* Wait until all data is sent and acknowledged. */
ban4jp 3:a2715e9c7737 219 // if (!s->sendlen) break; //useful debugging aid
ban4jp 3:a2715e9c7737 220 PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit());
ban4jp 3:a2715e9c7737 221 } while(!uip_acked());
ban4jp 0:685224d2f66d 222
ban4jp 0:685224d2f66d 223 s->state = STATE_NONE;
ban4jp 0:685224d2f66d 224
ban4jp 0:685224d2f66d 225 PT_END(&s->psockpt);
ban4jp 0:685224d2f66d 226 }
ban4jp 0:685224d2f66d 227 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 228 u16_t
ban4jp 0:685224d2f66d 229 psock_datalen(struct psock *psock)
ban4jp 0:685224d2f66d 230 {
ban4jp 0:685224d2f66d 231 return psock->bufsize - psock->buf.left;
ban4jp 0:685224d2f66d 232 }
ban4jp 0:685224d2f66d 233 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 234 char
ban4jp 0:685224d2f66d 235 psock_newdata(struct psock *s)
ban4jp 0:685224d2f66d 236 {
ban4jp 0:685224d2f66d 237 if(s->readlen > 0) {
ban4jp 0:685224d2f66d 238 /* There is data in the uip_appdata buffer that has not yet been
ban4jp 0:685224d2f66d 239 read with the PSOCK_READ functions. */
ban4jp 0:685224d2f66d 240 return 1;
ban4jp 0:685224d2f66d 241 } else if(s->state == STATE_READ) {
ban4jp 0:685224d2f66d 242 /* All data in uip_appdata buffer already consumed. */
ban4jp 0:685224d2f66d 243 s->state = STATE_BLOCKED_NEWDATA;
ban4jp 0:685224d2f66d 244 return 0;
ban4jp 0:685224d2f66d 245 } else if(uip_newdata()) {
ban4jp 0:685224d2f66d 246 /* There is new data that has not been consumed. */
ban4jp 0:685224d2f66d 247 return 1;
ban4jp 0:685224d2f66d 248 } else {
ban4jp 0:685224d2f66d 249 /* There is no new data. */
ban4jp 0:685224d2f66d 250 return 0;
ban4jp 0:685224d2f66d 251 }
ban4jp 0:685224d2f66d 252 }
ban4jp 0:685224d2f66d 253 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 254 PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
ban4jp 0:685224d2f66d 255 {
ban4jp 0:685224d2f66d 256 PT_BEGIN(&psock->psockpt);
ban4jp 0:685224d2f66d 257
ban4jp 0:685224d2f66d 258 buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
ban4jp 0:685224d2f66d 259
ban4jp 0:685224d2f66d 260 /* XXX: Should add buf_checkmarker() before do{} loop, if
ban4jp 0:685224d2f66d 261 incoming data has been handled while waiting for a write. */
ban4jp 0:685224d2f66d 262
ban4jp 0:685224d2f66d 263 do {
ban4jp 0:685224d2f66d 264 if(psock->readlen == 0) {
ban4jp 0:685224d2f66d 265 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
ban4jp 0:685224d2f66d 266 psock->state = STATE_READ;
ban4jp 0:685224d2f66d 267 psock->readptr = (u8_t *)uip_appdata;
ban4jp 0:685224d2f66d 268 psock->readlen = uip_datalen();
ban4jp 0:685224d2f66d 269 }
ban4jp 3:a2715e9c7737 270 } while(buf_bufto(&psock->buf, c,
ban4jp 3:a2715e9c7737 271 &psock->readptr,
ban4jp 3:a2715e9c7737 272 &psock->readlen) == BUF_NOT_FOUND);
ban4jp 0:685224d2f66d 273
ban4jp 0:685224d2f66d 274 if(psock_datalen(psock) == 0) {
ban4jp 0:685224d2f66d 275 psock->state = STATE_NONE;
ban4jp 0:685224d2f66d 276 PT_RESTART(&psock->psockpt);
ban4jp 0:685224d2f66d 277 }
ban4jp 0:685224d2f66d 278 PT_END(&psock->psockpt);
ban4jp 0:685224d2f66d 279 }
ban4jp 0:685224d2f66d 280 /*---------------------------------------------------------------------------*/
ban4jp 3:a2715e9c7737 281 PT_THREAD(psock_readbuf_len(register struct psock *psock, uint16_t len))
ban4jp 0:685224d2f66d 282 {
ban4jp 0:685224d2f66d 283 PT_BEGIN(&psock->psockpt);
ban4jp 0:685224d2f66d 284
ban4jp 0:685224d2f66d 285 buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
ban4jp 0:685224d2f66d 286
ban4jp 0:685224d2f66d 287 /* XXX: Should add buf_checkmarker() before do{} loop, if
ban4jp 0:685224d2f66d 288 incoming data has been handled while waiting for a write. */
ban4jp 0:685224d2f66d 289
ban4jp 0:685224d2f66d 290 do {
ban4jp 0:685224d2f66d 291 if(psock->readlen == 0) {
ban4jp 0:685224d2f66d 292 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
ban4jp 0:685224d2f66d 293 psock->state = STATE_READ;
ban4jp 0:685224d2f66d 294 psock->readptr = (u8_t *)uip_appdata;
ban4jp 0:685224d2f66d 295 psock->readlen = uip_datalen();
ban4jp 0:685224d2f66d 296 }
ban4jp 0:685224d2f66d 297 } while(buf_bufdata(&psock->buf, psock->bufsize,
ban4jp 3:a2715e9c7737 298 &psock->readptr, &psock->readlen) == BUF_NOT_FULL &&
ban4jp 3:a2715e9c7737 299 psock_datalen(psock) < len);
ban4jp 3:a2715e9c7737 300
ban4jp 0:685224d2f66d 301 if(psock_datalen(psock) == 0) {
ban4jp 0:685224d2f66d 302 psock->state = STATE_NONE;
ban4jp 0:685224d2f66d 303 PT_RESTART(&psock->psockpt);
ban4jp 0:685224d2f66d 304 }
ban4jp 0:685224d2f66d 305 PT_END(&psock->psockpt);
ban4jp 0:685224d2f66d 306 }
ban4jp 0:685224d2f66d 307 /*---------------------------------------------------------------------------*/
ban4jp 0:685224d2f66d 308 void
ban4jp 0:685224d2f66d 309 psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
ban4jp 0:685224d2f66d 310 {
ban4jp 0:685224d2f66d 311 psock->state = STATE_NONE;
ban4jp 0:685224d2f66d 312 psock->readlen = 0;
ban4jp 0:685224d2f66d 313 psock->bufptr = buffer;
ban4jp 0:685224d2f66d 314 psock->bufsize = buffersize;
ban4jp 0:685224d2f66d 315 buf_setup(&psock->buf, buffer, buffersize);
ban4jp 0:685224d2f66d 316 PT_INIT(&psock->pt);
ban4jp 0:685224d2f66d 317 PT_INIT(&psock->psockpt);
ban4jp 0:685224d2f66d 318 }
ban4jp 0:685224d2f66d 319 /*---------------------------------------------------------------------------*/