Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
psock.c
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 uIP TCP/IP stack 00030 * 00031 * Author: Adam Dunkels <adam@sics.se> 00032 * 00033 * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 00034 */ 00035 00036 #include <string.h> 00037 00038 #include "uipopt.h" 00039 #include "psock.h" 00040 #include "uip.h" 00041 00042 #define STATE_NONE 0 00043 #define STATE_ACKED 1 00044 #define STATE_READ 2 00045 #define STATE_BLOCKED_NEWDATA 3 00046 #define STATE_BLOCKED_CLOSE 4 00047 #define STATE_BLOCKED_SEND 5 00048 #define STATE_DATA_SENT 6 00049 00050 /* 00051 * Return value of the buffering functions that indicates that a 00052 * buffer was not filled by incoming data. 00053 * 00054 */ 00055 #define BUF_NOT_FULL 0 00056 #define BUF_NOT_FOUND 0 00057 00058 /* 00059 * Return value of the buffering functions that indicates that a 00060 * buffer was completely filled by incoming data. 00061 * 00062 */ 00063 #define BUF_FULL 1 00064 00065 /* 00066 * Return value of the buffering functions that indicates that an 00067 * end-marker byte was found. 00068 * 00069 */ 00070 #define BUF_FOUND 2 00071 00072 /*---------------------------------------------------------------------------*/ 00073 static void 00074 buf_setup(struct psock_buf *buf, 00075 u8_t *bufptr, u16_t bufsize) 00076 { 00077 buf->ptr = bufptr; 00078 buf->left = bufsize; 00079 } 00080 /*---------------------------------------------------------------------------*/ 00081 static u8_t 00082 buf_bufdata(struct psock_buf *buf, u16_t len, 00083 u8_t **dataptr, u16_t *datalen) 00084 { 00085 if(*datalen < buf->left) { 00086 memcpy(buf->ptr, *dataptr, *datalen); 00087 buf->ptr += *datalen; 00088 buf->left -= *datalen; 00089 *dataptr += *datalen; 00090 *datalen = 0; 00091 return BUF_NOT_FULL; 00092 } else if(*datalen == buf->left) { 00093 memcpy(buf->ptr, *dataptr, *datalen); 00094 buf->ptr += *datalen; 00095 buf->left = 0; 00096 *dataptr += *datalen; 00097 *datalen = 0; 00098 return BUF_FULL; 00099 } else { 00100 memcpy(buf->ptr, *dataptr, buf->left); 00101 buf->ptr += buf->left; 00102 *datalen -= buf->left; 00103 *dataptr += buf->left; 00104 buf->left = 0; 00105 return BUF_FULL; 00106 } 00107 } 00108 /*---------------------------------------------------------------------------*/ 00109 static u8_t 00110 buf_bufto(register struct psock_buf *buf, u8_t endmarker, 00111 register u8_t **dataptr, register u16_t *datalen) 00112 { 00113 u8_t c; 00114 while(buf->left > 0 && *datalen > 0) { 00115 c = *buf->ptr = **dataptr; 00116 ++*dataptr; 00117 ++buf->ptr; 00118 --*datalen; 00119 --buf->left; 00120 00121 if(c == endmarker) { 00122 return BUF_FOUND; 00123 } 00124 } 00125 00126 if(*datalen == 0) { 00127 return BUF_NOT_FOUND; 00128 } 00129 00130 return BUF_FULL; 00131 } 00132 /*---------------------------------------------------------------------------*/ 00133 static char 00134 data_is_sent_and_acked(register struct psock *s) 00135 { 00136 /* If data has previously been sent, and the data has been acked, we 00137 increase the send pointer and call send_data() to send more 00138 data. */ 00139 if(s->state != STATE_DATA_SENT || uip_rexmit()) { 00140 if(s->sendlen > uip_mss()) { 00141 uip_send(s->sendptr, uip_mss()); 00142 } else { 00143 uip_send(s->sendptr, s->sendlen); 00144 } 00145 s->state = STATE_DATA_SENT; 00146 return 0; 00147 } else if(s->state == STATE_DATA_SENT && uip_acked()) { 00148 if(s->sendlen > uip_mss()) { 00149 s->sendlen -= uip_mss(); 00150 s->sendptr += uip_mss(); 00151 } else { 00152 s->sendptr += s->sendlen; 00153 s->sendlen = 0; 00154 } 00155 s->state = STATE_ACKED; 00156 return 1; 00157 } 00158 return 0; 00159 } 00160 /*---------------------------------------------------------------------------*/ 00161 PT_THREAD(psock_send(register struct psock *s, const char *buf, 00162 unsigned int len)) 00163 { 00164 PT_BEGIN(&s->psockpt); 00165 00166 /* If there is no data to send, we exit immediately. */ 00167 if(len == 0) { 00168 PT_EXIT(&s->psockpt); 00169 } 00170 00171 /* Save the length of and a pointer to the data that is to be 00172 sent. */ 00173 s->sendptr = buf; 00174 s->sendlen = len; 00175 00176 s->state = STATE_NONE; 00177 00178 /* We loop here until all data is sent. The s->sendlen variable is 00179 updated by the data_sent() function. */ 00180 while(s->sendlen > 0) { 00181 00182 /* 00183 * The protothread will wait here until all data has been 00184 * acknowledged and sent (data_is_acked_and_send() returns 1). 00185 */ 00186 PT_WAIT_UNTIL(&s->psockpt, data_is_sent_and_acked(s)); 00187 } 00188 00189 s->state = STATE_NONE; 00190 00191 PT_END(&s->psockpt); 00192 } 00193 /*---------------------------------------------------------------------------*/ 00194 PT_THREAD(psock_generator_send(register struct psock *s, 00195 unsigned short (*generate)(void *), void *arg)) 00196 { 00197 PT_BEGIN(&s->psockpt); 00198 00199 /* Ensure that there is a generator function to call. */ 00200 if(generate == NULL) { 00201 PT_EXIT(&s->psockpt); 00202 } 00203 00204 s->state = STATE_NONE; 00205 do { 00206 /* Call the generator function to generate the data in the 00207 uip_appdata buffer. */ 00208 s->sendlen = generate(arg); 00209 s->sendptr = uip_appdata; 00210 00211 if(s->sendlen > uip_mss()) { 00212 uip_send(s->sendptr, uip_mss()); 00213 } else { 00214 uip_send(s->sendptr, s->sendlen); 00215 } 00216 s->state = STATE_DATA_SENT; 00217 00218 /* Wait until all data is sent and acknowledged. */ 00219 // if (!s->sendlen) break; //useful debugging aid 00220 PT_YIELD_UNTIL(&s->psockpt, uip_acked() || uip_rexmit()); 00221 } while(!uip_acked()); 00222 00223 s->state = STATE_NONE; 00224 00225 PT_END(&s->psockpt); 00226 } 00227 /*---------------------------------------------------------------------------*/ 00228 u16_t 00229 psock_datalen(struct psock *psock) 00230 { 00231 return psock->bufsize - psock->buf.left; 00232 } 00233 /*---------------------------------------------------------------------------*/ 00234 char 00235 psock_newdata(struct psock *s) 00236 { 00237 if(s->readlen > 0) { 00238 /* There is data in the uip_appdata buffer that has not yet been 00239 read with the PSOCK_READ functions. */ 00240 return 1; 00241 } else if(s->state == STATE_READ) { 00242 /* All data in uip_appdata buffer already consumed. */ 00243 s->state = STATE_BLOCKED_NEWDATA; 00244 return 0; 00245 } else if(uip_newdata()) { 00246 /* There is new data that has not been consumed. */ 00247 return 1; 00248 } else { 00249 /* There is no new data. */ 00250 return 0; 00251 } 00252 } 00253 /*---------------------------------------------------------------------------*/ 00254 PT_THREAD(psock_readto(register struct psock *psock, unsigned char c)) 00255 { 00256 PT_BEGIN(&psock->psockpt); 00257 00258 buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 00259 00260 /* XXX: Should add buf_checkmarker() before do{} loop, if 00261 incoming data has been handled while waiting for a write. */ 00262 00263 do { 00264 if(psock->readlen == 0) { 00265 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 00266 psock->state = STATE_READ; 00267 psock->readptr = (u8_t *)uip_appdata; 00268 psock->readlen = uip_datalen(); 00269 } 00270 } while(buf_bufto(&psock->buf, c, 00271 &psock->readptr, 00272 &psock->readlen) == BUF_NOT_FOUND); 00273 00274 if(psock_datalen(psock) == 0) { 00275 psock->state = STATE_NONE; 00276 PT_RESTART(&psock->psockpt); 00277 } 00278 PT_END(&psock->psockpt); 00279 } 00280 /*---------------------------------------------------------------------------*/ 00281 PT_THREAD(psock_readbuf_len(register struct psock *psock, uint16_t len)) 00282 { 00283 PT_BEGIN(&psock->psockpt); 00284 00285 buf_setup(&psock->buf, psock->bufptr, psock->bufsize); 00286 00287 /* XXX: Should add buf_checkmarker() before do{} loop, if 00288 incoming data has been handled while waiting for a write. */ 00289 00290 do { 00291 if(psock->readlen == 0) { 00292 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); 00293 psock->state = STATE_READ; 00294 psock->readptr = (u8_t *)uip_appdata; 00295 psock->readlen = uip_datalen(); 00296 } 00297 } while(buf_bufdata(&psock->buf, psock->bufsize, 00298 &psock->readptr, &psock->readlen) == BUF_NOT_FULL && 00299 psock_datalen(psock) < len); 00300 00301 if(psock_datalen(psock) == 0) { 00302 psock->state = STATE_NONE; 00303 PT_RESTART(&psock->psockpt); 00304 } 00305 PT_END(&psock->psockpt); 00306 } 00307 /*---------------------------------------------------------------------------*/ 00308 void 00309 psock_init(register struct psock *psock, char *buffer, unsigned int buffersize) 00310 { 00311 psock->state = STATE_NONE; 00312 psock->readlen = 0; 00313 psock->bufptr = buffer; 00314 psock->bufsize = buffersize; 00315 buf_setup(&psock->buf, buffer, buffersize); 00316 PT_INIT(&psock->pt); 00317 PT_INIT(&psock->psockpt); 00318 } 00319 /*---------------------------------------------------------------------------*/
Generated on Tue Jul 12 2022 12:52:12 by
1.7.2