Bugfix: the web client previously implicitly depended on uip_buf to be larger than an HTTP GET request. This made the web client fail when uip_buf was smaller, and lead to memory corruption. Also, there was a bug when HTTP request headers would arrive when the GET request was being sent out.
This commit is contained in:
parent
6b34b4f092
commit
8526049749
|
@ -1,19 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, Adam Dunkels.
|
* Copyright (c) 2002, Adam Dunkels.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
* 2. Redistributions in binary form must reproduce the above
|
||||||
* copyright notice, this list of conditions and the following
|
* copyright notice, this list of conditions and the following
|
||||||
* disclaimer in the documentation and/or other materials provided
|
* disclaimer in the documentation and/or other materials provided
|
||||||
* with the distribution.
|
* with the distribution.
|
||||||
* 3. The name of the author may not be used to endorse or promote
|
* 3. The name of the author may not be used to endorse or promote
|
||||||
* products derived from this software without specific prior
|
* products derived from this software without specific prior
|
||||||
* written permission.
|
* written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
@ -25,11 +25,11 @@
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* This file is part of the "contiki" web browser.
|
* This file is part of the "contiki" web browser.
|
||||||
*
|
*
|
||||||
* $Id: webclient.c,v 1.5 2007/11/30 21:53:50 oliverschmidt Exp $
|
* $Id: webclient.c,v 1.6 2008/11/09 12:39:31 adamdunkels Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ struct webclient_state {
|
||||||
|
|
||||||
u16_t port;
|
u16_t port;
|
||||||
char host[40];
|
char host[40];
|
||||||
char file[WWW_CONF_MAX_URLLEN];
|
char file[WWW_CONF_MAX_URLLEN];
|
||||||
u16_t getrequestptr;
|
u16_t getrequestptr;
|
||||||
u16_t getrequestleft;
|
u16_t getrequestleft;
|
||||||
|
|
||||||
|
@ -134,12 +134,12 @@ unsigned char
|
||||||
webclient_get(char *host, u16_t port, char *file)
|
webclient_get(char *host, u16_t port, char *file)
|
||||||
{
|
{
|
||||||
struct uip_conn *conn;
|
struct uip_conn *conn;
|
||||||
u16_t *ipaddr;
|
u16_t *ipaddr;
|
||||||
static u16_t addr[2];
|
static u16_t addr[2];
|
||||||
|
|
||||||
/* First check if the host is an IP address. */
|
/* First check if the host is an IP address. */
|
||||||
ipaddr = &addr[0];
|
ipaddr = &addr[0];
|
||||||
if(uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
|
if(uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
|
||||||
ipaddr = resolv_lookup(host);
|
ipaddr = resolv_lookup(host);
|
||||||
|
|
||||||
if(ipaddr == NULL) {
|
if(ipaddr == NULL) {
|
||||||
|
@ -161,42 +161,87 @@ webclient_get(char *host, u16_t port, char *file)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
static char * CC_FASTCALL
|
/* Copy data into a "window", specified by the windowstart and
|
||||||
copy_string(char *dest, const char *src, unsigned char len)
|
windowend variables. Only data that fits within the window is
|
||||||
|
copied. This function is used to copy data into the uIP buffer, which
|
||||||
|
typically is smaller than the data that is to be copied.
|
||||||
|
*/
|
||||||
|
static unsigned char *windowptr;
|
||||||
|
static int windowstart, windowend;
|
||||||
|
static int
|
||||||
|
window_copy(int curptr, const char *data, unsigned char datalen)
|
||||||
{
|
{
|
||||||
return strcpy(dest, src) + len;
|
int len;
|
||||||
|
|
||||||
|
if(windowstart == windowend) {
|
||||||
|
return curptr + datalen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(curptr + datalen < windowstart) {
|
||||||
|
/* If all the data is before the window, we do not copy the
|
||||||
|
data. */
|
||||||
|
return curptr + datalen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(curptr > windowend) {
|
||||||
|
/* If all the data is after the window, we do not copy the data. */
|
||||||
|
return curptr + datalen;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = datalen;
|
||||||
|
|
||||||
|
/* Trim off data before the window. */
|
||||||
|
data += windowstart - curptr;
|
||||||
|
len -= windowstart - curptr;
|
||||||
|
|
||||||
|
/* Trim off data after the window. */
|
||||||
|
if(len > windowend - windowstart) {
|
||||||
|
len = windowend - windowstart;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(windowptr + windowstart, data, len);
|
||||||
|
windowstart += len;
|
||||||
|
|
||||||
|
return curptr + datalen;
|
||||||
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
senddata(void)
|
senddata(void)
|
||||||
{
|
{
|
||||||
u16_t len;
|
u16_t len;
|
||||||
char *getrequest;
|
/* char *getrequest;*/
|
||||||
char *cptr;
|
char *cptr;
|
||||||
|
int curptr;
|
||||||
|
|
||||||
if(s.getrequestleft > 0) {
|
if(s.getrequestleft > 0) {
|
||||||
cptr = getrequest = (char *)uip_appdata;
|
|
||||||
|
|
||||||
cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
|
windowstart = s.getrequestptr;
|
||||||
cptr = copy_string(cptr, s.file, (unsigned char)strlen(s.file));
|
curptr = 0;
|
||||||
*cptr++ = ISO_space;
|
windowend = windowstart + uip_mss();
|
||||||
cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
|
windowptr = (char *)uip_appdata - windowstart;
|
||||||
|
|
||||||
cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
|
curptr = window_copy(curptr, http_get, sizeof(http_get) - 1);
|
||||||
|
curptr = window_copy(curptr, s.file, (unsigned char)strlen(s.file));
|
||||||
|
curptr = window_copy(curptr, " ", 1);
|
||||||
|
curptr = window_copy(curptr, http_10, sizeof(http_10) - 1);
|
||||||
|
|
||||||
|
curptr = window_copy(curptr, http_crnl, sizeof(http_crnl) - 1);
|
||||||
|
|
||||||
cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
|
curptr = window_copy(curptr, http_host, sizeof(http_host) - 1);
|
||||||
cptr = copy_string(cptr, s.host, (unsigned char)strlen(s.host));
|
curptr = window_copy(curptr, s.host, (unsigned char)strlen(s.host));
|
||||||
cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
|
curptr = window_copy(curptr, http_crnl, sizeof(http_crnl) - 1);
|
||||||
|
|
||||||
cptr = copy_string(cptr, http_user_agent_fields,
|
curptr = window_copy(curptr, http_user_agent_fields,
|
||||||
(unsigned char)strlen(http_user_agent_fields));
|
(unsigned char)strlen(http_user_agent_fields));
|
||||||
|
|
||||||
|
|
||||||
len = s.getrequestleft > uip_mss()?
|
len = s.getrequestleft > uip_mss()?
|
||||||
uip_mss():
|
uip_mss():
|
||||||
s.getrequestleft;
|
s.getrequestleft;
|
||||||
uip_send(&(getrequest[s.getrequestptr]), len);
|
uip_send(uip_appdata, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
acked(void)
|
acked(void)
|
||||||
|
@ -301,7 +346,7 @@ parse_headers(u16_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.httpheaderline[s.httpheaderlineptr - 1] = 0;
|
s.httpheaderline[s.httpheaderlineptr - 1] = 0;
|
||||||
/* Check for specific HTTP header fields. */
|
/* Check for specific HTTP header fields. */
|
||||||
if(casecmp(s.httpheaderline, http_content_type,
|
if(casecmp(s.httpheaderline, http_content_type,
|
||||||
sizeof(http_content_type) - 1) == 0) {
|
sizeof(http_content_type) - 1) == 0) {
|
||||||
/* Found Content-type field. */
|
/* Found Content-type field. */
|
||||||
|
@ -317,7 +362,7 @@ parse_headers(u16_t len)
|
||||||
sizeof(http_location) - 1;
|
sizeof(http_location) - 1;
|
||||||
|
|
||||||
if(strncmp(cptr, http_http, 7) == 0) {
|
if(strncmp(cptr, http_http, 7) == 0) {
|
||||||
cptr += 7;
|
cptr += 7;
|
||||||
for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
|
for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
|
||||||
if(*cptr == 0 ||
|
if(*cptr == 0 ||
|
||||||
*cptr == '/' ||
|
*cptr == '/' ||
|
||||||
|
@ -337,7 +382,7 @@ parse_headers(u16_t len)
|
||||||
|
|
||||||
/* We're done parsing, so we reset the pointer and start the
|
/* We're done parsing, so we reset the pointer and start the
|
||||||
next line. */
|
next line. */
|
||||||
s.httpheaderlineptr = 0;
|
s.httpheaderlineptr = 0;
|
||||||
} else {
|
} else {
|
||||||
++s.httpheaderlineptr;
|
++s.httpheaderlineptr;
|
||||||
}
|
}
|
||||||
|
@ -369,6 +414,8 @@ newdata(void)
|
||||||
void
|
void
|
||||||
webclient_appcall(void *state)
|
webclient_appcall(void *state)
|
||||||
{
|
{
|
||||||
|
char *dataptr;
|
||||||
|
|
||||||
if(uip_connected()) {
|
if(uip_connected()) {
|
||||||
s.timer = 0;
|
s.timer = 0;
|
||||||
s.state = WEBCLIENT_STATE_STATUSLINE;
|
s.state = WEBCLIENT_STATE_STATUSLINE;
|
||||||
|
@ -381,7 +428,11 @@ webclient_appcall(void *state)
|
||||||
if(uip_timedout()) {
|
if(uip_timedout()) {
|
||||||
webclient_timedout();
|
webclient_timedout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(uip_aborted()) {
|
||||||
|
webclient_aborted();
|
||||||
|
}
|
||||||
|
|
||||||
if(state == NULL) {
|
if(state == NULL) {
|
||||||
uip_abort();
|
uip_abort();
|
||||||
return;
|
return;
|
||||||
|
@ -391,12 +442,13 @@ webclient_appcall(void *state)
|
||||||
webclient_closed();
|
webclient_closed();
|
||||||
uip_abort();
|
uip_abort();
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if(uip_aborted()) {
|
|
||||||
webclient_aborted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The acked() and newdata() functions may alter the uip_appdata
|
||||||
|
ptr, so we need to store it in the "dataptr" variable so that we
|
||||||
|
can restore it before the senddata() function is called. */
|
||||||
|
dataptr = uip_appdata;
|
||||||
|
|
||||||
if(uip_acked()) {
|
if(uip_acked()) {
|
||||||
s.timer = 0;
|
s.timer = 0;
|
||||||
|
@ -406,6 +458,9 @@ webclient_appcall(void *state)
|
||||||
s.timer = 0;
|
s.timer = 0;
|
||||||
newdata();
|
newdata();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uip_appdata = dataptr;
|
||||||
|
|
||||||
if(uip_rexmit() ||
|
if(uip_rexmit() ||
|
||||||
uip_newdata() ||
|
uip_newdata() ||
|
||||||
uip_acked()) {
|
uip_acked()) {
|
||||||
|
|
Loading…
Reference in a new issue