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.h,v 1.3 2005/06/03 07:25:56 adam Exp $ 00034 */ 00035 00036 /** 00037 * \defgroup psock Protosockets library 00038 * @{ 00039 * 00040 * The protosocket library provides an interface to the uIP stack that is 00041 * similar to the traditional BSD socket interface. Unlike programs 00042 * written for the ordinary uIP event-driven interface, programs 00043 * written with the protosocket library are executed in a sequential 00044 * fashion and does not have to be implemented as explicit state 00045 * machines. 00046 * 00047 * Protosockets only work with TCP connections. 00048 * 00049 * The protosocket library uses \ref pt protothreads to provide 00050 * sequential control flow. This makes the protosockets lightweight in 00051 * terms of memory, but also means that protosockets inherits the 00052 * functional limitations of protothreads. Each protosocket lives only 00053 * within a single function block. Automatic variables (stack 00054 * variables) are not necessarily retained across a protosocket 00055 * library function call. 00056 * 00057 * \note Because the protosocket library uses protothreads, local variables 00058 * will not always be saved across a call to a protosocket library 00059 * function. It is therefore advised that local variables are used 00060 * with extreme care. 00061 * 00062 * The protosocket library provides functions for sending data without 00063 * having to deal with retransmissions and acknowledgements, as well 00064 * as functions for reading data without having to deal with data 00065 * being split across more than one TCP segment. 00066 * 00067 * Because each protosocket runs as a protothread, the protosocket has to be 00068 * started with a call to PSOCK_BEGIN() at the start of the function 00069 * in which the protosocket is used. Similarly, the protosocket protothread can 00070 * be terminated by a call to PSOCK_EXIT(). 00071 * 00072 * The example code below illustrates how to use the protosocket 00073 * library. The program implements a simple SMTP client that sends a 00074 * short email. The program is divided into two functions, one uIP 00075 * event handler (smtp_uipcall()) and one function that runs the 00076 * protosocket protothread and performs the SMTP communication 00077 * (smtp_socketthread()). 00078 * 00079 * An SMTP connection is represented by a smtp_state structure 00080 * containing a struct psock and a small input buffer. The input 00081 * buffer only needs to be 3 bytes long to accomodate the 3 byte 00082 * status codes used by SMTP. Connection structures can be allocated 00083 * from the memory buffer called connections, which is declared with 00084 * the MEMB() macro. 00085 * 00086 * The convenience macro SEND_STRING() is defined in order to simplify 00087 * the code, as it mostly involves sending strings. 00088 * 00089 * The function smtp_socketthread() is declared as a protothread using 00090 * the PT_THREAD() macro. The PSOCK_BEGIN() call at the first line of 00091 * the smtp_socketthread() function starts the protothread. SMTP 00092 * specifies that the server will start with sending a welcome message 00093 * that should include the status code 220 if the server is ready to 00094 * accept messages. Therefore, the smtp_socketthread() first calls 00095 * PSOCK_READTO() to read all incoming data up to the first 00096 * newline. If the status code was anything else but 220, the protosocket 00097 * is closed and the protosocket's protothread is terminated with the call 00098 * to PSOCK_CLOSE_EXIT(). 00099 * 00100 * If the connection is accepted by the server, smtp_socketthread() 00101 * continues with sending the HELO message. If this gets a positive 00102 * reply (a status code beginning with a 2), the protothread moves on 00103 * with the rest of the SMTP procedure. Finally, after all headers and 00104 * data is sent, the program sends a QUIT before it finally closes the 00105 * protosocket and exits the protosocket's protothread. 00106 * 00107 * 00108 \code 00109 #include <string.h> 00110 00111 #include "psock.h" 00112 #include "memb.h" 00113 00114 struct smtp_state { 00115 struct psock psock; 00116 char inputbuffer[3]; 00117 }; 00118 00119 MEMB(connections, sizeof(struct smtp_state), 2); 00120 00121 #define SEND_STRING(s, str) PSOCK_SEND(s, str, strlen(str)) 00122 00123 static 00124 PT_THREAD(smtp_socketthread(struct smtp_state *s)) 00125 { 00126 PSOCK_BEGIN(&s->psock); 00127 00128 PSOCK_READTO(&s->psock, '\n'); 00129 00130 if(strncmp(s->inputbuffer, "220", 3) != 0) { 00131 PSOCK_CLOSE_EXIT(&s->psock); 00132 } 00133 00134 SEND_STRING(&s->psock, "HELO contiki.example.com\r\n"); 00135 00136 PSOCK_READTO(&s->psock, '\n'); 00137 if(s->inputbuffer[0] != '2') { 00138 PSOCK_CLOSE_EXIT(&s->psock); 00139 } 00140 00141 SEND_STRING(&s->psock, "MAIL FROM: contiki@example.com\r\n"); 00142 00143 PSOCK_READTO(&s->psock, '\n'); 00144 if(s->inputbuffer[0] != '2') { 00145 PSOCK_CLOSE_EXIT(&s->psock); 00146 } 00147 00148 SEND_STRING(&s->psock, "RCPT TO: contiki@example.com\r\n"); 00149 00150 PSOCK_READTO(&s->psock, '\n'); 00151 if(s->inputbuffer[0] != '2') { 00152 PSOCK_CLOSE_EXIT(&s->psock); 00153 } 00154 00155 SEND_STRING(&s->psock, "DATA\r\n"); 00156 00157 PSOCK_READTO(&s->psock, '\n'); 00158 if(s->inputbuffer[0] != '3') { 00159 PSOCK_CLOSE_EXIT(&s->psock); 00160 } 00161 00162 SEND_STRING(&s->psock, "To: contiki@example.com\r\n"); 00163 SEND_STRING(&s->psock, "From: contiki@example.com\r\n"); 00164 SEND_STRING(&s->psock, "Subject: Example\r\n"); 00165 00166 SEND_STRING(&s->psock, "A test message from Contiki.\r\n"); 00167 00168 SEND_STRING(&s->psock, "\r\n.\r\n"); 00169 00170 PSOCK_READTO(&s->psock, '\n'); 00171 if(s->inputbuffer[0] != '2') { 00172 PSOCK_CLOSE_EXIT(&s->psock); 00173 } 00174 00175 SEND_STRING(&s->psock, "QUIT\r\n"); 00176 00177 PSOCK_END(&s->psock); 00178 } 00179 00180 void 00181 smtp_uipcall(void *state) 00182 { 00183 struct smtp_state *s = (struct smtp_state *)state; 00184 00185 if(uip_closed() || uip_aborted() || uip_timedout()) { 00186 memb_free(&connections, s); 00187 } else if(uip_connected()) { 00188 PSOCK_INIT(s, s->inputbuffer, sizeof(s->inputbuffer)); 00189 } else { 00190 smtp_socketthread(s); 00191 } 00192 } 00193 \endcode 00194 * 00195 */ 00196 00197 /** 00198 * \file 00199 * Protosocket library header file 00200 * \author 00201 * Adam Dunkels <adam@sics.se> 00202 * 00203 */ 00204 00205 #ifndef __PSOCK_H__ 00206 #define __PSOCK_H__ 00207 00208 #include "pt.h" 00209 #include "uipbuf.h" 00210 #include "memb.h" 00211 00212 /** 00213 * The representation of a protosocket. 00214 * 00215 * The protosocket structrure is an opaque structure with no user-visible 00216 * elements. 00217 */ 00218 struct psock { 00219 struct pt pt, psockpt; 00220 unsigned char state; 00221 const u8_t *sendptr; 00222 u16_t sendlen; 00223 u8_t *readptr; 00224 u16_t readlen; 00225 00226 struct uipbuf_buffer buf; 00227 char *bufptr; 00228 unsigned int bufsize; 00229 }; 00230 00231 void psock_init(struct psock *psock, char *buffer, unsigned int buffersize); 00232 /** 00233 * Initialize a protosocket. 00234 * 00235 * This macro initializes a protosocket and must be called before the 00236 * protosocket is used. The initialization also specifies the input buffer 00237 * for the protosocket. 00238 * 00239 * \param psock (struct psock *) A pointer to the protosocket to be 00240 * initialized 00241 * 00242 * \param buffer (char *) A pointer to the input buffer for the 00243 * protosocket. 00244 * 00245 * \param buffersize (unsigned int) The size of the input buffer. 00246 * 00247 * \hideinitializer 00248 */ 00249 #define PSOCK_INIT(psock, buffer, buffersize) \ 00250 psock_init(psock, buffer, buffersize) 00251 00252 /** 00253 * Start the protosocket protothread in a function. 00254 * 00255 * This macro starts the protothread associated with the protosocket and 00256 * must come before other protosocket calls in the function it is used. 00257 * 00258 * \param psock (struct psock *) A pointer to the protosocket to be 00259 * started. 00260 * 00261 * \hideinitializer 00262 */ 00263 #define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt)) 00264 00265 PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len)); 00266 /** 00267 * Send data. 00268 * 00269 * This macro sends data over a protosocket. The protosocket protothread blocks 00270 * until all data has been sent and is known to have been received by 00271 * the remote end of the TCP connection. 00272 * 00273 * \param psock (struct psock *) A pointer to the protosocket over which 00274 * data is to be sent. 00275 * 00276 * \param data (char *) A pointer to the data that is to be sent. 00277 * 00278 * \param datalen (unsigned int) The length of the data that is to be 00279 * sent. 00280 * 00281 * \hideinitializer 00282 */ 00283 #define PSOCK_SEND(psock, data, datalen) \ 00284 PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen)) 00285 00286 PT_THREAD(psock_generator_send(struct psock *psock, 00287 unsigned short (*f)(void *), void *arg)); 00288 00289 #define PSOCK_GENERATOR_SEND(psock, generator, arg) \ 00290 PT_WAIT_THREAD(&((psock)->pt), \ 00291 psock_generator_send(psock, generator, arg)) 00292 00293 00294 /*PT_THREAD(psock_closew(struct psock *psock)); 00295 #define PSOCK_CLOSEW(psock) \ 00296 PT_WAIT_THREAD(&(psock)->pt, psock_closew(psock)) 00297 */ 00298 00299 /** 00300 * Close a protosocket. 00301 * 00302 * This macro closes a protosocket and can only be called from within the 00303 * protothread in which the protosocket lives. 00304 * 00305 * \param psock (struct psock *) A pointer to the protosocket that is to 00306 * be closed. 00307 * 00308 * \hideinitializer 00309 */ 00310 #define PSOCK_CLOSE(psock) uip_close() 00311 00312 PT_THREAD(psock_readto(struct psock *psock, unsigned char c)); 00313 00314 /** 00315 * Read data up to a specified character. 00316 * 00317 * This macro will block waiting for data and read the data into the 00318 * input buffer specified with the call to PSOCK_INIT(). Data is only 00319 * read until the specifieed character appears in the data stream. 00320 * 00321 * \param psock (struct psock *) A pointer to the protosocket from which 00322 * data should be read. 00323 * 00324 * \param c (char) The character at which to stop reading. 00325 * 00326 * \hideinitializer 00327 */ 00328 #define PSOCK_READTO(psock, c) \ 00329 PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c)) 00330 00331 /** 00332 * The length of the data that was previously read. 00333 * 00334 * This macro returns the length of the data that was previously read 00335 * using PSOCK_READTO() or PSOCK_READ(). 00336 * 00337 * \param psock (struct psock *) A pointer to the protosocket holding the data. 00338 * 00339 * \hideinitializer 00340 */ 00341 #define PSOCK_DATALEN(psock) uipbuf_len(&(psock)->buf) 00342 00343 /** 00344 * Exit the protosocket's protothread. 00345 * 00346 * This macro terminates the protothread of the protosocket and should 00347 * almost always be used in conjunction with PSOCK_CLOSE(). 00348 * 00349 * \sa PSOCK_CLOSE_EXIT() 00350 * 00351 * \param psock (struct psock *) A pointer to the protosocket. 00352 * 00353 * \hideinitializer 00354 */ 00355 #define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt)) 00356 00357 /** 00358 * Close a protosocket and exit the protosocket's protothread. 00359 * 00360 * This macro closes a protosocket and exits the protosocket's protothread. 00361 * 00362 * \param psock (struct psock *) A pointer to the protosocket. 00363 * 00364 * \hideinitializer 00365 */ 00366 #define PSOCK_CLOSE_EXIT(psock) \ 00367 do { \ 00368 PSOCK_CLOSE(psock); \ 00369 PSOCK_EXIT(psock); \ 00370 } while(0) 00371 00372 #define PSOCK_END(psock) PT_END(&((psock)->pt)) 00373 00374 char psock_newdata(struct psock *s); 00375 00376 /** 00377 * Check if new data has arrived on a protosocket. 00378 * 00379 * This macro is used in conjunction with the PSOCK_WAIT_UNTIL() 00380 * macro to check if data has arrived on a protosocket. 00381 * 00382 * \param psock (struct psock *) A pointer to the protosocket. 00383 * 00384 * \hideinitializer 00385 */ 00386 #define PSOCK_NEWDATA(psock) psock_newdata(psock) 00387 00388 /** 00389 * Wait until a condition is true. 00390 * 00391 * This macro blocks the protothread until the specified condition is 00392 * true. The macro PSOCK_NEWDATA() can be used to check if new data 00393 * arrives when the protosocket is waiting. 00394 * 00395 * Typically, this macro is used as follows: 00396 * 00397 \code 00398 PT_THREAD(thread(struct psock *s, struct timer *t)) 00399 { 00400 PSOCK_BEGIN(s); 00401 00402 PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t)); 00403 00404 if(PSOCK_NEWDATA(s)) { 00405 PSOCK_READTO(s, '\n'); 00406 } else { 00407 handle_timed_out(s); 00408 } 00409 00410 PSOCK_END(s); 00411 } 00412 \endcode 00413 * 00414 * \param psock (struct psock *) A pointer to the protosocket. 00415 * \param condition The condition to wait for. 00416 * 00417 * \hideinitializer 00418 */ 00419 #define PSOCK_WAIT_UNTIL(psock, condition) \ 00420 PT_WAIT_UNTIL(&((psock)->pt), (condition)); 00421 00422 #define PSOCK_WAIT_THREAD(psock, condition) \ 00423 PT_WAIT_THREAD(&((psock)->pt), (condition)) 00424 00425 #endif /* __PSOCK_H__ */
1.3.6