32 #include "websocket-http-client.h" 36 #include "ipv6/ip64-addr.h" 43 #define LOG_MODULE "Websocket" 44 #define LOG_LEVEL LOG_LEVEL_IPV6 47 STATE_WAITING_FOR_HEADER,
48 STATE_WAITING_FOR_CONNECTED,
53 send_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));
87 send_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");
106 event(
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) {
130 parse_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);
195 input(
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);
222 websocket_http_client_register(
struct websocket_http_client_state *s,
226 const char *subprotocol,
232 strncpy(s->host, host,
sizeof(s->host));
237 strncpy(s->file, file,
sizeof(s->file));
239 if(subprotocol == NULL) {
242 strncpy(s->subprotocol, subprotocol,
sizeof(s->subprotocol));
245 strncpy(s->header,
"",
sizeof(s->header));
247 strncpy(s->header, header,
sizeof(s->header));
259 websocket_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);
301 websocket_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);
312 websocket_http_client_sendbuflen(
struct websocket_http_client_state *s)
314 return tcp_socket_max_sendlen(&s->s);
318 websocket_http_client_close(
struct websocket_http_client_state *s)
320 tcp_socket_close(&s->s);
324 websocket_http_client_hostname(
struct websocket_http_client_state *s)
330 websocket_http_client_init(
struct websocket_http_client_state *s)
337 websocket_http_client_set_proxy(
struct websocket_http_client_state *s,
338 const uip_ipaddr_t *addr, uint16_t port)
341 s->proxy_port = port;
345 websocket_http_client_queuelen(
struct websocket_http_client_state *s)
347 return tcp_socket_queuelen(&s->s);
Hostname is fresh and usable.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
uIP DNS resolver code header file.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Representation of an IP address.
Header file for the IP address manipulation library.
#define PT_END(pt)
Declare the end of a protothread.
resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
Look up a hostname in the array of known hostnames.
#define PT_YIELD(pt)
Yield from the current protothread.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define uip_create_unspecified(a)
set IP address a to unspecified
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.