blob: 4e5daaf6b406dcaf01cf3c5c332b2b8a9ff88e40 [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 *
adamdunkelsd0791bb2005-02-22 22:23:07 +000033 * $Id: psock.c,v 1.1 2005/02/22 22:23:07 adamdunkels Exp $
adamdunkelsa2f3c422004-09-12 20:24:53 +000034 */
35
adamdunkelsd0791bb2005-02-22 22:23:07 +000036#include "psock.h"
adamdunkels039c3e02004-08-11 21:20:36 +000037
adamdunkelsd0791bb2005-02-22 22:23:07 +000038#define PSOCK_STATE_NONE 0
39#define PSOCK_STATE_ACKED 1
40#define PSOCK_STATE_READ 2
41#define PSOCK_STATE_BLOCKED_NEWDATA 3
42#define PSOCK_STATE_BLOCKED_CLOSE 4
43#define PSOCK_STATE_BLOCKED_SEND 5
44#define PSOCK_STATE_DATA_SENT 6
adamdunkelsc8e7c772004-08-14 21:57:36 +000045
adamdunkelse0b45472004-08-20 21:17:41 +000046/*---------------------------------------------------------------------------*/
47static char
adamdunkelsd0791bb2005-02-22 22:23:07 +000048send_data(register struct psock *s)
adamdunkelse0b45472004-08-20 21:17:41 +000049{
adamdunkelsd0791bb2005-02-22 22:23:07 +000050 if(s->state != PSOCK_STATE_DATA_SENT || uip_rexmit()) {
adamdunkelse0b45472004-08-20 21:17:41 +000051 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 }
adamdunkelsd0791bb2005-02-22 22:23:07 +000056 s->state = PSOCK_STATE_DATA_SENT;
adamdunkelse0b45472004-08-20 21:17:41 +000057 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
adamdunkelsd0791bb2005-02-22 22:23:07 +000063data_sent(register struct psock *s)
adamdunkelse0b45472004-08-20 21:17:41 +000064{
adamdunkelsd0791bb2005-02-22 22:23:07 +000065 if(s->state == PSOCK_STATE_DATA_SENT && uip_acked()) {
adamdunkelse0b45472004-08-20 21:17:41 +000066 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 }
adamdunkelsd0791bb2005-02-22 22:23:07 +000073 s->state = PSOCK_STATE_ACKED;
adamdunkelse0b45472004-08-20 21:17:41 +000074 return 1;
75 }
76 return 0;
77}
78/*---------------------------------------------------------------------------*/
adamdunkelsd0791bb2005-02-22 22:23:07 +000079PT_THREAD(psock_send(register struct psock *s, const char *buf, unsigned int len))
adamdunkelse0b45472004-08-20 21:17:41 +000080{
adamdunkelsd0791bb2005-02-22 22:23:07 +000081 PT_BEGIN(&s->psockpt);
adamdunkelse0b45472004-08-20 21:17:41 +000082
83 if(len == 0) {
adamdunkelsd0791bb2005-02-22 22:23:07 +000084 PT_EXIT(&s->psockpt);
adamdunkelse0b45472004-08-20 21:17:41 +000085 }
86
87 s->sendptr = buf;
88 s->sendlen = len;
adamdunkelsbdafa392004-09-01 19:09:49 +000089
adamdunkelsd0791bb2005-02-22 22:23:07 +000090 s->state = PSOCK_STATE_NONE;
adamdunkelse0b45472004-08-20 21:17:41 +000091
92 while(s->sendlen > 0) {
adamdunkelsd0791bb2005-02-22 22:23:07 +000093 PT_WAIT_UNTIL(&s->psockpt, data_sent(s) & send_data(s));
adamdunkelse0b45472004-08-20 21:17:41 +000094 }
95
adamdunkelsd0791bb2005-02-22 22:23:07 +000096 s->state = PSOCK_STATE_NONE;
adamdunkelsbdafa392004-09-01 19:09:49 +000097
adamdunkelsd0791bb2005-02-22 22:23:07 +000098 PT_END(&s->psockpt);
adamdunkelse0b45472004-08-20 21:17:41 +000099}
100/*---------------------------------------------------------------------------*/
adamdunkelsd0791bb2005-02-22 22:23:07 +0000101PT_THREAD(psock_generator_send(register struct psock *s,
adamdunkelsbae0a302004-09-12 07:16:23 +0000102 unsigned short (*generate)(void *), void *arg))
103{
adamdunkelsd0791bb2005-02-22 22:23:07 +0000104 PT_BEGIN(&s->psockpt);
adamdunkelsbae0a302004-09-12 07:16:23 +0000105
106 if(generate == NULL) {
adamdunkelsd0791bb2005-02-22 22:23:07 +0000107 PT_EXIT(&s->psockpt);
adamdunkelsbae0a302004-09-12 07:16:23 +0000108 }
109
adamdunkelsd0791bb2005-02-22 22:23:07 +0000110 s->state = PSOCK_STATE_NONE;
adamdunkelsbae0a302004-09-12 07:16:23 +0000111 s->sendlen = generate(arg);
112 s->sendptr = uip_appdata;
113 do {
114
115 if(uip_rexmit()) {
116 generate(arg);
117 }
adamdunkelsd0791bb2005-02-22 22:23:07 +0000118 PT_WAIT_UNTIL(&s->psockpt, data_sent(s) & send_data(s));
adamdunkelsbae0a302004-09-12 07:16:23 +0000119 } while(s->sendlen > 0);
120
adamdunkelsd0791bb2005-02-22 22:23:07 +0000121 s->state = PSOCK_STATE_NONE;
adamdunkelsbae0a302004-09-12 07:16:23 +0000122
adamdunkelsd0791bb2005-02-22 22:23:07 +0000123 PT_END(&s->psockpt);
adamdunkelsbae0a302004-09-12 07:16:23 +0000124}
125/*---------------------------------------------------------------------------*/
adamdunkelsbdafa392004-09-01 19:09:49 +0000126char
adamdunkelsd0791bb2005-02-22 22:23:07 +0000127psock_newdata(struct psock *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;
adamdunkelsd0791bb2005-02-22 22:23:07 +0000132 } else if(s->state == PSOCK_STATE_READ) {
adamdunkelse0b45472004-08-20 21:17:41 +0000133 /* Data in uip_appdata buffer already consumed. */
adamdunkelsd0791bb2005-02-22 22:23:07 +0000134 s->state = PSOCK_STATE_BLOCKED_NEWDATA;
adamdunkelse0b45472004-08-20 21:17:41 +0000135 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/*---------------------------------------------------------------------------*/
adamdunkelsd0791bb2005-02-22 22:23:07 +0000145PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
adamdunkelsc8e7c772004-08-14 21:57:36 +0000146{
adamdunkelsd0791bb2005-02-22 22:23:07 +0000147 PT_BEGIN(&psock->psockpt);
adamdunkelse0b45472004-08-20 21:17:41 +0000148
adamdunkelsd0791bb2005-02-22 22:23:07 +0000149 uipbuf_setup(&psock->buf, psock->bufptr, psock->bufsize);
adamdunkelsc8e7c772004-08-14 21:57:36 +0000150
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 {
adamdunkelsd0791bb2005-02-22 22:23:07 +0000155 if(psock->readlen == 0) {
156 PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
157 psock->state = PSOCK_STATE_READ;
158 psock->readptr = (u8_t *)uip_appdata;
159 psock->readlen = uip_datalen();
adamdunkelsc8e7c772004-08-14 21:57:36 +0000160 }
adamdunkelsd0791bb2005-02-22 22:23:07 +0000161 } while((uipbuf_bufto(&psock->buf, c,
162 &psock->readptr,
163 &psock->readlen) & UIPBUF_FOUND) == 0);
adamdunkelsc8e7c772004-08-14 21:57:36 +0000164
adamdunkelsd0791bb2005-02-22 22:23:07 +0000165 if(uipbuf_len(&psock->buf) == 0) {
166 psock->state = PSOCK_STATE_NONE;
167 PT_RESTART(&psock->psockpt);
adamdunkelsbae0a302004-09-12 07:16:23 +0000168 }
adamdunkelsd0791bb2005-02-22 22:23:07 +0000169 PT_END(&psock->psockpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000170}
171/*---------------------------------------------------------------------------*/
172void
adamdunkelsd0791bb2005-02-22 22:23:07 +0000173psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
adamdunkels039c3e02004-08-11 21:20:36 +0000174{
adamdunkelsd0791bb2005-02-22 22:23:07 +0000175 psock->state = PSOCK_STATE_NONE;
176 psock->readlen = 0;
177 psock->bufptr = buffer;
178 psock->bufsize = buffersize;
179 uipbuf_setup(&psock->buf, buffer, buffersize);
180 PT_INIT(&psock->pt);
181 PT_INIT(&psock->psockpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000182}
183/*---------------------------------------------------------------------------*/