blob: 287bf44f902f8bd4c93749a10f36d26c86316a8f [file] [log] [blame]
adamdunkelsd0791bb2005-02-22 22:23:07 +00001/*
2 * Copyright (c) 2004, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 * Author: Adam Dunkels <adam@sics.se>
32 *
33 * $Id: psock.h,v 1.1 2005/02/22 22:23:07 adamdunkels Exp $
34 */
35
36/**
37 * \defgroup psock Protosockets library
38 * @{
39 *
40 * The protosocket library provides an interface to the uIP stack that is
41 * similar to the traditional BSD socket interface. Unlike programs
42 * written for the ordinary uIP event-driven interface, programs
43 * written with the protosocket library are executed in a sequential
44 * fashion and does not have to be implemented as explicit state
45 * machines.
46 *
47 * Protosockets only work with TCP connections.
48 *
49 * The protosocket library uses \ref pt protothreads to provide
50 * sequential control flow. This makes the protosockets lightweight in
51 * terms of memory, but also means that protosockets inherits the
52 * functional limitations of protothreads. Each protosocket lives only
53 * within a single function block. Automatic variables (stack
54 * variables) are not necessarily retained across a protosocket
55 * library function call.
56 *
57 * \note Because the protosocket library uses protothreads, local variables
58 * will not always be saved across a call to a protosocket library
59 * function. It is therefore advised that local variables are used
60 * with extreme care.
61 *
62 * The protosocket library provides functions for sending data without
63 * having to deal with retransmissions and acknowledgements, as well
64 * as functions for reading data without having to deal with data
65 * being split across more than one TCP segment.
66 *
67 * Because each protosocket runs as a protothread, the protosocket has to be
68 * started with a call to PSOCK_BEGIN() at the start of the function
69 * in which the protosocket is used. Similarly, the protosocket protothread can
70 * be terminated by a call to PSOCK_EXIT().
71 *
72 * The example code below illustrates how to use the protosocket
73 * library. The program implements a simple SMTP client that sends a
74 * short email. The program is divided into two functions, one uIP
75 * event handler (smtp_uipcall()) and one function that runs the
76 * protosocket protothread and performs the SMTP communication
77 * (smtp_socketthread()).
78 *
79 * An SMTP connection is represented by a smtp_state structure
80 * containing a struct psock and a small input buffer. The input
81 * buffer only needs to be 3 bytes long to accomodate the 3 byte
82 * status codes used by SMTP. Connection structures can be allocated
83 * from the memory buffer called connections, which is declared with
84 * the MEMB() macro.
85 *
86 * The convenience macro SEND_STRING() is defined in order to simplify
87 * the code, as it mostly involves sending strings.
88 *
89 * The function smtp_socketthread() is declared as a protothread using
90 * the PT_THREAD() macro. The PSOCK_BEGIN() call at the first line of
91 * the smtp_socketthread() function starts the protothread. SMTP
92 * specifies that the server will start with sending a welcome message
93 * that should include the status code 220 if the server is ready to
94 * accept messages. Therefore, the smtp_socketthread() first calls
95 * PSOCK_READTO() to read all incoming data up to the first
96 * newline. If the status code was anything else but 220, the protosocket
97 * is closed and the protosocket's protothread is terminated with the call
98 * to PSOCK_CLOSE_EXIT().
99 *
100 * If the connection is accepted by the server, smtp_socketthread()
101 * continues with sending the HELO message. If this gets a positive
102 * reply (a status code beginning with a 2), the protothread moves on
103 * with the rest of the SMTP procedure. Finally, after all headers and
104 * data is sent, the program sends a QUIT before it finally closes the
105 * protosocket and exits the protosocket's protothread.
106 *
107 *
108 \code
109#include <string.h>
110
111#include "psock.h"
112#include "memb.h"
113
114struct smtp_state {
115 struct psock psock;
116 char inputbuffer[3];
117};
118
119MEMB(connections, sizeof(struct smtp_state), 2);
120
121#define SEND_STRING(s, str) PSOCK_SEND(s, str, strlen(str))
122
123static
124PT_THREAD(smtp_socketthread(struct smtp_state *s))
125{
126 PSOCK_BEGIN(&s->psock);
127
128 PSOCK_READTO(&s->psock, '\n');
129
130 if(strncmp(s->inputbuffer, "220", 3) != 0) {
131 PSOCK_CLOSE_EXIT(&s->psock);
132 }
133
134 SEND_STRING(&s->psock, "HELO contiki.example.com\r\n");
135
136 PSOCK_READTO(&s->psock, '\n');
137 if(s->inputbuffer[0] != '2') {
138 PSOCK_CLOSE_EXIT(&s->psock);
139 }
140
141 SEND_STRING(&s->psock, "MAIL FROM: contiki@example.com\r\n");
142
143 PSOCK_READTO(&s->psock, '\n');
144 if(s->inputbuffer[0] != '2') {
145 PSOCK_CLOSE_EXIT(&s->psock);
146 }
147
148 SEND_STRING(&s->psock, "RCPT TO: contiki@example.com\r\n");
149
150 PSOCK_READTO(&s->psock, '\n');
151 if(s->inputbuffer[0] != '2') {
152 PSOCK_CLOSE_EXIT(&s->psock);
153 }
154
155 SEND_STRING(&s->psock, "DATA\r\n");
156
157 PSOCK_READTO(&s->psock, '\n');
158 if(s->inputbuffer[0] != '3') {
159 PSOCK_CLOSE_EXIT(&s->psock);
160 }
161
162 SEND_STRING(&s->psock, "To: contiki@example.com\r\n");
163 SEND_STRING(&s->psock, "From: contiki@example.com\r\n");
164 SEND_STRING(&s->psock, "Subject: Example\r\n");
165
166 SEND_STRING(&s->psock, "A test message from Contiki.\r\n");
167
168 SEND_STRING(&s->psock, "\r\n.\r\n");
169
170 PSOCK_READTO(&s->psock, '\n');
171 if(s->inputbuffer[0] != '2') {
172 PSOCK_CLOSE_EXIT(&s->psock);
173 }
174
175 SEND_STRING(&s->psock, "QUIT\r\n");
176
177 PSOCK_END(&s->psock);
178}
179
180void
181smtp_uipcall(void *state)
182{
183 struct smtp_state *s = (struct smtp_state *)state;
184
185 if(uip_closed() || uip_aborted() || uip_timedout()) {
186 memb_free(&connections, s);
187 } else if(uip_connected()) {
188 PSOCK_INIT(s, s->inputbuffer, sizeof(s->inputbuffer));
189 } else {
190 smtp_socketthread(s);
191 }
192}
193 \endcode
194 *
195 */
196
197/**
198 * \file
199 * Protosocket library header file
200 * \author
201 * Adam Dunkels <adam@sics.se>
202 *
203 */
204
205#ifndef __PSOCK_H__
206#define __PSOCK_H__
207
208#include "pt.h"
209#include "uipbuf.h"
210#include "memb.h"
211
212/**
213 * The representation of a protosocket.
214 *
215 * The protosocket structrure is an opaque structure with no user-visible
216 * elements.
217 */
218struct psock {
219 struct pt pt, psockpt;
220 unsigned char state;
221 const u8_t *sendptr;
222 u16_t sendlen;
223 u8_t *readptr;
224 u16_t readlen;
225
226 struct uipbuf_buffer buf;
227 char *bufptr;
228 unsigned int bufsize;
229};
230
231void psock_init(struct psock *psock, char *buffer, unsigned int buffersize);
232/**
233 * Initialize a protosocket.
234 *
235 * This macro initializes a protosocket and must be called before the
236 * protosocket is used. The initialization also specifies the input buffer
237 * for the protosocket.
238 *
239 * \param psock (struct psock *) A pointer to the protosocket to be
240 * initialized
241 *
242 * \param buffer (char *) A pointer to the input buffer for the
243 * protosocket.
244 *
245 * \param buffersize (unsigned int) The size of the input buffer.
246 *
247 * \hideinitializer
248 */
249#define PSOCK_INIT(psock, buffer, buffersize) \
250 psock_init(psock, buffer, buffersize)
251
252/**
253 * Start the protosocket protothread in a function.
254 *
255 * This macro starts the protothread associated with the protosocket and
256 * must come before other protosocket calls in the function it is used.
257 *
258 * \param psock (struct psock *) A pointer to the protosocket to be
259 * started.
260 *
261 * \hideinitializer
262 */
263#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
264
265PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len));
266/**
267 * Send data.
268 *
269 * This macro sends data over a protosocket. The protosocket protothread blocks
270 * until all data has been sent and is known to have been received by
271 * the remote end of the TCP connection.
272 *
273 * \param psock (struct psock *) A pointer to the protosocket over which
274 * data is to be sent.
275 *
276 * \param data (char *) A pointer to the data that is to be sent.
277 *
278 * \param datalen (unsigned int) The length of the data that is to be
279 * sent.
280 *
281 * \hideinitializer
282 */
283#define PSOCK_SEND(psock, data, datalen) \
284 PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
285
286PT_THREAD(psock_generator_send(struct psock *psock,
287 unsigned short (*f)(void *), void *arg));
288
289#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
290 PT_WAIT_THREAD(&((psock)->pt), \
291 psock_generator_send(psock, generator, arg))
292
293
294/*PT_THREAD(psock_closew(struct psock *psock));
295#define PSOCK_CLOSEW(psock) \
296 PT_WAIT_THREAD(&(psock)->pt, psock_closew(psock))
297*/
298
299/**
300 * Close a protosocket.
301 *
302 * This macro closes a protosocket and can only be called from within the
303 * protothread in which the protosocket lives.
304 *
305 * \param psock (struct psock *) A pointer to the protosocket that is to
306 * be closed.
307 *
308 * \hideinitializer
309 */
310#define PSOCK_CLOSE(psock) uip_close()
311
312PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
313
314/**
315 * Read data up to a specified character.
316 *
317 * This macro will block waiting for data and read the data into the
318 * input buffer specified with the call to PSOCK_INIT(). Data is only
319 * read until the specifieed character appears in the data stream.
320 *
321 * \param psock (struct psock *) A pointer to the protosocket from which
322 * data should be read.
323 *
324 * \param c (char) The character at which to stop reading.
325 *
326 * \hideinitializer
327 */
328#define PSOCK_READTO(psock, c) \
329 PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
330
331/**
332 * The length of the data that was previously read.
333 *
334 * This macro returns the length of the data that was previously read
335 * using PSOCK_READTO() or PSOCK_READ().
336 *
337 * \param psock (struct psock *) A pointer to the protosocket holding the data.
338 *
339 * \hideinitializer
340 */
341#define PSOCK_DATALEN(psock) uipbuf_len(&(psock)->buf)
342
343/**
344 * Exit the protosocket's protothread.
345 *
346 * This macro terminates the protothread of the protosocket and should
347 * almost always be used in conjunction with PSOCK_CLOSE().
348 *
349 * \sa PSOCK_CLOSE_EXIT()
350 *
351 * \param psock (struct psock *) A pointer to the protosocket.
352 *
353 * \hideinitializer
354 */
355#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
356
357/**
358 * Close a protosocket and exit the protosocket's protothread.
359 *
360 * This macro closes a protosocket and exits the protosocket's protothread.
361 *
362 * \param psock (struct psock *) A pointer to the protosocket.
363 *
364 * \hideinitializer
365 */
366#define PSOCK_CLOSE_EXIT(psock) \
367 do { \
368 PSOCK_CLOSE(psock); \
369 PSOCK_EXIT(psock); \
370 } while(0)
371
372#define PSOCK_END(psock) PT_END(&((psock)->pt))
373
374char psock_newdata(struct psock *s);
375
376/**
377 * Check if new data has arrived on a protosocket.
378 *
379 * This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
380 * macro to check if data has arrived on a protosocket.
381 *
382 * \param psock (struct psock *) A pointer to the protosocket.
383 *
384 * \hideinitializer
385 */
386#define PSOCK_NEWDATA(psock) psock_newdata(psock)
387
388/**
389 * Wait until a condition is true.
390 *
391 * This macro blocks the protothread until the specified condition is
392 * true. The macro PSOCK_NEWDATA() can be used to check if new data
393 * arrives when the protosocket is waiting.
394 *
395 * Typically, this macro is used as follows:
396 *
397 \code
398 PT_THREAD(thread(struct psock *s, struct timer *t))
399 {
400 PSOCK_BEGIN(s);
401
402 PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
403
404 if(PSOCK_NEWDATA(s)) {
405 PSOCK_READTO(s, '\n');
406 } else {
407 handle_timed_out(s);
408 }
409
410 PSOCK_END(s);
411 }
412 \endcode
413 *
414 * \param psock (struct psock *) A pointer to the protosocket.
415 * \param condition The condition to wait for.
416 *
417 * \hideinitializer
418 */
419#define PSOCK_WAIT_UNTIL(psock, condition) \
420 PT_WAIT_UNTIL(&((psock)->pt), (condition));
421
422#define PSOCK_WAIT_THREAD(psock, condition) \
423 PT_WAIT_THREAD(&((psock)->pt), (condition))
424
425#endif /* __PSOCK_H__ */