1 | /*
|
---|
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 uIP TCP/IP stack
|
---|
30 | *
|
---|
31 | * Author: Adam Dunkels <adam@sics.se>
|
---|
32 | *
|
---|
33 | * $Id: psock.h 262 2016-11-18 05:58:30Z coas-nagasima $
|
---|
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. Automatic variables (stack variables) are
|
---|
54 | * not retained across a protosocket library function call.
|
---|
55 | *
|
---|
56 | * \note Because the protosocket library uses protothreads, local
|
---|
57 | * variables will not always be saved across a call to a protosocket
|
---|
58 | * library function. It is therefore advised that local variables are
|
---|
59 | * used with extreme care.
|
---|
60 | *
|
---|
61 | * The protosocket library provides functions for sending data without
|
---|
62 | * having to deal with retransmissions and acknowledgements, as well
|
---|
63 | * as functions for reading data without having to deal with data
|
---|
64 | * being split across more than one TCP segment.
|
---|
65 | *
|
---|
66 | * Because each protosocket runs as a protothread, the protosocket has to be
|
---|
67 | * started with a call to PSOCK_BEGIN() at the start of the function
|
---|
68 | * in which the protosocket is used. Similarly, the protosocket protothread can
|
---|
69 | * be terminated by a call to PSOCK_EXIT().
|
---|
70 | *
|
---|
71 | */
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * \file
|
---|
75 | * Protosocket library header file
|
---|
76 | * \author
|
---|
77 | * Adam Dunkels <adam@sics.se>
|
---|
78 | *
|
---|
79 | */
|
---|
80 |
|
---|
81 | #ifndef __PSOCK_H__
|
---|
82 | #define __PSOCK_H__
|
---|
83 |
|
---|
84 | #include "net/ip/uipopt.h"
|
---|
85 | #include "sys/pt.h"
|
---|
86 |
|
---|
87 | /*
|
---|
88 | * The structure that holds the state of a buffer.
|
---|
89 | *
|
---|
90 | * This structure holds the state of a uIP buffer. The structure has
|
---|
91 | * no user-visible elements, but is used through the functions
|
---|
92 | * provided by the library.
|
---|
93 | *
|
---|
94 | */
|
---|
95 | struct psock_buf {
|
---|
96 | uint8_t *ptr;
|
---|
97 | unsigned short left;
|
---|
98 | };
|
---|
99 |
|
---|
100 | /**
|
---|
101 | * The representation of a protosocket.
|
---|
102 | *
|
---|
103 | * The protosocket structrure is an opaque structure with no user-visible
|
---|
104 | * elements.
|
---|
105 | */
|
---|
106 | struct psock {
|
---|
107 | struct pt pt, psockpt; /* Protothreads - one that's using the psock
|
---|
108 | functions, and one that runs inside the
|
---|
109 | psock functions. */
|
---|
110 | const uint8_t *sendptr; /* Pointer to the next data to be sent. */
|
---|
111 | uint8_t *readptr; /* Pointer to the next data to be read. */
|
---|
112 |
|
---|
113 | uint8_t *bufptr; /* Pointer to the buffer used for buffering
|
---|
114 | incoming data. */
|
---|
115 |
|
---|
116 | uint16_t sendlen; /* The number of bytes left to be sent. */
|
---|
117 | uint16_t readlen; /* The number of bytes left to be read. */
|
---|
118 |
|
---|
119 | struct psock_buf buf; /* The structure holding the state of the
|
---|
120 | input buffer. */
|
---|
121 | unsigned int bufsize; /* The size of the input buffer. */
|
---|
122 |
|
---|
123 | unsigned char state; /* The state of the protosocket. */
|
---|
124 | };
|
---|
125 |
|
---|
126 | void psock_init(struct psock *psock, uint8_t *buffer, unsigned int buffersize);
|
---|
127 | /**
|
---|
128 | * Initialize a protosocket.
|
---|
129 | *
|
---|
130 | * This macro initializes a protosocket and must be called before the
|
---|
131 | * protosocket is used. The initialization also specifies the input buffer
|
---|
132 | * for the protosocket.
|
---|
133 | *
|
---|
134 | * \param psock (struct psock *) A pointer to the protosocket to be
|
---|
135 | * initialized
|
---|
136 | *
|
---|
137 | * \param buffer (uint8_t *) A pointer to the input buffer for the
|
---|
138 | * protosocket.
|
---|
139 | *
|
---|
140 | * \param buffersize (unsigned int) The size of the input buffer.
|
---|
141 | *
|
---|
142 | * \hideinitializer
|
---|
143 | */
|
---|
144 | #define PSOCK_INIT(psock, buffer, buffersize) \
|
---|
145 | psock_init(psock, buffer, buffersize)
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Start the protosocket protothread in a function.
|
---|
149 | *
|
---|
150 | * This macro starts the protothread associated with the protosocket and
|
---|
151 | * must come before other protosocket calls in the function it is used.
|
---|
152 | *
|
---|
153 | * \param psock (struct psock *) A pointer to the protosocket to be
|
---|
154 | * started.
|
---|
155 | *
|
---|
156 | * \hideinitializer
|
---|
157 | */
|
---|
158 | #define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
|
---|
159 |
|
---|
160 | PT_THREAD(psock_send(struct psock *psock, const uint8_t *buf, unsigned int len));
|
---|
161 | /**
|
---|
162 | * Send data.
|
---|
163 | *
|
---|
164 | * This macro sends data over a protosocket. The protosocket protothread blocks
|
---|
165 | * until all data has been sent and is known to have been received by
|
---|
166 | * the remote end of the TCP connection.
|
---|
167 | *
|
---|
168 | * \param psock (struct psock *) A pointer to the protosocket over which
|
---|
169 | * data is to be sent.
|
---|
170 | *
|
---|
171 | * \param data (uint8_t *) A pointer to the data that is to be sent.
|
---|
172 | *
|
---|
173 | * \param datalen (unsigned int) The length of the data that is to be
|
---|
174 | * sent.
|
---|
175 | *
|
---|
176 | * \hideinitializer
|
---|
177 | */
|
---|
178 | #define PSOCK_SEND(psock, data, datalen) \
|
---|
179 | PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
|
---|
180 |
|
---|
181 | /**
|
---|
182 | * \brief Send a null-terminated string.
|
---|
183 | * \param psock Pointer to the protosocket.
|
---|
184 | * \param str The string to be sent.
|
---|
185 | *
|
---|
186 | * This function sends a null-terminated string over the
|
---|
187 | * protosocket.
|
---|
188 | *
|
---|
189 | * \hideinitializer
|
---|
190 | */
|
---|
191 | #define PSOCK_SEND_STR(psock, str) \
|
---|
192 | PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, (uint8_t *)str, strlen(str)))
|
---|
193 |
|
---|
194 | PT_THREAD(psock_generator_send(struct psock *psock,
|
---|
195 | unsigned short (*f)(void *), void *arg));
|
---|
196 |
|
---|
197 | /**
|
---|
198 | * \brief Generate data with a function and send it
|
---|
199 | * \param psock Pointer to the protosocket.
|
---|
200 | * \param generator Pointer to the generator function
|
---|
201 | * \param arg Argument to the generator function
|
---|
202 | *
|
---|
203 | * This function generates data and sends it over the
|
---|
204 | * protosocket. This can be used to dynamically generate
|
---|
205 | * data for a transmission, instead of generating the data
|
---|
206 | * in a buffer beforehand. This function reduces the need for
|
---|
207 | * buffer memory. The generator function is implemented by
|
---|
208 | * the application, and a pointer to the function is given
|
---|
209 | * as an argument with the call to PSOCK_GENERATOR_SEND().
|
---|
210 | *
|
---|
211 | * The generator function should place the generated data
|
---|
212 | * directly in the uip_appdata buffer, and return the
|
---|
213 | * length of the generated data. The generator function is
|
---|
214 | * called by the protosocket layer when the data first is
|
---|
215 | * sent, and once for every retransmission that is needed.
|
---|
216 | *
|
---|
217 | * \hideinitializer
|
---|
218 | */
|
---|
219 | #define PSOCK_GENERATOR_SEND(psock, generator, arg) \
|
---|
220 | PT_WAIT_THREAD(&((psock)->pt), \
|
---|
221 | psock_generator_send(psock, generator, arg))
|
---|
222 |
|
---|
223 |
|
---|
224 | /**
|
---|
225 | * Close a protosocket.
|
---|
226 | *
|
---|
227 | * This macro closes a protosocket and can only be called from within the
|
---|
228 | * protothread in which the protosocket lives.
|
---|
229 | *
|
---|
230 | * \param psock (struct psock *) A pointer to the protosocket that is to
|
---|
231 | * be closed.
|
---|
232 | *
|
---|
233 | * \hideinitializer
|
---|
234 | */
|
---|
235 | #define PSOCK_CLOSE(psock) uip_close()
|
---|
236 |
|
---|
237 | PT_THREAD(psock_readbuf(struct psock *psock));
|
---|
238 | /**
|
---|
239 | * Read data until the buffer is full.
|
---|
240 | *
|
---|
241 | * This macro will block waiting for data and read the data into the
|
---|
242 | * input buffer specified with the call to PSOCK_INIT(). Data is read
|
---|
243 | * until the buffer is full..
|
---|
244 | *
|
---|
245 | * \param psock (struct psock *) A pointer to the protosocket from which
|
---|
246 | * data should be read.
|
---|
247 | *
|
---|
248 | * \hideinitializer
|
---|
249 | */
|
---|
250 | #define PSOCK_READBUF(psock) \
|
---|
251 | PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
|
---|
252 |
|
---|
253 | PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
|
---|
254 | /**
|
---|
255 | * Read data up to a specified character.
|
---|
256 | *
|
---|
257 | * This macro will block waiting for data and read the data into the
|
---|
258 | * input buffer specified with the call to PSOCK_INIT(). Data is only
|
---|
259 | * read until the specified character appears in the data stream.
|
---|
260 | *
|
---|
261 | * \param psock (struct psock *) A pointer to the protosocket from which
|
---|
262 | * data should be read.
|
---|
263 | *
|
---|
264 | * \param c (char) The character at which to stop reading.
|
---|
265 | *
|
---|
266 | * \hideinitializer
|
---|
267 | */
|
---|
268 | #define PSOCK_READTO(psock, c) \
|
---|
269 | PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
|
---|
270 |
|
---|
271 | /**
|
---|
272 | * The length of the data that was previously read.
|
---|
273 | *
|
---|
274 | * This macro returns the length of the data that was previously read
|
---|
275 | * using PSOCK_READTO() or PSOCK_READ().
|
---|
276 | *
|
---|
277 | * \param psock (struct psock *) A pointer to the protosocket holding the data.
|
---|
278 | *
|
---|
279 | * \hideinitializer
|
---|
280 | */
|
---|
281 | #define PSOCK_DATALEN(psock) psock_datalen(psock)
|
---|
282 |
|
---|
283 | uint16_t psock_datalen(struct psock *psock);
|
---|
284 |
|
---|
285 | /**
|
---|
286 | * Exit the protosocket's protothread.
|
---|
287 | *
|
---|
288 | * This macro terminates the protothread of the protosocket and should
|
---|
289 | * almost always be used in conjunction with PSOCK_CLOSE().
|
---|
290 | *
|
---|
291 | * \sa PSOCK_CLOSE_EXIT()
|
---|
292 | *
|
---|
293 | * \param psock (struct psock *) A pointer to the protosocket.
|
---|
294 | *
|
---|
295 | * \hideinitializer
|
---|
296 | */
|
---|
297 | #define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
|
---|
298 |
|
---|
299 | /**
|
---|
300 | * Close a protosocket and exit the protosocket's protothread.
|
---|
301 | *
|
---|
302 | * This macro closes a protosocket and exits the protosocket's protothread.
|
---|
303 | *
|
---|
304 | * \param psock (struct psock *) A pointer to the protosocket.
|
---|
305 | *
|
---|
306 | * \hideinitializer
|
---|
307 | */
|
---|
308 | #define PSOCK_CLOSE_EXIT(psock) \
|
---|
309 | do { \
|
---|
310 | PSOCK_CLOSE(psock); \
|
---|
311 | PSOCK_EXIT(psock); \
|
---|
312 | } while(0)
|
---|
313 |
|
---|
314 | /**
|
---|
315 | * Declare the end of a protosocket's protothread.
|
---|
316 | *
|
---|
317 | * This macro is used for declaring that the protosocket's protothread
|
---|
318 | * ends. It must always be used together with a matching PSOCK_BEGIN()
|
---|
319 | * macro.
|
---|
320 | *
|
---|
321 | * \param psock (struct psock *) A pointer to the protosocket.
|
---|
322 | *
|
---|
323 | * \hideinitializer
|
---|
324 | */
|
---|
325 | #define PSOCK_END(psock) PT_END(&((psock)->pt))
|
---|
326 |
|
---|
327 | char psock_newdata(struct psock *s);
|
---|
328 |
|
---|
329 | /**
|
---|
330 | * Check if new data has arrived on a protosocket.
|
---|
331 | *
|
---|
332 | * This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
|
---|
333 | * macro to check if data has arrived on a protosocket.
|
---|
334 | *
|
---|
335 | * \param psock (struct psock *) A pointer to the protosocket.
|
---|
336 | *
|
---|
337 | * \hideinitializer
|
---|
338 | */
|
---|
339 | #define PSOCK_NEWDATA(psock) psock_newdata(psock)
|
---|
340 |
|
---|
341 | /**
|
---|
342 | * Wait until a condition is true.
|
---|
343 | *
|
---|
344 | * This macro blocks the protothread until the specified condition is
|
---|
345 | * true. The macro PSOCK_NEWDATA() can be used to check if new data
|
---|
346 | * arrives when the protosocket is waiting.
|
---|
347 | *
|
---|
348 | * Typically, this macro is used as follows:
|
---|
349 | *
|
---|
350 | \code
|
---|
351 | PT_THREAD(thread(struct psock *s, struct uip_timer *t))
|
---|
352 | {
|
---|
353 | PSOCK_BEGIN(s);
|
---|
354 |
|
---|
355 | PSOCK_WAIT_UNTIL(s, PSOCK_NEWDATA(s) || timer_expired(t));
|
---|
356 |
|
---|
357 | if(PSOCK_NEWDATA(s)) {
|
---|
358 | PSOCK_READTO(s, '\n');
|
---|
359 | } else {
|
---|
360 | handle_timed_out(s);
|
---|
361 | }
|
---|
362 |
|
---|
363 | PSOCK_END(s);
|
---|
364 | }
|
---|
365 | \endcode
|
---|
366 | *
|
---|
367 | * \param psock (struct psock *) A pointer to the protosocket.
|
---|
368 | * \param condition The condition to wait for.
|
---|
369 | *
|
---|
370 | * \hideinitializer
|
---|
371 | */
|
---|
372 | #define PSOCK_WAIT_UNTIL(psock, condition) \
|
---|
373 | PT_WAIT_UNTIL(&((psock)->pt), (condition));
|
---|
374 |
|
---|
375 | #define PSOCK_WAIT_THREAD(psock, condition) \
|
---|
376 | PT_WAIT_THREAD(&((psock)->pt), (condition))
|
---|
377 |
|
---|
378 | #endif /* __PSOCK_H__ */
|
---|
379 |
|
---|
380 | /** @} */
|
---|
381 | /** @} */
|
---|