37 #include "contiki-net.h"
40 #include "webclient.h"
42 #define WEBCLIENT_TIMEOUT 100
44 #define WEBCLIENT_STATE_STATUSLINE 0
45 #define WEBCLIENT_STATE_HEADERS 1
46 #define WEBCLIENT_STATE_DATA 2
47 #define WEBCLIENT_STATE_CLOSE 3
49 #define HTTPFLAG_NONE 0
51 #define HTTPFLAG_MOVED 2
52 #define HTTPFLAG_ERROR 3
57 #define ISO_space 0x20
59 struct webclient_state {
66 char file[WWW_CONF_MAX_URLLEN];
67 uint16_t getrequestptr;
68 uint16_t getrequestleft;
70 char httpheaderline[200];
71 uint16_t httpheaderlineptr;
76 static struct webclient_state s;
80 webclient_mimetype(
void)
86 webclient_filename(
void)
92 webclient_hostname(
void)
110 init_connection(
void)
112 s.state = WEBCLIENT_STATE_STATUSLINE;
114 s.getrequestleft =
sizeof(http_get) - 1 + 1 +
115 sizeof(http_10) - 1 +
116 sizeof(http_crnl) - 1 +
117 sizeof(http_host) - 1 +
118 sizeof(http_crnl) - 1 +
119 (uint16_t)strlen(http_user_agent_fields) +
120 (uint16_t)strlen(s.file) + (uint16_t)strlen(s.host);
123 s.httpheaderlineptr = 0;
127 webclient_close(
void)
129 s.state = WEBCLIENT_STATE_CLOSE;
133 webclient_get(
const char *host, uint16_t port,
const char *file)
137 uip_ipaddr_t *ipaddr;
158 strncpy(s.file, file,
sizeof(s.file));
159 strncpy(s.host, host,
sizeof(s.host));
170 static unsigned char *windowptr;
171 static int windowstart, windowend;
173 window_copy(
int curptr,
const char *data,
unsigned char datalen)
177 if(windowstart == windowend) {
178 return curptr + datalen;
181 if(curptr + datalen < windowstart) {
184 return curptr + datalen;
187 if(curptr > windowend) {
189 return curptr + datalen;
195 data += windowstart - curptr;
196 len -= windowstart - curptr;
199 if(len > windowend - windowstart) {
200 len = windowend - windowstart;
203 strncpy(windowptr + windowstart, data, len);
206 return curptr + datalen;
215 if(s.getrequestleft > 0) {
217 windowstart = s.getrequestptr;
219 windowend = windowstart +
uip_mss();
222 curptr = window_copy(curptr, http_get,
sizeof(http_get) - 1);
223 curptr = window_copy(curptr, s.file, (
unsigned char)strlen(s.file));
224 curptr = window_copy(curptr,
" ", 1);
225 curptr = window_copy(curptr, http_10,
sizeof(http_10) - 1);
227 curptr = window_copy(curptr, http_crnl,
sizeof(http_crnl) - 1);
229 curptr = window_copy(curptr, http_host,
sizeof(http_host) - 1);
230 curptr = window_copy(curptr, s.host, (
unsigned char)strlen(s.host));
231 curptr = window_copy(curptr, http_crnl,
sizeof(http_crnl) - 1);
233 curptr = window_copy(curptr, http_user_agent_fields,
234 (
unsigned char)strlen(http_user_agent_fields));
236 len = s.getrequestleft >
uip_mss()?
248 if(s.getrequestleft > 0) {
249 len = s.getrequestleft >
uip_mss()?
252 s.getrequestleft -=
len;
253 s.getrequestptr +=
len;
258 parse_statusline(uint16_t len)
262 while(len > 0 && s.httpheaderlineptr <
sizeof(s.httpheaderline)) {
263 s.httpheaderline[s.httpheaderlineptr] = *(
char *)
uip_appdata;
266 if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
268 if((strncmp(s.httpheaderline, http_10,
269 sizeof(http_10) - 1) == 0) ||
270 (strncmp(s.httpheaderline, http_11,
271 sizeof(http_11) - 1) == 0)) {
272 cptr = &(s.httpheaderline[9]);
273 s.httpflag = HTTPFLAG_NONE;
274 if(strncmp(cptr, http_200,
sizeof(http_200) - 1) == 0) {
276 s.httpflag = HTTPFLAG_OK;
277 }
else if(strncmp(cptr, http_301,
sizeof(http_301) - 1) == 0 ||
278 strncmp(cptr, http_302,
sizeof(http_302) - 1) == 0) {
281 s.httpflag = HTTPFLAG_MOVED;
283 s.httpheaderline[s.httpheaderlineptr - 1] = 0;
293 s.httpheaderlineptr = 0;
294 s.state = WEBCLIENT_STATE_HEADERS;
297 ++s.httpheaderlineptr;
304 casecmp(
char *str1,
const char *str2,
char len)
325 parse_headers(uint16_t len)
328 static unsigned char i;
330 while(len > 0 && s.httpheaderlineptr <
sizeof(s.httpheaderline)) {
331 s.httpheaderline[s.httpheaderlineptr] = *(
char *)
uip_appdata;
334 if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
337 if(s.httpheaderline[0] == ISO_cr) {
341 s.state = WEBCLIENT_STATE_DATA;
345 s.httpheaderline[s.httpheaderlineptr - 1] = 0;
347 if(casecmp(s.httpheaderline, http_content_type,
348 sizeof(http_content_type) - 1) == 0) {
350 cptr = strchr(s.httpheaderline,
';');
354 strncpy(s.mimetype, s.httpheaderline +
355 sizeof(http_content_type) - 1,
sizeof(s.mimetype));
356 }
else if(casecmp(s.httpheaderline, http_location,
357 sizeof(http_location) - 1) == 0) {
358 cptr = s.httpheaderline +
359 sizeof(http_location) - 1;
361 if(strncmp(cptr, http_http, 7) == 0) {
363 for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
375 strncpy(s.file, cptr,
sizeof(s.file));
382 s.httpheaderlineptr = 0;
384 ++s.httpheaderlineptr;
397 if(s.state == WEBCLIENT_STATE_STATUSLINE) {
398 len = parse_statusline(len);
401 if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
402 len = parse_headers(len);
405 if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
406 s.httpflag != HTTPFLAG_MOVED) {
412 webclient_appcall(
void *state)
418 s.state = WEBCLIENT_STATE_STATUSLINE;
420 webclient_connected();
426 webclient_timedout();
438 if(s.state == WEBCLIENT_STATE_CLOSE) {
467 if(s.timer == WEBCLIENT_TIMEOUT) {
468 webclient_timedout();
477 if(s.httpflag != HTTPFLAG_MOVED) {
479 webclient_datahandler(
NULL, 0);
488 resolv_query(s.host);
491 webclient_get(s.host, s.port, s.file);
Hostname is fresh and usable.
Representation of a uIP TCP connection.
CCIF struct uip_conn * tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Open a TCP connection to the specified IP address and port.
#define uip_aborted()
Has the connection been aborted by the other end?
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_newdata()
Is new incoming data available?
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
#define NULL
The null pointer.
uint16_t len
Length of the data that was previously sent.
#define uip_poll()
Is the connection being polled by uIP?
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
#define uip_acked()
Has previously sent data been acknowledged?
#define uip_connected()
Has the connection just been connected?
#define uip_abort()
Abort the current connection.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
#define uip_timedout()
Has the connection timed out?
#define uip_closed()
Has the connection been closed by the other end?
uip_appdata
Pointer to the application data in the packet buffer.
#define uip_rexmit()
Do we need to retransmit previously data?