32#include "websocket-http-client.h"
36#include "ipv6/ip64-addr.h"
43#define LOG_MODULE "Websocket"
44#define LOG_LEVEL LOG_LEVEL_NONE
47 STATE_WAITING_FOR_HEADER,
48 STATE_WAITING_FOR_CONNECTED,
53send_get(
struct websocket_http_client_state *s)
55 struct tcp_socket *tcps;
58 tcp_socket_send_str(tcps,
"GET ");
59 tcp_socket_send_str(tcps, s->file);
60 tcp_socket_send_str(tcps,
" HTTP/1.1\r\n");
61 tcp_socket_send_str(tcps,
"Host: ");
62 tcp_socket_send_str(tcps, s->host);
63 tcp_socket_send_str(tcps,
"\r\n");
64 if(strlen(s->header) > 0) {
65 tcp_socket_send_str(tcps, s->header);
74 tcp_socket_send_str(tcps,
75 "Connection: Upgrade\r\n"
76 "Upgrade: websocket\r\n"
77 "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
78 "Sec-WebSocket-Version: 13\r\n"
79 "Sec-WebSocket-Protocol:");
80 tcp_socket_send_str(tcps, s->subprotocol);
81 tcp_socket_send_str(tcps,
"\r\n");
82 tcp_socket_send_str(tcps,
"\r\n");
83 LOG_INFO(
"send_get(): output buffer left %d\n", tcp_socket_max_sendlen(tcps));
87send_connect(
struct websocket_http_client_state *s)
89 struct tcp_socket *tcps;
93 tcp_socket_send_str(tcps,
"CONNECT ");
94 tcp_socket_send_str(tcps, s->host);
95 tcp_socket_send_str(tcps,
":");
96 sprintf(buf,
"%d", s->port);
97 tcp_socket_send_str(tcps, buf);
98 tcp_socket_send_str(tcps,
" HTTP/1.1\r\n");
99 tcp_socket_send_str(tcps,
"Host: ");
100 tcp_socket_send_str(tcps, s->host);
101 tcp_socket_send_str(tcps,
"\r\n");
102 tcp_socket_send_str(tcps,
"Proxy-Connection: Keep-Alive\r\n\r\n");
106event(
struct tcp_socket *tcps,
void *ptr,
107 tcp_socket_event_t e)
109 struct websocket_http_client_state *s = ptr;
111 if(e == TCP_SOCKET_CONNECTED) {
112 if(s->proxy_port != 0) {
117 }
else if(e == TCP_SOCKET_CLOSED) {
118 websocket_http_client_closed(s);
119 }
else if(e == TCP_SOCKET_TIMEDOUT) {
120 websocket_http_client_timedout(s);
121 }
else if(e == TCP_SOCKET_ABORTED) {
122 websocket_http_client_aborted(s);
123 }
else if(e == TCP_SOCKET_DATA_SENT) {
130parse_header_byte(
struct websocket_http_client_state *s,
133 static const char *endmarker =
"\r\n\r\n";
148 s->http_status = (b -
'0');
150 s->http_status = s->http_status * 10 + (b -
'0');
152 s->http_status = s->http_status * 10 + (b -
'0');
154 if((s->proxy_port != 0 && !(s->http_status == 200 || s->http_status == 101)) ||
155 (s->proxy_port == 0 && s->http_status != 101)) {
158 LOG_WARN(
"didn't get the 101 status code (got %d), closing connection\n",
160 websocket_http_client_close(s);
177 if(b == (uint8_t)endmarker[s->i]) {
182 }
while(s->i < strlen(endmarker));
184 if(s->proxy_port != 0 && s->state == STATE_WAITING_FOR_HEADER) {
186 s->state = STATE_WAITING_FOR_CONNECTED;
188 s->state = STATE_STEADY_STATE;
189 websocket_http_client_connected(s);
191 PT_END(&s->parse_header_pt);
195input(
struct tcp_socket *tcps,
void *ptr,
196 const uint8_t *inputptr,
int inputdatalen)
198 struct websocket_http_client_state *s = ptr;
200 if(s->state == STATE_WAITING_FOR_HEADER ||
201 s->state == STATE_WAITING_FOR_CONNECTED) {
203 for(i = 0; i < inputdatalen; i++) {
204 parse_header_byte(s, inputptr[i]);
205 if(s->state == STATE_STEADY_STATE) {
211 if(i < inputdatalen && s->state == STATE_STEADY_STATE) {
212 websocket_http_client_datahandler(s, &inputptr[i], inputdatalen - i);
215 websocket_http_client_datahandler(s, inputptr, inputdatalen);
222websocket_http_client_register(
struct websocket_http_client_state *s,
226 const char *subprotocol,
232 strncpy(s->host, host,
sizeof(s->host) - 1);
237 strncpy(s->file, file,
sizeof(s->file) - 1);
239 if(subprotocol == NULL) {
242 strncpy(s->subprotocol, subprotocol,
sizeof(s->subprotocol) - 1);
245 strncpy(s->header,
"",
sizeof(s->header) - 1);
247 strncpy(s->header, header,
sizeof(s->header) - 1);
259websocket_http_client_get(
struct websocket_http_client_state *s)
262 uip_ip6addr_t ip6addr;
266 LOG_INFO(
"Get: connecting to %s with file %s subprotocol %s header %s\n",
267 s->host, s->file, s->subprotocol, s->header);
270 s->state = STATE_WAITING_FOR_HEADER;
272 if(tcp_socket_register(&s->s, s,
273 s->inputbuf,
sizeof(s->inputbuf),
274 s->outputbuf,
sizeof(s->outputbuf),
280 if(s->proxy_port != 0) {
283 port = s->proxy_port;
284 }
else if(uiplib_ip6addrconv(s->host, &ip6addr) == 0) {
286 if(uiplib_ip4addrconv(s->host, &ip4addr) != 0) {
287 ip64_addr_4to6(&ip4addr, &ip6addr);
294 return tcp_socket_connect(&s->s,
addr, s->port);
297 return tcp_socket_connect(&s->s, &ip6addr, port);
301websocket_http_client_send(
struct websocket_http_client_state *s,
305 if(s->state == STATE_STEADY_STATE) {
306 return tcp_socket_send(&s->s, data, datalen);
312websocket_http_client_sendbuflen(
struct websocket_http_client_state *s)
314 return tcp_socket_max_sendlen(&s->s);
318websocket_http_client_close(
struct websocket_http_client_state *s)
320 tcp_socket_close(&s->s);
324websocket_http_client_hostname(
struct websocket_http_client_state *s)
330websocket_http_client_init(
struct websocket_http_client_state *s)
337websocket_http_client_set_proxy(
struct websocket_http_client_state *s,
338 const uip_ipaddr_t *
addr, uint16_t port)
341 s->proxy_port = port;
345websocket_http_client_queuelen(
struct websocket_http_client_state *s)
347 return tcp_socket_queuelen(&s->s);
#define PT_YIELD(pt)
Yield from the current protothread.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
#define PT_END(pt)
Declare the end of a protothread.
#define uip_create_unspecified(a)
set IP address a to unspecified
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
Look up a hostname in the array of known hostnames.
Header file for the logging system.
uIP DNS resolver code header file.
@ RESOLV_STATUS_CACHED
Hostname is fresh and usable.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for the IP address manipulation library.
Representation of an IP address.