From f9e28e79b9bcfe222a8816b02acead1584458d96 Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Thu, 16 Apr 2020 18:13:04 +0200 Subject: [PATCH] Factored out W5100 HTTP client handling. In order to reduce code duplication for a planned W5100 HTTP client program beside wget65 the W5100 HTTP client code is now available for reuse. --- apps/Makefile | 2 +- apps/w5100_http.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++ apps/w5100_http.h | 48 ++++++++++++ apps/wget65.c | 150 +++---------------------------------- 4 files changed, 246 insertions(+), 139 deletions(-) create mode 100644 apps/w5100_http.c create mode 100644 apps/w5100_http.h diff --git a/apps/Makefile b/apps/Makefile index 0d03239..47f79a7 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -46,7 +46,7 @@ TCP =\ bin: wget65.bin -wget65.bin: w5100.c linenoise.c +wget65.bin: w5100.c w5100_http.c linenoise.c wget65.bin: IP65LIB = ../ip65/ip65.lib wget65.bin: A2_DRIVERLIB = ../drivers/ip65_apple2_uther2.lib diff --git a/apps/w5100_http.c b/apps/w5100_http.c new file mode 100644 index 0000000..b262c31 --- /dev/null +++ b/apps/w5100_http.c @@ -0,0 +1,185 @@ +/****************************************************************************** + +Copyright (c) 2020, Oliver Schmidt +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL OLIVER SCHMIDT BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#include +#include + +#include "../inc/ip65.h" +#include "w5100.h" +#include "w5100_http.h" + +// Both pragmas are obligatory to have cc65 generate code +// suitable to access the W5100 auto-increment registers. +#pragma optimize (on) +#pragma static-locals (on) + +bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector, + char* buffer, size_t length) +{ + printf("Connecting to %s:%d ", dotted_quad(addr), port); + + if (!w5100_connect(addr, port)) + { + printf("- Connect failed\n"); + return false; + } + + printf("- Ok\n\nSending request "); + { + uint16_t snd; + uint16_t pos = 0; + uint16_t len = strlen(selector); + + while (len) + { + if (input_check_for_abort_key()) + { + printf("- User abort\n"); + w5100_disconnect(); + return false; + } + + snd = w5100_send_request(); + if (!snd) + { + if (!w5100_connected()) + { + printf("- Connection lost\n"); + return false; + } + continue; + } + + if (len < snd) + { + snd = len; + } + + { + // One less to allow for faster pre-increment below + const char *dataptr = selector + pos - 1; + uint16_t i; + for (i = 0; i < snd; ++i) + { + // The variable is necessary to have cc65 generate code + // suitable to access the W5100 auto-increment register. + char data = *++dataptr; + *w5100_data = data; + } + } + + w5100_send_commit(snd); + len -= snd; + pos += snd; + } + } + + printf("- Ok\n\nReceiving response "); + { + uint16_t rcv; + bool body = false; + uint16_t len = 0; + + while (!body) + { + if (input_check_for_abort_key()) + { + printf("- User abort\n"); + w5100_disconnect(); + return false; + } + + rcv = w5100_receive_request(); + if (!rcv) + { + if (!w5100_connected()) + { + printf("- Connection lost\n"); + return false; + } + continue; + } + + if (rcv > length - len) + { + rcv = length - len; + } + + { + // One less to allow for faster pre-increment below + char *dataptr = buffer + len - 1; + uint16_t i; + for (i = 0; i < rcv; ++i) + { + // The variable is necessary to have cc65 generate code + // suitable to access the W5100 auto-increment register. + char data = *w5100_data; + *++dataptr = data; + + if (!memcmp(dataptr - 3, "\r\n\r\n", 4)) + { + rcv = i + 1; + body = true; + } + } + } + + w5100_receive_commit(rcv); + len += rcv; + + // No body found in full buffer + if (len == sizeof(buffer)) + { + printf("- Invalid response\n"); + w5100_disconnect(); + return false; + } + } + + // Replace "HTTP/1.1" with "HTTP/1.0" + buffer[7] = '0'; + + if (memcmp(buffer, "HTTP/1.0 200", 12)) + { + if (!memcmp(buffer, "HTTP/1.0", 8)) + { + char *eol = strchr(buffer,'\r'); + *eol = '\0'; + printf("- Status%s\n", buffer + 8); + } + else + { + printf("- Unknown response\n"); + } + w5100_disconnect(); + return false; + } + } + return true; +} diff --git a/apps/w5100_http.h b/apps/w5100_http.h new file mode 100644 index 0000000..85aafd9 --- /dev/null +++ b/apps/w5100_http.h @@ -0,0 +1,48 @@ +/****************************************************************************** + +Copyright (c) 2020, Oliver Schmidt +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL OLIVER SCHMIDT BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#ifndef _W5100_HTTP_H_ +#define _W5100_HTTP_H_ + +#ifndef __APPLE2ENH__ +#error W5100 auto-increment register access requires 65C02. +#endif + +#include +#include + +// Connect to server with IP address on TCP port , +// then HTTP GET and consume HTTP response header. Provide feedback +// on progress to the user via STDOUT. After returning from w5100_http_open() +// the connection is ready to consume the HTTP body. +// Return true if the connection is established, return false otherwise. +bool w5100_http_open(uint32_t addr, uint16_t port, const char* selector, + char* buffer, size_t length); + +#endif diff --git a/apps/wget65.c b/apps/wget65.c index b75e5c2..f513dfb 100644 --- a/apps/wget65.c +++ b/apps/wget65.c @@ -13,6 +13,7 @@ #include "../inc/ip65.h" #include "w5100.h" +#include "w5100_http.h" #include "linenoise.h" // Both pragmas are obligatory to have cc65 generate code @@ -24,13 +25,10 @@ char buffer[0x1000]; char name[16]; -void ip65_error_exit(bool quit) +void ip65_error_exit(void) { printf("- %s\n", ip65_strerror(ip65_error)); - if (quit) - { - exit(EXIT_FAILURE); - } + exit(EXIT_FAILURE); } void file_error_exit(void) @@ -241,15 +239,6 @@ void exit_on_key(void) } } -void exit_on_disconnect(void) -{ - if (!w5100_connected()) - { - printf("- Connection lost\n"); - exit(EXIT_FAILURE); - } -} - void write_file(const char *name) { uint16_t i; @@ -490,10 +479,10 @@ int main(int, char *argv[]) } } - printf("- %d\n\nInitializing ", eth_init); + printf("- %d\n\nInitializing %s ", eth_init, eth_name); if (ip65_init(eth_init)) { - ip65_error_exit(true); + ip65_error_exit(); } // Abort on Ctrl-C to be consistent with Linenoise @@ -502,7 +491,7 @@ int main(int, char *argv[]) printf("- Ok\n\nObtaining IP address "); if (dhcp_init()) { - ip65_error_exit(true); + ip65_error_exit(); } printf("- Ok\n\n"); @@ -520,9 +509,7 @@ int main(int, char *argv[]) break; } - // Do not actually exit - ip65_error_exit(false); - printf("\n"); + printf("- %s\n\n", ip65_strerror(ip65_error)); } save_argument("wget.urls"); printf("- Ok\n\n"); @@ -632,7 +619,8 @@ int main(int, char *argv[]) char oldcursor; char c; - printf("- Ok\n\nClobber %s? ", buffer); + printf("- Ok\n\n"); + cprintf("Clobber %s? ", buffer); oldcursor = cursor(true); c = cgetc(); @@ -668,124 +656,10 @@ int main(int, char *argv[]) } save_argument("wget.files"); - printf("\n\nConnecting to %s:%d ", dotted_quad(url_ip), url_port); - - if (!w5100_connect(url_ip, url_port)) + printf("\n\n"); + if (!w5100_http_open(url_ip, url_port, url_selector, buffer, sizeof(buffer))) { - printf("- Connect failed\n"); - exit(EXIT_FAILURE); - } - - printf("- Ok\n\nSending request "); - { - uint16_t snd; - uint16_t pos = 0; - uint16_t len = strlen(url_selector); - - while (len) - { - exit_on_key(); - - snd = w5100_send_request(); - if (!snd) - { - exit_on_disconnect(); - continue; - } - - if (len < snd) - { - snd = len; - } - - { - // One less to allow for faster pre-increment below - char *dataptr = url_selector + pos - 1; - for (i = 0; i < snd; ++i) - { - // The variable is necessary to have cc65 generate code - // suitable to access the W5100 auto-increment register. - char data = *++dataptr; - *w5100_data = data; - } - } - - w5100_send_commit(snd); - len -= snd; - pos += snd; - } - } - - printf("- Ok\n\nReceiving response "); - { - uint16_t rcv; - bool body = false; - uint16_t len = 0; - - while (!body) - { - exit_on_key(); - - rcv = w5100_receive_request(); - if (!rcv) - { - exit_on_disconnect(); - continue; - } - - if (rcv > sizeof(buffer) - len) - { - rcv = sizeof(buffer) - len; - } - - { - // One less to allow for faster pre-increment below - char *dataptr = buffer + len - 1; - for (i = 0; i < rcv; ++i) - { - // The variable is necessary to have cc65 generate code - // suitable to access the W5100 auto-increment register. - char data = *w5100_data; - *++dataptr = data; - - if (!memcmp(dataptr - 3, "\r\n\r\n", 4)) - { - rcv = i + 1; - body = true; - } - } - } - - w5100_receive_commit(rcv); - len += rcv; - - // No body found in full buffer - if (len == sizeof(buffer)) - { - printf("- Invalid response\n"); - w5100_disconnect(); - exit(EXIT_FAILURE); - } - } - - // Replace "HTTP/1.1" with "HTTP/1.0" - buffer[7] = '0'; - - if (!match("HTTP/1.0 200", buffer)) - { - if (match("HTTP/1.0", buffer)) - { - char *eol = strchr(buffer,'\r'); - *eol = '\0'; - printf("- Status%s\n", buffer + 8); - } - else - { - printf("- Unknown response\n"); - } - w5100_disconnect(); - exit(EXIT_FAILURE); - } + return EXIT_FAILURE; } if (device)