Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2004, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * Author: Adam Dunkels <adam@sics.se> 00032 * 00033 * $Id: psock.c,v 1.12 2010/06/15 14:19:22 nifi Exp $ 00034 */ 00035 00036 #include <string.h> 00037 00038 #include "net/psock.h" 00039 00040 #define STATE_NONE 0 00041 #define STATE_ACKED 1 00042 #define STATE_READ 2 00043 #define STATE_BLOCKED_NEWDATA 3 00044 #define STATE_BLOCKED_CLOSE 4 00045 #define STATE_BLOCKED_SEND 5 00046 #define STATE_DATA_SENT 6 00047 00048 /* 00049 * Return value of the buffering functions that indicates that a 00050 * buffer was not filled by incoming data. 00051 * 00052 */ 00053 #define BUF_NOT_FULL 0 00054 #define BUF_NOT_FOUND 0 00055 00056 /* 00057 * Return value of the buffering functions that indicates that a 00058 * buffer was completely filled by incoming data. 00059 * 00060 */ 00061 #define BUF_FULL 1 00062 00063 /* 00064 * Return value of the buffering functions that indicates that an 00065 * end-marker byte was found. 00066 * 00067 */ 00068 #define BUF_FOUND 2 00069 00070 /*---------------------------------------------------------------------------*/ 00071 static void 00072 buf_setup(struct psock_buf *buf, 00073 uint8_t *bufptr, uint16_t bufsize) 00074 { 00075 buf->ptr = bufptr; 00076 buf->left = bufsize; 00077 } 00078 /*---------------------------------------------------------------------------*/ 00079 static uint8_t 00080 buf_bufdata(struct psock_buf *buf, uint16_t len, 00081 uint8_t **dataptr, uint16_t *datalen) 00082 { 00083 if(*datalen < buf->left) { 00084 memcpy(buf->ptr, *dataptr, *datalen); 00085 buf->ptr += *datalen; 00086 buf->left -= *datalen; 00087 *dataptr += *datalen; 00088 *datalen = 0; 00089 return BUF_NOT_FULL; 00090 } else if(*datalen == buf->left) { 00091 memcpy(buf->ptr, *dataptr, *datalen); 00092 buf->ptr += *datalen; 00093 buf->left = 0; 00094 *dataptr += *datalen; 00095 *datalen = 0; 00096 return BUF_FULL; 00097 } else { 00098 memcpy(buf->ptr, *dataptr, buf->left); 00099 buf->ptr += buf->left; 00100 *datalen -= buf->left; 00101 *dataptr += buf->left; 00102 buf->left = 0; 00103 return BUF_FULL; 00104 } 00105 } 00106 /*---------------------------------------------------------------------------*/ 00107 static uint8_t 00108 buf_bufto(CC_REGISTER_ARG struct psock_buf *buf, uint8_t endmarker, 00109 CC_REGISTER_ARG uint8_t **dataptr, CC_REGISTER_ARG uint16_t *datalen) 00110 { 00111 uint8_t c; 00112 while(buf->left > 0 && *datalen > 0) { 00113 c = *buf->ptr = **dataptr; 00114 ++*dataptr; 00115 ++buf->ptr; 00116 --*datalen; 00117 --buf->left; 00118 00119 if(c == endmarker) { 00120 return BUF_FOUND; 00121 } 00122 } 00123 00124 if(*datalen == 0) { 00125 return BUF_NOT_FOUND; 00126 } 00127 00128 while(*datalen > 0) { 00129 c = **dataptr; 00130 --*datalen; 00131 ++*dataptr; 00132 00133 if(c == endmarker) { 00134 return BUF_FOUND | BUF_FULL; 00135 } 00136 } 00137 00138 return BUF_FULL; 00139 } 00140 /*---------------------------------------------------------------------------*/ 00141 static char 00142 data_is_sent_and_acked(CC_REGISTER_ARG struct psock *s) 00143 { 00144 /* If data has previously been sent, and the data has been acked, we 00145 increase the send pointer and call send_data() to send more 00146 data. */ 00147 if(s->state != STATE_DATA_SENT || uip_rexmit()) { 00148 if(s->sendlen > uip_mss()) { 00149 uip_send(s->sendptr, uip_mss()); 00150 } else { 00151 uip_send(s->sendptr, s->sendlen); 00152 } 00153 s->state = STATE_DATA_SENT; 00154 return 0; 00155 } else if(s->state == STATE_DATA_SENT && uip_acked()) { 00156 if(s->sendlen > uip_mss()) { 00157 s->sendlen -= uip_mss(); 00158 s->sendptr += uip_mss(); 00159 } else { 00160 s->sendptr += s->sendlen; 00161 s->sendlen = 0; 00162 } 00163 s->state = STATE_ACKED; 00164 return 1; 00165 } 00166 return 0; 00167 } 00168 /*---------------------------------------------------------------------------*/ 00169 PT_THREAD(psock_send(CC_REGISTER_ARG struct psock *s, const uint8_t *buf, 00170 unsigned int len)) 00171 { 00172 PT_BEGIN(&s->psockpt); 00173 00174 /* If there is no data to send, we exit immediately. */ 00175 if(len == 0) { 00176 PT_EXIT(&s->psockpt); 00177 } 00178 00179 /* Save the length of and a pointer to the data that is to be 00180 sent. */ 00181 s->sendptr = buf; 00182 s->sendlen = len; 00183 00184 s->state = STATE_NONE; 00185 00186 /* We loop here until all data is sent. The s->sendlen variable is 00187 updated by the data_sent() function. */ 00188 while(s->sendlen > 0) { 00189 00190 /* 00191 * The protothread will wait here until all data has been 00192 * acknowledged and sent (data_is_acked_and_send() returns 1). 00193 */ 00194 PT_WAIT_UNTIL(&s->psockpt, data_is_sent_and_acked(s)); 00195 } 00196 00197 s->state = STATE_NONE; 00198 00199 PT_END(&s->psockpt); 00200 } 00201 /*---------------------------------------------------------------------------*/ 00202 PT_THREAD(psock_generator_send(CC_REGISTER_ARG struct psock *s, 00203 unsigned short (*generate)(void *), void *arg)) 00204 { 00205 PT_BEGIN(&s->psockpt); 00206 00207 /* Ensure that there is a generator function to call. */ 00208 if(generate == NULL) { 00209 PT_EXIT(&s->psockpt); 00210 } 00211 00212 s->state = STATE_NONE; 00213 do { 00214 /* Call the generator function to generate the data in the 00215 uip_appdata buffer. */ 00216 s->sendlen = generate(arg); 00217 s->sendptr = uip_appdata; 00218 00219 if(s->sendlen > uip_mss()) { 00220 uip_send(s->sendptr, uip_mss()); 00221 } else { 00222 uip_send(s->sendptr, s->sendlen); 00223 } 00224 s->state = STATE_DATA_SENT; 00225 00226 /* Wait until all data is sent and acknowledged. */ 00227 // if (!s->sendlen) break; //useful debugging aid 00228 PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit()); 00229 } while(!uip_acked()); 00230 00231 s->state = STATE_NONE; 00232 00233 PT_END(&s->psockpt); 00234 } 00235 /*---------------------------------------------------------------------------*/ 00236 uint16_t 00237 psock_datalen(struct psock *psock) 00238 { 00239 return psock->bufsize - psock->buf.left; 00240 } 00241 /*---------------------------------------------------------------------------*/ 00242 char 00243 psock_newdata(struct psock *s) 00244 { 00245 if(s->readlen > 0) { 00246 /* There is data in the uip_appdata buffer that has not yet been 00247 read with the PSOCK_READ functions. */ 00248 return 1; 00249 } else if(s->state == STATE_READ) { 00250 /* All data in uip_appdata buffer already consumed. */ 00251 s->state = STATE_BLOCKED_NEWDATA; 00252 return 0; 00253 } else if(uip_newdata()) { 00254 /* There is new data that has not been consumed. */ 00255 return 1; 00256 } else { 00257 /* There is no new data. */ 00258 return 0; 00259 } 00260 } 00261 /*---------------------------------------------------------------------------*/ 00262 PT_THREAD(psock_readto(CC_REGISTER_ARG struct psock *psock, unsigned char c)) 00263 { 00264 PT_BEGIN(&psock->psockpt); 00265 00266 buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 00267 00268 /* XXX: Should add buf_checkmarker() before do{} loop, if 00269 incoming data has been handled while waiting for a write. */ 00270 00271 do { 00272 if(psock->readlen == 0) { 00273 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 00274 psock->state = STATE_READ; 00275 psock->readptr = (uint8_t *)uip_appdata; 00276 psock->readlen = uip_datalen(); 00277 } 00278 } while((buf_bufto(&psock->buf, c, 00279 &psock->readptr, 00280 &psock->readlen) & BUF_FOUND) == 0); 00281 00282 if(psock_datalen(psock) == 0) { 00283 psock->state = STATE_NONE; 00284 PT_RESTART(&psock->psockpt); 00285 } 00286 PT_END(&psock->psockpt); 00287 } 00288 /*---------------------------------------------------------------------------*/ 00289 PT_THREAD(psock_readbuf_len(CC_REGISTER_ARG struct psock *psock, uint16_t len)) 00290 { 00291 PT_BEGIN(&psock->psockpt); 00292 00293 buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 00294 00295 /* XXX: Should add buf_checkmarker() before do{} loop, if 00296 incoming data has been handled while waiting for a write. */ 00297 00298 /* read len bytes or to end of data */ 00299 do { 00300 if(psock->readlen == 0) { 00301 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 00302 psock->state = STATE_READ; 00303 psock->readptr = (uint8_t *)uip_appdata; 00304 psock->readlen = uip_datalen(); 00305 } 00306 } while(buf_bufdata(&psock->buf, psock->bufsize, 00307 &psock->readptr, &psock->readlen) == BUF_NOT_FULL && 00308 psock_datalen(psock) < len); 00309 00310 if(psock_datalen(psock) == 0) { 00311 psock->state = STATE_NONE; 00312 PT_RESTART(&psock->psockpt); 00313 } 00314 PT_END(&psock->psockpt); 00315 } 00316 00317 /*---------------------------------------------------------------------------*/ 00318 void 00319 psock_init(CC_REGISTER_ARG struct psock *psock, 00320 uint8_t *buffer, unsigned int buffersize) 00321 { 00322 psock->state = STATE_NONE; 00323 psock->readlen = 0; 00324 psock->bufptr = buffer; 00325 psock->bufsize = buffersize; 00326 buf_setup(&psock->buf, buffer, buffersize); 00327 PT_INIT(&psock->pt); 00328 PT_INIT(&psock->psockpt); 00329 } 00330 /*---------------------------------------------------------------------------*/