blob: 3d2adabfcc6067624fa76338490b5e65ea93d2cd [file] [log] [blame]
adamdunkels039c3e02004-08-11 21:20:36 +00001#include "socket.h"
2
adamdunkelse0b45472004-08-20 21:17:41 +00003#define SOCKET_STATE_NONE 0
4#define SOCKET_STATE_ACKED 1
5#define SOCKET_STATE_READ 2
6#define SOCKET_STATE_BLOCKED_NEWDATA 3
7#define SOCKET_STATE_BLOCKED_CLOSE 4
8#define SOCKET_STATE_BLOCKED_SEND 5
9#define SOCKET_STATE_DATA_SENT 6
adamdunkelsc8e7c772004-08-14 21:57:36 +000010
adamdunkelse0b45472004-08-20 21:17:41 +000011/*---------------------------------------------------------------------------*/
12static char
13send_data(struct socket *s)
14{
15 if(s->state != SOCKET_STATE_DATA_SENT || uip_rexmit()) {
16 if(s->sendlen > uip_mss()) {
17 uip_send(s->sendptr, uip_mss());
adamdunkels039c3e02004-08-11 21:20:36 +000018 } else {
adamdunkelse0b45472004-08-20 21:17:41 +000019 uip_send(s->sendptr, s->sendlen);
adamdunkels039c3e02004-08-11 21:20:36 +000020 }
adamdunkelse0b45472004-08-20 21:17:41 +000021 s->state = SOCKET_STATE_DATA_SENT;
22 return 1;
adamdunkels039c3e02004-08-11 21:20:36 +000023 }
adamdunkelse0b45472004-08-20 21:17:41 +000024 return 0;
adamdunkels039c3e02004-08-11 21:20:36 +000025}
26/*---------------------------------------------------------------------------*/
adamdunkelse0b45472004-08-20 21:17:41 +000027static char
28data_sent(struct socket *s)
29{
30 if(s->state == SOCKET_STATE_DATA_SENT && uip_acked()) {
31 if(s->sendlen > uip_mss()) {
32 s->sendlen -= uip_mss();
33 s->sendptr += uip_mss();
34 } else {
35 s->sendptr += s->sendlen;
36 s->sendlen = 0;
37 }
38 s->state = SOCKET_STATE_ACKED;
39 return 1;
40 }
41 return 0;
42}
43/*---------------------------------------------------------------------------*/
44PT_THREAD(socket_send(struct socket *s, char *buf, unsigned int len))
45{
adamdunkelsbdafa392004-09-01 19:09:49 +000046 PT_BEGIN(&s->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +000047
48 if(len == 0) {
49 PT_EXIT(&s->socketpt);
50 }
51
52 s->sendptr = buf;
53 s->sendlen = len;
adamdunkelsbdafa392004-09-01 19:09:49 +000054
55 s->state = SOCKET_STATE_NONE;
adamdunkelse0b45472004-08-20 21:17:41 +000056
57 while(s->sendlen > 0) {
adamdunkelsbdafa392004-09-01 19:09:49 +000058 PT_WAIT_UNTIL(&s->socketpt, data_sent(s) & send_data(s));
adamdunkelse0b45472004-08-20 21:17:41 +000059 }
60
adamdunkelsbdafa392004-09-01 19:09:49 +000061 s->state = SOCKET_STATE_NONE;
62
63 PT_END(&s->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +000064}
65/*---------------------------------------------------------------------------*/
adamdunkelsbdafa392004-09-01 19:09:49 +000066char
67socket_newdata(struct socket *s)
adamdunkels039c3e02004-08-11 21:20:36 +000068{
adamdunkelsbdafa392004-09-01 19:09:49 +000069 if(s->readlen > 0) {
70 /* Data in uip_appdata buffer that has not yet been read. */
71 return 1;
72 } else if(s->state == SOCKET_STATE_READ) {
adamdunkelse0b45472004-08-20 21:17:41 +000073 /* Data in uip_appdata buffer already consumed. */
74 s->state = SOCKET_STATE_BLOCKED_NEWDATA;
75 return 0;
76 } else if(uip_newdata()) {
77 /* There is new data that has not been consumed. */
78 return 1;
79 } else {
80 /* There is no new data. */
81 return 0;
adamdunkelsc8e7c772004-08-14 21:57:36 +000082 }
adamdunkelsc8e7c772004-08-14 21:57:36 +000083}
84/*---------------------------------------------------------------------------*/
85PT_THREAD(socket_readto(struct socket *socket, unsigned char c))
86{
adamdunkelsbdafa392004-09-01 19:09:49 +000087 PT_BEGIN(&socket->socketpt);
adamdunkelse0b45472004-08-20 21:17:41 +000088
adamdunkelsc8e7c772004-08-14 21:57:36 +000089 uipbuf_setup(&socket->buf, socket->bufptr, socket->bufsize);
90
adamdunkelse0b45472004-08-20 21:17:41 +000091 /* XXX: Should add uipbuf_checkmarker() before do{} loop, if
92 incoming data has been handled while waiting for a write. */
93
adamdunkelsc8e7c772004-08-14 21:57:36 +000094 do {
95 if(socket->readlen == 0) {
adamdunkelsbdafa392004-09-01 19:09:49 +000096 PT_WAIT_UNTIL(&socket->socketpt, socket_newdata(socket));
adamdunkelsc8e7c772004-08-14 21:57:36 +000097 socket->state = SOCKET_STATE_READ;
98 socket->readptr = (u8_t *)uip_appdata;
99 socket->readlen = uip_datalen();
100 }
101 } while((uipbuf_bufto(&socket->buf, c,
102 &socket->readptr,
103 &socket->readlen) & UIPBUF_FOUND) == 0 &&
104 socket->readlen > 0);
105
adamdunkelse0b45472004-08-20 21:17:41 +0000106 if(uipbuf_len(&socket->buf) == 0) {
107 socket->state = SOCKET_STATE_NONE;
108 PT_RESTART(&socket->socketpt);
109 }
adamdunkelsbdafa392004-09-01 19:09:49 +0000110
adamdunkelse0b45472004-08-20 21:17:41 +0000111
adamdunkelsbdafa392004-09-01 19:09:49 +0000112 PT_END(&socket->socketpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000113}
114/*---------------------------------------------------------------------------*/
115void
adamdunkelse0b45472004-08-20 21:17:41 +0000116socket_init(struct socket *socket, char *buffer, unsigned int buffersize)
adamdunkels039c3e02004-08-11 21:20:36 +0000117{
118 socket->state = SOCKET_STATE_NONE;
119 socket->readlen = 0;
120 socket->bufptr = buffer;
121 socket->bufsize = buffersize;
122 uipbuf_setup(&socket->buf, buffer, buffersize);
123 PT_INIT(&socket->pt);
adamdunkelsc8e7c772004-08-14 21:57:36 +0000124 PT_INIT(&socket->socketpt);
adamdunkels039c3e02004-08-11 21:20:36 +0000125}
126/*---------------------------------------------------------------------------*/