blob: f4736e9d027017bb65b3660bcead8cb63d50840f [file] [log] [blame]
adamdunkels92622ca2003-07-30 23:10:49 +00001/*
2 * Copyright (c) 2002, Adam Dunkels.
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
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * 3. All advertising materials mentioning features or use of this
15 * software must display the following acknowledgement:
16 * This product includes software developed by Adam Dunkels.
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * This file is part of the Contiki desktop environment
34 *
35 * $Id: wget.c,v 1.1 2003/07/30 23:10:49 adamdunkels Exp $
36 *
37 */
38
39
40#include "ctk.h"
41#include "dispatcher.h"
42#include "webclient.h"
43#include "resolv.h"
44#include "petsciiconv.h"
45#include "uip_main.h"
46#include "loader.h"
47
48#include <c64.h>
49#include <cbm.h>
50#include <stdio.h>
51#include <string.h>
52#include <fcntl.h>
53
54
55static struct ctk_window window;
56
57static struct ctk_label hostlabel =
58 {CTK_LABEL(0, 1, 7, 1, "Server:")};
59static char hostedit[40];
60static char host[40];
61static struct ctk_textentry hosttextentry =
62 {CTK_TEXTENTRY(8, 1, 26, 1, hostedit, 38)};
63
64static struct ctk_label filelabel =
65 {CTK_LABEL(0, 3, 5, 1, "File:")};
66static char fileedit[40];
67static char file[40];
68static struct ctk_textentry filetextentry =
69 {CTK_TEXTENTRY(8, 3, 26, 1, fileedit, 38)};
70
71static struct ctk_label savefilenamelabel =
72 {CTK_LABEL(0, 5, 14, 1, "Save filename:")};
73static char savefilename[40];
74static struct ctk_textentry savefilenametextentry =
75 {CTK_TEXTENTRY(15, 5, 19, 1, savefilename, 38)};
76
77static struct ctk_button filebutton =
78 {CTK_BUTTON(0, 7, 13, "Download file")};
79
80static struct ctk_button d64button =
81 {CTK_BUTTON(17, 7, 18, "Download D64 disk")};
82
83static struct ctk_label statustext =
84 {CTK_LABEL(0, 9, 36, 1, "")};
85static char statusmsg[40];
86
87static struct ctk_window d64dialog;
88static struct ctk_label overwritelabel =
89 {CTK_LABEL(0, 1, 36, 1, "This will overwrite the entire disk!")};
90static struct ctk_label makesurelabel1 =
91 {CTK_LABEL(7, 3, 22, 1, "Make sure you have the")};
92static struct ctk_label makesurelabel2 =
93 {CTK_LABEL(6, 4, 24, 1, "right disk in the drive!")};
94static struct ctk_button overwritebutton =
95 {CTK_BUTTON(2, 6, 14, "Overwrite disk")};
96static struct ctk_button cancelbutton =
97 {CTK_BUTTON(26, 6, 6, "Cancel")};
98
99static DISPATCHER_SIGHANDLER(wget_sighandler, s, data);
100static struct dispatcher_proc p =
101 {DISPATCHER_PROC("Web downloader", NULL, wget_sighandler, webclient_appcall)};
102static ek_id_t id;
103
104/* State */
105
106#define DLOAD_NONE 0
107#define DLOAD_FILE 1
108#define DLOAD_D64 2
109static u8_t dload_state;
110static unsigned long dload_bytes;
111
112
113
114struct drv_state {
115 u8_t track;
116 u8_t sect;
117};
118
119static struct drv_state ds;
120
121static char buffer[256];
122static u16_t bufferptr;
123
124/*-----------------------------------------------------------------------------------*/
125/* wget_init();
126 *
127 * Initializes and starts the web browser. Called either at startup or
128 * to open the browser window.
129 */
130LOADER_INIT_FUNC(wget_init)
131{
132 if(id == EK_ID_NONE) {
133 id = dispatcher_start(&p);
134
135 /* Create the main window. */
136 ctk_window_new(&window, 36, 10, "Web downloader");
137
138 CTK_WIDGET_ADD(&window, &hostlabel);
139 CTK_WIDGET_ADD(&window, &hosttextentry);
140
141 CTK_WIDGET_ADD(&window, &filelabel);
142 CTK_WIDGET_ADD(&window, &filetextentry);
143
144 CTK_WIDGET_ADD(&window, &savefilenamelabel);
145 CTK_WIDGET_ADD(&window, &savefilenametextentry);
146
147 CTK_WIDGET_ADD(&window, &filebutton);
148
149 CTK_WIDGET_ADD(&window, &d64button);
150
151 CTK_WIDGET_ADD(&window, &statustext);
152
153 memset(hostedit, 0, sizeof(hostedit));
154 memset(fileedit, 0, sizeof(fileedit));
155 memset(savefilename, 0, sizeof(savefilename));
156
157 ctk_dialog_new(&d64dialog, 36, 8);
158 CTK_WIDGET_ADD(&d64dialog, &overwritelabel);
159 CTK_WIDGET_ADD(&d64dialog, &makesurelabel1);
160 CTK_WIDGET_ADD(&d64dialog, &makesurelabel2);
161 CTK_WIDGET_ADD(&d64dialog, &overwritebutton);
162 CTK_WIDGET_ADD(&d64dialog, &cancelbutton);
163
164
165 /* Attach as a listener to a number of signals ("Button activate",
166 "Hyperlink activate" and "Hyperlink hover", and the resolver's
167 signal. */
168 dispatcher_listen(ctk_signal_window_close);
169 dispatcher_listen(ctk_signal_button_activate);
170 dispatcher_listen(resolv_signal_found);
171 }
172 ctk_window_open(&window);
173}
174/*-----------------------------------------------------------------------------------*/
175static void
176show_statustext(char *text)
177{
178 ctk_label_set_text(&statustext, text);
179 CTK_WIDGET_REDRAW(&statustext);
180}
181/*-----------------------------------------------------------------------------------*/
182/* open_url():
183 *
184 * Called when the URL present in the global "url" variable should be
185 * opened. It will call the hostname resolver as well as the HTTP
186 * client requester.
187 */
188static void
189start_get(void)
190{
191 u16_t addr[2];
192
193 /* First check if the host is an IP address. */
194 if(uip_main_ipaddrconv(host, (unsigned char *)addr) == 0) {
195
196 /* Try to lookup the hostname. If it fails, we initiate a hostname
197 lookup and print out an informative message on the statusbar. */
198 if(resolv_lookup(host) == NULL) {
199 resolv_query(host);
200 show_statustext("Resolving host...");
201 return;
202 }
203 }
204
205 /* The hostname we present in the hostname table, so we send out the
206 initial GET request. */
207 if(webclient_get(host, 80, file) == 0) {
208 show_statustext("Out of memory error.");
209 } else {
210 show_statustext("Connecting...");
211 }
212}
213/*-----------------------------------------------------------------------------------*/
214static
215DISPATCHER_SIGHANDLER(wget_sighandler, s, data)
216{
217 int ret;
218 static unsigned char i;
219 DISPATCHER_SIGHANDLER_ARGS(s, data);
220
221 if(s == ctk_signal_button_activate) {
222 if(data == (void *)&filebutton) {
223 ret = cbm_open(2, 8, 2, savefilename);
224 if(ret == -1) {
225 sprintf(statusmsg, "Open error with '%s'", savefilename);
226 show_statustext(statusmsg);
227 } else {
228 strncpy(host, hostedit, sizeof(host));
229 strncpy(file, fileedit, sizeof(file));
230 petsciiconv_toascii(host, sizeof(host));
231 petsciiconv_toascii(file, sizeof(file));
232 start_get();
233 dload_bytes = 0;
234 dload_state = DLOAD_FILE;
235 }
236 } else if(data == (void *)&d64button) {
237 ctk_dialog_open(&d64dialog);
238 } else if(data == (void *)&cancelbutton) {
239 ctk_dialog_close();
240 } else if(data == (void *)&overwritebutton) {
241 ctk_dialog_close();
242 strncpy(host, hostedit, sizeof(host));
243 strncpy(file, fileedit, sizeof(file));
244 petsciiconv_toascii(host, sizeof(host));
245 petsciiconv_toascii(file, sizeof(file));
246 start_get();
247 dload_bytes = 0;
248 dload_state = DLOAD_D64;
249 ds.track = 1;
250 ds.sect = 0;
251 bufferptr = 0;
252 }
253 } else if(s == resolv_signal_found) {
254 /* Either found a hostname, or not. */
255 if((char *)data != NULL &&
256 resolv_lookup((char *)data) != NULL) {
257 start_get();
258 } else {
259 show_statustext("Host not found.");
260 }
261 } else if(s == ctk_signal_window_close) {
262 dispatcher_exit(&p);
263 id = EK_ID_NONE;
264 LOADER_UNLOAD();
265 }
266}
267/*-----------------------------------------------------------------------------------*/
268/* webclient_aborted():
269 *
270 * Callback function. Called from the webclient when the HTTP
271 * connection was abruptly aborted.
272 */
273void
274webclient_aborted(void)
275{
276 show_statustext("Connection reset by peer");
277}
278/*-----------------------------------------------------------------------------------*/
279/* webclient_timedout():
280 *
281 * Callback function. Called from the webclient when the HTTP
282 * connection timed out.
283 */
284void
285webclient_timedout(void)
286{
287 show_statustext("Connection timed out");
288 if(dload_state == DLOAD_FILE) {
289 cbm_close(2);
290 }
291
292}
293/*-----------------------------------------------------------------------------------*/
294/* webclient_closed():
295 *
296 * Callback function. Called from the webclient when the HTTP
297 * connection was closed after a request from the "webclient_close()"
298 * function. .
299 */
300void
301webclient_closed(void)
302{
303 show_statustext("Done.");
304}
305/*-----------------------------------------------------------------------------------*/
306/* webclient_closed():
307 *
308 * Callback function. Called from the webclient when the HTTP
309 * connection is connected.
310 */
311void
312webclient_connected(void)
313{
314 show_statustext("Request sent...");
315}
316/*-----------------------------------------------------------------------------------*/
317static void
318x_open(u8_t f, u8_t d, u8_t cmd, u8_t *fname)
319{
320 u8_t ret;
321
322 ret = cbm_open(f, d, cmd, fname);
323 if(ret != 0) {
324 /* printf("open: error %d\n", ret);*/
325 /* ctk_label_set_text(&statuslabel, "Open err");
326 CTK_WIDGET_REDRAW(&statuslabel);*/
327 show_statustext("Open error");
328 }
329
330}
331
332#if 0
333static u8_t cmd[32];
334static void
335read_sector(u8_t device, u8_t track, u8_t sect, void *mem)
336{
337 int ret;
338
339 x_open(15, device, 15, NULL);
340 x_open(2, device, 2, "#");
341
342 /* sprintf(cmd, "u1: 2 0%3d%3d", track, sect); */
343 strcpy(cmd, "u1: 2 0");
344 cmd[8] = ' ';
345 cmd[9] = '0' + track / 10;
346 cmd[10] = '0' + track % 10;
347 cmd[11] = ' ';
348 cmd[12] = '0' + sect / 10;
349 cmd[13] = '0' + sect % 10;
350 cmd[14] = 0;
351 cbm_write(15, cmd, strlen(cmd));
352 /* printf("%s\n", cmd);*/
353
354 ret = cbm_read(2, mem, 256);
355 if(ret == -1) {
356 ctk_label_set_text(&statuslabel, "Read err");
357 CTK_WIDGET_REDRAW(&statuslabel);
358 }
359 /* printf("read: read %d bytes\n", ret);*/
360
361 cbm_close(2);
362 cbm_close(15);
363
364}
365#endif /* 0 */
366
367static void
368write_sector(u8_t device, u8_t track, u8_t sect, void *mem)
369{
370 u16_t ret;
371 u8_t cmd[32];
372
373 x_open(15, device, 15, NULL);
374 x_open(2, device, 2, "#");
375
376 sprintf(cmd, "u2: 2 0%3d%3d", track, sect);
377 cbm_write(15, cmd, strlen(cmd));
378 printf("%s\n", cmd);
379
380 ret = cbm_write(2, mem, 256);
381 /* ret = 0;*/
382 if(ret == -1) {
383 sprintf(statusmsg, "Write error at %d:%d", track, sect);
384 show_statustext(statusmsg);
385 } else {
386 sprintf(statusmsg, "Wrote %d:%d", track, sect);
387 show_statustext(statusmsg);
388 }
389 /* printf("write: wrote %d bytes\n", ret);*/
390
391 cbm_close(2);
392 cbm_close(15);
393}
394
395static u8_t
396next_sector(void)
397{
398 ++ds.sect;
399 if(ds.track < 18) {
400 if(ds.sect == 21) {
401 ++ds.track;
402 ds.sect = 0;
403 }
404 } else if(ds.track < 25) {
405 if(ds.sect == 19) {
406 ++ds.track;
407 ds.sect = 0;
408 }
409 } else if(ds.track < 31) {
410 if(ds.sect == 18) {
411 ++ds.track;
412 ds.sect = 0;
413 }
414 } else if(ds.track < 36) {
415 if(ds.sect == 17) {
416 ++ds.track;
417 ds.sect = 0;
418 }
419 }
420
421 if(ds.track == 36) {
422 return 1;
423 }
424 return 0;
425}
426/*-----------------------------------------------------------------------------------*/
427static void
428write_buffer(void)
429{
430 write_sector(8, ds.track, ds.sect, buffer);
431 if(next_sector() != 0) {
432 dload_state = DLOAD_NONE;
433 }
434}
435static void
436handle_d64_data(char *data, u16_t len)
437{
438 u16_t bufferlen;
439
440 while(dload_state == DLOAD_D64 &&
441 len > 0) {
442 bufferlen = sizeof(buffer) - bufferptr;
443 if(len < bufferlen) {
444 bufferlen = len;
445 }
446
447 memcpy(&buffer[bufferptr], data, bufferlen);
448
449 data += bufferlen;
450 bufferptr += bufferlen;
451 len -= bufferlen;
452
453 if(bufferptr == sizeof(buffer)) {
454 write_buffer();
455 bufferptr = 0;
456 }
457 }
458}
459/*-----------------------------------------------------------------------------------*/
460/* webclient_datahandler():
461 *
462 * Callback function. Called from the webclient module when HTTP data
463 * has arrived.
464 */
465void
466webclient_datahandler(char *data, u16_t len)
467{
468 int ret;
469
470 if(len > 0) {
471 dload_bytes += len;
472 sprintf(statusmsg, "Downloading (%lu bytes)", dload_bytes);
473 show_statustext(statusmsg);
474 if(dload_state == DLOAD_D64) {
475 handle_d64_data(data, len);
476 } else if(dload_state == DLOAD_FILE) {
477 ret = cbm_write(2, data, len);
478 if(ret != len) {
479 sprintf(statusmsg, "Wrote only %d bytes", ret);
480 show_statustext(statusmsg);
481 }
482 }
483 }
484
485 if(data == NULL) {
486 if(dload_state == DLOAD_FILE) {
487 cbm_close(2);
488 }
489 dload_state = DLOAD_NONE;
490 sprintf(statusmsg, "Finished downloading %lu bytes", dload_bytes);
491 show_statustext(statusmsg);
492 }
493}
494/*-----------------------------------------------------------------------------------*/