Contiki 3.x
shell-wget.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Wget Contiki shell command
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "shell.h"
42 
43 #include "webclient.h"
44 
45 #include <stdio.h>
46 #include <string.h>
47 
48 #define MAX_URLLEN 128
49 static char url[MAX_URLLEN];
50 
51 static uint8_t running;
52 
53 /*---------------------------------------------------------------------------*/
54 PROCESS(shell_wget_process, "wget");
55 SHELL_COMMAND(wget_command,
56  "wget",
57  "wget [URL]: download a file with HTTP",
58  &shell_wget_process);
59 /*---------------------------------------------------------------------------*/
60 static void
61 open_url(char *url)
62 {
63  unsigned char i, c;
64  static char host[32];
65  char *file;
66  register char *urlptr;
67  static uip_ipaddr_t addr;
68 
69  /* Trim off any spaces in the end of the url. */
70  urlptr = url + strlen(url) - 1;
71  while(*urlptr == ' ' && urlptr > url) {
72  *urlptr = 0;
73  --urlptr;
74  }
75 
76  /* Don't even try to go further if the URL is empty. */
77  if(urlptr == url) {
78  return;
79  }
80 
81  /* See if the URL starts with http://, otherwise prepend it. */
82  if(strncmp(url, http_http, 7) != 0) {
83  while(urlptr >= url) {
84  *(urlptr + 7) = *urlptr;
85  --urlptr;
86  }
87  strncpy(url, http_http, 7);
88  }
89 
90  /* Find host part of the URL. */
91  urlptr = &url[7];
92  if(*urlptr == '[') {
93  /* IPv6 address */
94  c = ']';
95  ++urlptr;
96  } else {
97  c = ':';
98  }
99  for(i = 0; i < sizeof(host); ++i) {
100  if(*urlptr == 0 ||
101  *urlptr == '/' ||
102  *urlptr == ' ' ||
103  *urlptr == c) {
104  host[i] = 0;
105  break;
106  }
107  host[i] = *urlptr;
108  ++urlptr;
109  }
110  if(*urlptr == ']') {
111  /* Move past end of IPv6 host */
112  urlptr++;
113  }
114 
115  /* XXX: Here we should find the port part of the URL, but this isn't
116  currently done because of laziness from the programmer's side
117  :-) */
118 
119  /* Find file part of the URL. */
120  while(*urlptr != '/' && *urlptr != 0) {
121  ++urlptr;
122  }
123  if(*urlptr == '/') {
124  file = urlptr;
125  } else {
126  file = "/";
127  }
128 
129 #if UIP_UDP
130  /* Try to lookup the hostname. If it fails, we initiate a hostname
131  lookup and print out an informative message on the statusbar. */
132  if(uiplib_ipaddrconv(host, &addr) == 0) {
133  uip_ipaddr_t *addrptr;
134  shell_output_str(&wget_command, "Not an IP address", "");
135  if(resolv_lookup(host, &addrptr) == RESOLV_STATUS_UNCACHED) {
136  shell_output_str(&wget_command, "Not resolved", "");
137  resolv_query(host);
138  return;
139  }
140  uip_ipaddr_copy(&addr, addrptr);
141  }
142 #else /* UIP_UDP */
143  uiplib_ipaddrconv(host, &addr);
144 #endif /* UIP_UDP */
145 
146  /* The hostname we present in the hostname table, so we send out the
147  initial GET request. */
148  shell_output_str(&wget_command, "Host ", host);
149  shell_output_str(&wget_command, "File ", file);
150 
151  if(webclient_get(host, 80, file) == 0) {
152  shell_output_str(&wget_command, "Out of memory", "");
153  } else {
154  shell_output_str(&wget_command, "Connecting...", "");
155  }
156 }
157 /*---------------------------------------------------------------------------*/
158 PROCESS_THREAD(shell_wget_process, ev, data)
159 {
160  PROCESS_BEGIN();
161 
162  strncpy(url, data, sizeof(url));
163  open_url(url);
164 
165  running = 1;
166 
167  while(running) {
169 
170  if(ev == tcpip_event) {
171  webclient_appcall(data);
172 #if UIP_UDP
173  } else if(ev == resolv_event_found) {
174  /* Either found a hostname, or not. */
175  if((char *)data != NULL &&
176  resolv_lookup((char *)data, NULL) == RESOLV_STATUS_CACHED) {
177  open_url(url);
178  } else {
179  shell_output_str(&wget_command, "Host not found.", "");
180  }
181 #endif /* UIP_UDP */
182  }
183  }
184 
185  PROCESS_END();
186 }
187 /*---------------------------------------------------------------------------*/
188 void
189 shell_wget_init(void)
190 {
191  shell_register_command(&wget_command);
192 }
193 /*---------------------------------------------------------------------------*/
194 void
195 webclient_datahandler(char *data, uint16_t len)
196 {
197  if(len == 0) {
198  running = 0;
199  } else {
200  shell_output(&wget_command, data, len, NULL, 0);
201  }
202 }
203 /*---------------------------------------------------------------------------*/
204 void
205 webclient_connected(void)
206 {
207  shell_output_str(&wget_command, "connected", "");
208 }
209 /*---------------------------------------------------------------------------*/
210 void
211 webclient_timedout(void)
212 {
213  shell_output_str(&wget_command, "timedout", "");
214  running = 0;
215 }
216 /*---------------------------------------------------------------------------*/
217 void
218 webclient_aborted(void)
219 {
220  shell_output_str(&wget_command, "aborted", "");
221  running = 0;
222 }
223 /*---------------------------------------------------------------------------*/
224 void
225 webclient_closed(void)
226 {
227  shell_output_str(&wget_command, "closed", "");
228  running = 0;
229 }
230 /*---------------------------------------------------------------------------*/
Hostname was not found in the cache.
Definition: resolv.h:71
Hostname is fresh and usable.
Definition: resolv.h:68
void shell_output_str(struct shell_command *c, char *text1, const char *text2)
Output strings from a shell command.
Definition: shell.c:383
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
Main header file for the Contiki shell
#define NULL
The null pointer.
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
Definition: uiplib.h:71
void shell_output(struct shell_command *c, void *data1, int len1, const void *data2, int len2)
Output data from a shell command.
Definition: shell.c:395
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
CCIF process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1026
void shell_register_command(struct shell_command *c)
Register a command with the shell.
Definition: shell.c:413
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
process_event_t tcpip_event
The uIP event.
Definition: tcpip.c:75
#define SHELL_COMMAND(name, command, description, process)
Define a shell command.
Definition: shell.h:219