blob: 9085d8413d42ae9e84dcff7e1fb51396e8f16343 [file] [log] [blame]
adamdunkelsa2f3c422004-09-12 20:24:53 +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: socket.c,v 1.8 2004/09/12 20:24:56 adamdunkels Exp $
34 */
35
adamdunkels039c3e02004-08-11 21:20:36 +000036#include "socket.h"
37
adamdunkelse0b45472004-08-20 21:17:41 +000038#define SOCKET_STATE_NONE 0
39#define SOCKET_STATE_ACKED 1
40#define SOCKET_STATE_READ 2
41#define SOCKET_STATE_BLOCKED_NEWDATA 3
42#define SOCKET_STATE_BLOCKED_CLOSE 4
43#define SOCKET_STATE_BLOCKED_SEND 5
44#define SOCKET_STATE_DATA_SENT 6
adamdunkelsc8e7c772004-08-14 21:57:36 +000045
adamdunkelse0b45472004-08-20 21:17:41 +000046/*---------------------------------------------------------------------------*/
47static char
adamdunkelse59ce4a2004-09-03 09:59:46 +000048send_data(register struct socket *s)
adamdunkelse0b45472004-08-20 21:17:41 +000049{
50 if(s->state != SOCKET_STATE_DATA_SENT || uip_rexmit()) {
51 if(s->sendlen > uip_mss()) {
52 uip_send(s->sendptr, uip_mss());
adamdunkels039c3e02004-08-11 21:20:36 +000053 } else {
adamdunkelse0b45472004-08-20 21:17:41 +000054 uip_send(s->sendptr, s->sendlen);
adamdunkels039c3e02004-08-11 21:20:36 +000055 }
adamdunkelse0b45472004-08-20 21:17:41 +000056 s->state = SOCKET_STATE_DATA_SENT;
57 return 1;
adamdunkels039c3e02004-08-11 21:20:36 +000058 }
adamdunkelse0b45472004-08-20 21:17:41 +000059 return 0;
adamdunkels039c3e02004-08-11 21:20:36 +000060}
61/*---------------------------------------------------------------------------*/
adamdunkelse0b45472004-08-20 21:17:41 +000062static char
adamdunkelse59ce4a2004-09-03 09:59:46 +000063data_sent(register struct socket *s)
adamdunkelse0b45472004-08-20 21:17:41 +000064{
65 if(s->state == SOCKET_STATE_DATA_SENT && uip_acked()) {
66 if(s->sendlen > uip_mss()) {
67 s->sendlen -= uip_mss();
68 s->sendptr += uip_mss();
69 } else {
70 s->sendptr += s->sendlen;
71 s->sendlen = 0;
72 }
73 s->state = SOCKET_STATE_ACKED;
74 return 1;
75 }
76 return 0;
77}
78/*---------------------------------------------------------------------------*/
adamdunkelse59ce4a2004-09-03 09:59:46 +000079PT_THREAD(socket_send(register struct socket *s, const char *buf, unsigned int len))
adamdunkelse0b45472004-08-20 21:17:41 +000080{
adamdunkelsbdafa392004-09-01 19:09:49 +000081 PT_BEGIN(&s->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +000082
83 if(len == 0) {
84 PT_EXIT(&s->socketpt);
85 }
86
87 s->sendptr = buf;
88 s->sendlen = len;
adamdunkelsbdafa392004-09-01 19:09:49 +000089
90 s->state = SOCKET_STATE_NONE;
adamdunkelse0b45472004-08-20 21:17:41 +000091
92 while(s->sendlen > 0) {
adamdunkelsbae0a302004-09-12 07:16:23 +000093 PT_WAIT_UNTIL(&s->socketpt, data_sent(s) & send_data(s));
adamdunkelse0b45472004-08-20 21:17:41 +000094 }
95
adamdunkelsbdafa392004-09-01 19:09:49 +000096 s->state = SOCKET_STATE_NONE;
97
98 PT_END(&s->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +000099}
100/*---------------------------------------------------------------------------*/
adamdunkelsbae0a302004-09-12 07:16:23 +0000101PT_THREAD(socket_generator_send(register struct socket *s,
102 unsigned short (*generate)(void *), void *arg))
103{
104 PT_BEGIN(&s->socketpt);
105
106 if(generate == NULL) {
107 PT_EXIT(&s->socketpt);
108 }
109
110 s->state = SOCKET_STATE_NONE;
111 s->sendlen = generate(arg);
112 s->sendptr = uip_appdata;
113 do {
114
115 if(uip_rexmit()) {
116 generate(arg);
117 }
118 PT_WAIT_UNTIL(&s->socketpt, data_sent(s) & send_data(s));
119 } while(s->sendlen > 0);
120
121 s->state = SOCKET_STATE_NONE;
122
123 PT_END(&s->socketpt);
124}
125/*---------------------------------------------------------------------------*/
adamdunkelsbdafa392004-09-01 19:09:49 +0000126char
127socket_newdata(struct socket *s)
adamdunkels039c3e02004-08-11 21:20:36 +0000128{
adamdunkelsbdafa392004-09-01 19:09:49 +0000129 if(s->readlen > 0) {
130 /* Data in uip_appdata buffer that has not yet been read. */
131 return 1;
132 } else if(s->state == SOCKET_STATE_READ) {
adamdunkelse0b45472004-08-20 21:17:41 +0000133 /* Data in uip_appdata buffer already consumed. */
134 s->state = SOCKET_STATE_BLOCKED_NEWDATA;
135 return 0;
136 } else if(uip_newdata()) {
137 /* There is new data that has not been consumed. */
138 return 1;
139 } else {
140 /* There is no new data. */
141 return 0;
adamdunkelsc8e7c772004-08-14 21:57:36 +0000142 }
adamdunkelsc8e7c772004-08-14 21:57:36 +0000143}
144/*---------------------------------------------------------------------------*/
adamdunkelse59ce4a2004-09-03 09:59:46 +0000145PT_THREAD(socket_readto(register struct socket *socket, unsigned char c))
adamdunkelsc8e7c772004-08-14 21:57:36 +0000146{
adamdunkelsbdafa392004-09-01 19:09:49 +0000147 PT_BEGIN(&socket->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +0000148
adamdunkelsc8e7c772004-08-14 21:57:36 +0000149 uipbuf_setup(&socket->buf, socket->bufptr, socket->bufsize);
150
adamdunkelse0b45472004-08-20 21:17:41 +0000151 /* XXX: Should add uipbuf_checkmarker() before do{} loop, if
152 incoming data has been handled while waiting for a write. */
153
adamdunkelsc8e7c772004-08-14 21:57:36 +0000154 do {
155 if(socket->readlen == 0) {
adamdunkelsbdafa392004-09-01 19:09:49 +0000156 PT_WAIT_UNTIL(&socket->socketpt, socket_newdata(socket));
adamdunkelsc8e7c772004-08-14 21:57:36 +0000157 socket->state = SOCKET_STATE_READ;
158 socket->readptr = (u8_t *)uip_appdata;
159 socket->readlen = uip_datalen();
160 }
161 } while((uipbuf_bufto(&socket->buf, c,
162 &socket->readptr,
adamdunkelsc9c2dab2004-09-09 21:19:46 +0000163 &socket->readlen) & UIPBUF_FOUND) == 0);
adamdunkelsc8e7c772004-08-14 21:57:36 +0000164
adamdunkelse0b45472004-08-20 21:17:41 +0000165 if(uipbuf_len(&socket->buf) == 0) {
166 socket->state = SOCKET_STATE_NONE;
167 PT_RESTART(&socket->socketpt);
adamdunkelsbae0a302004-09-12 07:16:23 +0000168 }
adamdunkelsbdafa392004-09-01 19:09:49 +0000169 PT_END(&socket->socketpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000170}
171/*---------------------------------------------------------------------------*/
172void
adamdunkelse59ce4a2004-09-03 09:59:46 +0000173socket_init(register struct socket *socket, char *buffer, unsigned int buffersize)
adamdunkels039c3e02004-08-11 21:20:36 +0000174{
175 socket->state = SOCKET_STATE_NONE;
176 socket->readlen = 0;
177 socket->bufptr = buffer;
178 socket->bufsize = buffersize;
179 uipbuf_setup(&socket->buf, buffer, buffersize);
180 PT_INIT(&socket->pt);
adamdunkelsc8e7c772004-08-14 21:57:36 +0000181 PT_INIT(&socket->socketpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000182}
183/*---------------------------------------------------------------------------*/