| /* | |
| * Copyright (c) 2004, Swedish Institute of Computer Science. | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * 3. Neither the name of the Institute nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| * SUCH DAMAGE. | |
| * | |
| * This file is part of the uIP TCP/IP stack | |
| * | |
| * Author: Adam Dunkels <adam@sics.se> | |
| * | |
| * $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $ | |
| */ | |
| /** | |
| * \defgroup psock Protosockets library | |
| * @{ | |
| * | |
| * The protosocket library provides an interface to the uIP stack that is | |
| * similar to the traditional BSD socket interface. Unlike programs | |
| * written for the ordinary uIP event-driven interface, programs | |
| * written with the protosocket library are executed in a sequential | |
| * fashion and does not have to be implemented as explicit state | |
| * machines. | |
| * | |
| * Protosockets only work with TCP connections. | |
| * | |
| * The protosocket library uses \ref pt protothreads to provide | |
| * sequential control flow. This makes the protosockets lightweight in | |
| * terms of memory, but also means that protosockets inherits the | |
| * functional limitations of protothreads. Each protosocket lives only | |
| * within a single function. Automatic variables (stack variables) are | |
| * not retained across a protosocket library function call. | |
| * | |
| * \note Because the protosocket library uses protothreads, local | |
| * variables will not always be saved across a call to a protosocket | |
| * library function. It is therefore advised that local variables are | |
| * used with extreme care. | |
| * | |
| * The protosocket library provides functions for sending data without | |
| * having to deal with retransmissions and acknowledgements, as well | |
| * as functions for reading data without having to deal with data | |
| * being split across more than one TCP segment. | |
| * | |
| * Because each protosocket runs as a protothread, the protosocket has to be | |
| * started with a call to PSOCK_BEGIN() at the start of the function | |
| * in which the protosocket is used. Similarly, the protosocket protothread can | |
| * be terminated by a call to PSOCK_EXIT(). | |
| * | |
| */ | |
| /** | |
| * \file | |
| * Protosocket library header file | |
| * \author | |
| * Adam Dunkels <adam@sics.se> | |
| * | |
| */ | |
| #ifndef __PSOCK_H__ | |
| #define __PSOCK_H__ | |
| #include "uipopt.h" | |
| #include "pt.h" | |
| /* | |
| * The structure that holds the state of a buffer. | |
| * | |
| * This structure holds the state of a uIP buffer. The structure has | |
| * no user-visible elements, but is used through the functions | |
| * provided by the library. | |
| * | |
| */ | |
| struct psock_buf { | |
| u8_t *ptr; | |
| unsigned short left; | |
| }; | |
| /** | |
| * The representation of a protosocket. | |
| * | |
| * The protosocket structrure is an opaque structure with no user-visible | |
| * elements. | |
| */ | |
| struct psock { | |
| struct pt pt, psockpt; /* Protothreads - one that's using the psock | |
| functions, and one that runs inside the | |
| psock functions. */ | |
| const u8_t *sendptr; /* Pointer to the next data to be sent. */ | |
| u8_t *readptr; /* Pointer to the next data to be read. */ | |
| char *bufptr; /* Pointer to the buffer used for buffering | |
| incoming data. */ | |
| u16_t sendlen; /* The number of bytes left to be sent. */ | |
| u16_t readlen; /* The number of bytes left to be read. */ | |
| struct psock_buf buf; /* The structure holding the state of the | |
| input buffer. */ | |
| unsigned int bufsize; /* The size of the input buffer. */ | |
| unsigned char state; /* The state of the protosocket. */ | |
| }; | |
| void psock_init(struct psock *psock, char *buffer, unsigned int buffersize); | |
| /** | |
| * Initialize a protosocket. | |
| * | |
| * This macro initializes a protosocket and must be called before the | |
| * protosocket is used. The initialization also specifies the input buffer | |
| * for the protosocket. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket to be | |
| * initialized | |
| * | |
| * \param buffer (char *) A pointer to the input buffer for the | |
| * protosocket. | |
| * | |
| * \param buffersize (unsigned int) The size of the input buffer. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_INIT(psock, buffer, buffersize) \ | |
| psock_init(psock, buffer, buffersize) | |
| /** | |
| * Start the protosocket protothread in a function. | |
| * | |
| * This macro starts the protothread associated with the protosocket and | |
| * must come before other protosocket calls in the function it is used. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket to be | |
| * started. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt)) | |
| PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len)); | |
| /** | |
| * Send data. | |
| * | |
| * This macro sends data over a protosocket. The protosocket protothread blocks | |
| * until all data has been sent and is known to have been received by | |
| * the remote end of the TCP connection. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket over which | |
| * data is to be sent. | |
| * | |
| * \param data (char *) A pointer to the data that is to be sent. | |
| * | |
| * \param datalen (unsigned int) The length of the data that is to be | |
| * sent. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_SEND(psock, data, datalen) \ | |
| PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen)) | |
| /** | |
| * \brief Send a null-terminated string. | |
| * \param psock Pointer to the protosocket. | |
| * \param str The string to be sent. | |
| * | |
| * This function sends a null-terminated string over the | |
| * protosocket. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_SEND_STR(psock, str) \ | |
| PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str))) | |
| PT_THREAD(psock_generator_send(struct psock *psock, | |
| unsigned short (*f)(void *), void *arg)); | |
| /** | |
| * \brief Generate data with a function and send it | |
| * \param psock Pointer to the protosocket. | |
| * \param generator Pointer to the generator function | |
| * \param arg Argument to the generator function | |
| * | |
| * This function generates data and sends it over the | |
| * protosocket. This can be used to dynamically generate | |
| * data for a transmission, instead of generating the data | |
| * in a buffer beforehand. This function reduces the need for | |
| * buffer memory. The generator function is implemented by | |
| * the application, and a pointer to the function is given | |
| * as an argument with the call to PSOCK_GENERATOR_SEND(). | |
| * | |
| * The generator function should place the generated data | |
| * directly in the uip_appdata buffer, and return the | |
| * length of the generated data. The generator function is | |
| * called by the protosocket layer when the data first is | |
| * sent, and once for every retransmission that is needed. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_GENERATOR_SEND(psock, generator, arg) \ | |
| PT_WAIT_THREAD(&((psock)->pt), \ | |
| psock_generator_send(psock, generator, arg)) | |
| /** | |
| * Close a protosocket. | |
| * | |
| * This macro closes a protosocket and can only be called from within the | |
| * protothread in which the protosocket lives. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket that is to | |
| * be closed. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_CLOSE(psock) uip_close() | |
| PT_THREAD(psock_readbuf(struct psock *psock)); | |
| /** | |
| * Read data until the buffer is full. | |
| * | |
| * This macro will block waiting for data and read the data into the | |
| * input buffer specified with the call to PSOCK_INIT(). Data is read | |
| * until the buffer is full.. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket from which | |
| * data should be read. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_READBUF(psock) \ | |
| PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock)) | |
| PT_THREAD(psock_readto(struct psock *psock, unsigned char c)); | |
| /** | |
| * Read data up to a specified character. | |
| * | |
| * This macro will block waiting for data and read the data into the | |
| * input buffer specified with the call to PSOCK_INIT(). Data is only | |
| * read until the specifieed character appears in the data stream. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket from which | |
| * data should be read. | |
| * | |
| * \param c (char) The character at which to stop reading. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_READTO(psock, c) \ | |
| PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c)) | |
| /** | |
| * The length of the data that was previously read. | |
| * | |
| * This macro returns the length of the data that was previously read | |
| * using PSOCK_READTO() or PSOCK_READ(). | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket holding the data. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_DATALEN(psock) psock_datalen(psock) | |
| u16_t psock_datalen(struct psock *psock); | |
| /** | |
| * Exit the protosocket's protothread. | |
| * | |
| * This macro terminates the protothread of the protosocket and should | |
| * almost always be used in conjunction with PSOCK_CLOSE(). | |
| * | |
| * \sa PSOCK_CLOSE_EXIT() | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt)) | |
| /** | |
| * Close a protosocket and exit the protosocket's protothread. | |
| * | |
| * This macro closes a protosocket and exits the protosocket's protothread. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_CLOSE_EXIT(psock) \ | |
| do { \ | |
| PSOCK_CLOSE(psock); \ | |
| PSOCK_EXIT(psock); \ | |
| } while(0) | |
| /** | |
| * Declare the end of a protosocket's protothread. | |
| * | |
| * This macro is used for declaring that the protosocket's protothread | |
| * ends. It must always be used together with a matching PSOCK_BEGIN() | |
| * macro. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_END(psock) PT_END(&((psock)->pt)) | |
| char psock_newdata(struct psock *s); | |
| /** | |
| * Check if new data has arrived on a protosocket. | |
| * | |
| * This macro is used in conjunction with the PSOCK_WAIT_UNTIL() | |
| * macro to check if data has arrived on a protosocket. | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_NEWDATA(psock) psock_newdata(psock) | |
| /** | |
| * Wait until a condition is true. | |
| * | |
| * This macro blocks the protothread until the specified condition is | |
| * true. The macro PSOCK_NEWDATA() can be used to check if new data | |
| * arrives when the protosocket is waiting. | |
| * | |
| * Typically, this macro is used as follows: | |
| * | |
| \code | |
| PT_THREAD(thread(struct psock *s, struct timer *t)) | |
| { | |
| PSOCK_BEGIN(s); | |
| PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t)); | |
| if(PSOCK_NEWDATA(s)) { | |
| PSOCK_READTO(s, '\n'); | |
| } else { | |
| handle_timed_out(s); | |
| } | |
| PSOCK_END(s); | |
| } | |
| \endcode | |
| * | |
| * \param psock (struct psock *) A pointer to the protosocket. | |
| * \param condition The condition to wait for. | |
| * | |
| * \hideinitializer | |
| */ | |
| #define PSOCK_WAIT_UNTIL(psock, condition) \ | |
| PT_WAIT_UNTIL(&((psock)->pt), (condition)); | |
| #define PSOCK_WAIT_THREAD(psock, condition) \ | |
| PT_WAIT_THREAD(&((psock)->pt), (condition)) | |
| #endif /* __PSOCK_H__ */ | |
| /** @} */ |