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)