mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-08-27 02:29:07 +00:00
So far the base address of the Ethernet chip was a general property of all Ethernet drivers. It served two purposes: 1. Allowing to use a single Ethernet driver for a certain Ethernet chip, no matter what machine was connected to the chip. 2. Allowing use an Ethernet card in all Apple II slots. However, we now use customized Ethernet drivers for the individual machines so 1.) isn't relevant anymore. In fact one wants to omit the overhead of a runtime-adjustable base address where it isn't needed. So only the Apple II slots are left. But this should rather be a driver-internal approach then. We should just hand the driver the slot number the user wants to use and have the driver do its thing. Independently from the aspect if the driver parameter is a base address or a slot number the parameter handling was changed too. For asm programs there was so far a specific init function to be called prior to the main init function if it was desired to chnage the parameter default. This was done to keep the main init function backward compatible. But now that the parameter (now the slot number) is only used on the Apple II anyhow it seems reasonable to drop the specific init function again and just provide the parameter to the main init function. All C64-only user code can stay as-is. Only Apple II user code needs to by adjusted. Please note that this change only affects asm programs, C programs always used a single init function with the Apple II slot number as parameter.
400 lines
16 KiB
C
400 lines
16 KiB
C
#ifndef _IP65_H
|
|
#define _IP65_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
// Error codes
|
|
//
|
|
#define IP65_ERROR_PORT_IN_USE 0x80
|
|
#define IP65_ERROR_TIMEOUT_ON_RECEIVE 0x81
|
|
#define IP65_ERROR_TRANSMIT_FAILED 0x82
|
|
#define IP65_ERROR_TRANSMISSION_REJECTED_BY_PEER 0x83
|
|
#define IP65_ERROR_INPUT_TOO_LARGE 0x84
|
|
#define IP65_ERROR_DEVICE_FAILURE 0x85
|
|
#define IP65_ERROR_ABORTED_BY_USER 0x86
|
|
#define IP65_ERROR_LISTENER_NOT_AVAILABLE 0x87
|
|
#define IP65_ERROR_CONNECTION_RESET_BY_PEER 0x89
|
|
#define IP65_ERROR_CONNECTION_CLOSED 0x8A
|
|
#define IP65_ERROR_MALFORMED_URL 0xA0
|
|
#define IP65_ERROR_DNS_LOOKUP_FAILED 0xA1
|
|
|
|
// Last error code
|
|
//
|
|
extern uint8_t ip65_error;
|
|
|
|
// Ethernet driver initialization parameter values
|
|
//
|
|
#ifdef __APPLE2__
|
|
#define ETH_INIT_DEFAULT 3 // Apple II slot number
|
|
#else
|
|
#define ETH_INIT_DEFAULT 0 // Unused
|
|
#endif
|
|
|
|
// Initialize the IP stack
|
|
//
|
|
// This calls the individual protocol & driver initializations, so this is
|
|
// the only *_init routine that must be called by a user application,
|
|
// except for dhcp_init which must also be called if the application
|
|
// is using DHCP rather than hardcoded IP configuration.
|
|
//
|
|
// Inputs: eth_init: Ethernet driver initialization parameter
|
|
// Output: true if there was an error, false otherwise
|
|
//
|
|
bool __fastcall__ ip65_init(uint8_t eth_init);
|
|
|
|
// Access to Ethernet configuration
|
|
//
|
|
// Access to the two items below is only valid after ip65_init returned false.
|
|
//
|
|
extern uint8_t cfg_mac[6]; // MAC address of local machine
|
|
extern char eth_name[]; // Zero terminated string containing Ethernet driver name
|
|
|
|
// Main IP polling loop
|
|
//
|
|
// This routine should be periodically called by an application at any time
|
|
// that an inbound packet needs to be handled.
|
|
// It is 'non-blocking', i.e. it will return if there is no packet waiting to be
|
|
// handled. Any inbound packet will be handed off to the appropriate handler.
|
|
//
|
|
// Inputs: None
|
|
// Output: true if no packet was waiting or packet handling caused error, false otherwise
|
|
//
|
|
bool ip65_process(void);
|
|
|
|
// Generate a 'random' 16 bit word
|
|
//
|
|
// Entropy comes from the last ethernet frame, counters, and timer.
|
|
//
|
|
// Inputs: None
|
|
// Output: Pseudo-random 16 bit number
|
|
//
|
|
uint16_t ip65_random_word(void);
|
|
|
|
// Convert 4 octets (IP address, netmask) into a string representing a dotted quad
|
|
//
|
|
// The string is returned in a statically allocated buffer, which subsequent calls
|
|
// will overwrite.
|
|
//
|
|
// Inputs: quad: IP address
|
|
// Output: Zero terminated string containing dotted quad (e.g. "192.168.1.0")
|
|
//
|
|
char* __fastcall__ dotted_quad(uint32_t quad);
|
|
|
|
// Convert a string representing a dotted quad (IP address, netmask) into 4 octets
|
|
//
|
|
// Inputs: quad: Zero terminated string containing dotted quad (e.g. "192.168.1.0"),
|
|
// to simplify URL parsing, a ':' or '/' can also terminate the string.
|
|
// Output: IP address, 0 on error
|
|
//
|
|
uint32_t __fastcall__ parse_dotted_quad(char* quad);
|
|
|
|
// Minimal DHCP client implementation
|
|
//
|
|
// IP addresses are requested from a DHCP server (aka 'leased') but are not renewed
|
|
// or released. Although this is not correct behaviour according to the DHCP RFC,
|
|
// this works fine in practice in a typical home network environment.
|
|
//
|
|
// Inputs: None (although ip65_init should be called first)
|
|
// Output: false if IP config has been sucesfully obtained and cfg_ip, cfg_netmask,
|
|
// cfg_gateway and cfg_dns will be set per response from dhcp server.
|
|
// dhcp_server will be set to address of server that provided configuration.
|
|
// true if there was an error
|
|
//
|
|
bool dhcp_init(void);
|
|
|
|
// Access to IP configuration
|
|
//
|
|
// The five items below will be overwritten if dhcp_init is called.
|
|
//
|
|
extern uint32_t cfg_ip; // IP address of local machine
|
|
extern uint32_t cfg_netmask; // Netmask of local network
|
|
extern uint32_t cfg_gateway; // IP address of router on local network
|
|
extern uint32_t cfg_dns; // IP address of DNS server to use
|
|
extern uint32_t dhcp_server; // Address of DHCP server that config was obtained from
|
|
|
|
// Resolve a string containing a hostname (or a dotted quad) to an IP address
|
|
//
|
|
// Inputs: hostname: Zero terminated string containing either a DNS hostname
|
|
// (e.g. "host.example.com") or an address in "dotted quad"
|
|
// format (e.g. "192.168.1.0")
|
|
// Output: IP address of the hostname, 0 on error
|
|
//
|
|
uint32_t __fastcall__ dns_resolve(const char* hostname);
|
|
|
|
// Send a ping (ICMP echo request) to a remote host, and wait for a response
|
|
//
|
|
// Inputs: dest: Destination IP address
|
|
// Output: 0 if no response, otherwise time (in miliseconds) for host to respond
|
|
//
|
|
uint16_t __fastcall__ icmp_ping(uint32_t dest);
|
|
|
|
// Add a UDP listener
|
|
//
|
|
// Inputs: port: UDP port to listen on
|
|
// callback: Vector to call when UDP packet arrives on specified port
|
|
// Output: true if too may listeners already installed, false otherwise
|
|
//
|
|
bool __fastcall__ udp_add_listener(uint16_t port, void (*callback)(void));
|
|
|
|
// Remove a UDP listener
|
|
//
|
|
// Inputs: port: UDP port to stop listening on
|
|
// Output: false if handler found and removed,
|
|
// true if handler for specified port not found
|
|
//
|
|
bool __fastcall__ udp_remove_listener(uint16_t port);
|
|
|
|
// Access to received UDP packet
|
|
//
|
|
// Access to the four items below is only valid in the context of a callback
|
|
// added with udp_add_listener.
|
|
//
|
|
extern uint8_t udp_recv_buf[1476]; // Buffer with data received
|
|
uint16_t udp_recv_len(void); // Length of data received
|
|
uint32_t udp_recv_src(void); // Source IP address
|
|
uint16_t udp_recv_src_port(void); // Source port
|
|
|
|
// Send a UDP packet
|
|
//
|
|
// If the correct MAC address can't be found in the ARP cache then
|
|
// an ARP request is sent - and the UDP packet is NOT sent. The caller
|
|
// should wait a while calling ip65_process (to allow time for an ARP
|
|
// response to arrive) and then call upd_send again. This behavior
|
|
// makes sense as a UDP packet may get lost in transit at any time
|
|
// so the caller should to be prepared to resend it after a while
|
|
// anyway.
|
|
//
|
|
// Inputs: buf: Pointer to buffer containing data to be sent
|
|
// len: Length of data to send (exclusive of any headers)
|
|
// dest: Destination IP address
|
|
// dest_port: Destination port
|
|
// src_port: Source port
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ udp_send(const uint8_t* buf, uint16_t len, uint32_t dest,
|
|
uint16_t dest_port, uint16_t src_port);
|
|
|
|
// Listen for an inbound TCP connection
|
|
//
|
|
// This is a 'blocking' call, i.e. it will not return until a connection has been made.
|
|
//
|
|
// Inputs: port: TCP port to listen on
|
|
// callback: Vector to call when data arrives on this connection
|
|
// buf: Pointer to buffer with data received
|
|
// len: -1 on close, otherwise length of data received
|
|
// Output: IP address of the connected client, 0 on error
|
|
//
|
|
uint32_t __fastcall__ tcp_listen(uint16_t port,
|
|
void __fastcall__ (*callback)(const uint8_t* buf,
|
|
int16_t len));
|
|
|
|
// Make outbound TCP connection
|
|
//
|
|
// Inputs: dest: Destination IP address
|
|
// dest_port: Destination port
|
|
// callback: Vector to call when data arrives on this connection
|
|
// buf: Pointer to buffer with data received
|
|
// len: -1 on close, otherwise length of data received
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ tcp_connect(uint32_t dest, uint16_t dest_port,
|
|
void __fastcall__ (*callback)(const uint8_t* buf,
|
|
int16_t len));
|
|
|
|
// Close the current TCP connection
|
|
//
|
|
// Inputs: None
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool tcp_close(void);
|
|
|
|
// Send data on the current TCP connection
|
|
//
|
|
// Inputs: buf: Pointer to buffer containing data to be sent
|
|
// len: Length of data to send (up to 1460 bytes)
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ tcp_send(const uint8_t* buf, uint16_t len);
|
|
|
|
// Send an empty ACK packet on the current TCP connection
|
|
//
|
|
// Inputs: None
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool tcp_send_keep_alive(void);
|
|
|
|
// Query an SNTP server for current UTC time
|
|
//
|
|
// Inputs: SNTP server IP address
|
|
// Output: The number of seconds since 00:00 on Jan 1 1900 (UTC), 0 on error
|
|
//
|
|
uint32_t __fastcall__ sntp_get_time(uint32_t server);
|
|
|
|
// Download a file from a TFTP server and provide data to user supplied vector
|
|
//
|
|
// Inputs: server: IP address of server to receive file from
|
|
// name: Zero terminated string containing the name of file to download
|
|
// callback: Vector to call once for each 512 byte packet received
|
|
// buf: Pointer to buffer containing data received
|
|
// len: 512 if buffer is full, otherwise number of bytes
|
|
// in the buffer
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ tftp_download(uint32_t server, const char* name,
|
|
void __fastcall__ (*callback)(const uint8_t* buf,
|
|
uint16_t len));
|
|
|
|
// Download a file from a TFTP server and provide data to specified memory location
|
|
//
|
|
// Inputs: server: IP address of server to receive file from
|
|
// name: Zero terminated string containing the name of file to download
|
|
// buf: Pointer to buffer containing data received
|
|
// Output: Length of data received, 0 on error
|
|
//
|
|
uint16_t __fastcall__ tftp_download_to_memory(uint32_t server, const char* name,
|
|
const uint8_t* buf);
|
|
|
|
// Upload a file to a TFTP server with data retrieved from user supplied vector
|
|
//
|
|
// Inputs: server: IP address of server to send file to
|
|
// name: Zero terminated string containing the name of file to upload
|
|
// callback: Vector to call once for each 512 byte packet to be sent
|
|
// buf: Pointer to buffer containing data to be sent
|
|
// Output: 512 if buffer is full, otherwise number of bytes
|
|
// in the buffer
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ tftp_upload(uint32_t server, const char* name,
|
|
uint16_t __fastcall__ (*callback)(const uint8_t* buf));
|
|
|
|
// Upload a file to a TFTP server with data retrieved from specified memory location
|
|
//
|
|
// Inputs: server: IP address of server to send file to
|
|
// name: Zero terminated string containing the name of file to upload
|
|
// buf: Pointer to buffer containing data to be sent
|
|
// len: Length of data to be sent
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ tftp_upload_from_memory(uint32_t server, const char* name,
|
|
const uint8_t* buf, uint16_t len);
|
|
|
|
// Parse an HTTP URL into a form that makes it easy to retrieve the specified resource
|
|
//
|
|
// On success the variables url_ip, url_port and url_selector (see below) are valid.
|
|
//
|
|
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
|
// Output: true if an error occured, false otherwise
|
|
//
|
|
bool __fastcall__ url_parse(const char* url);
|
|
|
|
// Access to parsed HTTP URL
|
|
//
|
|
// Access to the three items below is only valid after url_parse returned false.
|
|
//
|
|
extern uint32_t url_ip; // IP address of host in URL
|
|
extern uint16_t url_port; // Port number of URL
|
|
extern char* url_selector; // Zero terminated string containing selector part of URL
|
|
|
|
// Download a resource specified by an HTTP URL
|
|
//
|
|
// The URL mustn't be longer than 1400 chars. The buffer is temporarily used to hold the
|
|
// generated HTTP request so it should have a length of at least 1460 bytes. On success
|
|
// the resource is zero terminated.
|
|
//
|
|
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
|
// buf: Pointer to a buffer that the resource will be downloaded into
|
|
// len: Length of buffer
|
|
// Output: Length of resource downloaded, 0 on error
|
|
//
|
|
uint16_t __fastcall__ url_download(const char* url, const uint8_t* buf, uint16_t len);
|
|
|
|
// Start an HTTP server
|
|
//
|
|
// This routine will stay in an endless loop that is broken only if user press the abort key.
|
|
//
|
|
// Inputs: port: TCP port to listen on
|
|
// callback: Vector to call for each inbound HTTP request
|
|
// client: IP address of the client that sent the request
|
|
// method: Zero terminated string containing the HTTP method
|
|
// path: Zero terminated string containing the HTTP path
|
|
// Output: None
|
|
//
|
|
void __fastcall__ httpd_start(uint16_t port,
|
|
void __fastcall__ (*callback)(uint32_t client,
|
|
const char* method,
|
|
const char* path));
|
|
|
|
// HTTP response types
|
|
//
|
|
#define HTTPD_RESPONSE_NOHEADER 0 // No HTTP response header
|
|
#define HTTPD_RESPONSE_200_TEXT 1 // HTTP Code: 200 OK, Content Type: 'text/text'
|
|
#define HTTPD_RESPONSE_200_HTML 2 // HTTP Code: 200 OK, Content Type: 'text/html'
|
|
#define HTTPD_RESPONSE_200_DATA 3 // HTTP Code: 200 OK, Content Type: 'application/octet-stream'
|
|
#define HTTPD_RESPONSE_404 4 // HTTP Code: 404 Not Found
|
|
#define HTTPD_RESPONSE_500 5 // HTTP Code: 500 System Error
|
|
|
|
// Send HTTP response
|
|
//
|
|
// Calling httpd_send_response is only valid in the context of a httpd_start callback.
|
|
// For the response types HTTPD_RESPONSE_404 and HTTPD_RESPONSE_500 'buf' is ignored.
|
|
// With the response type HTTPD_RESPONSE_NOHEADER it's possible to add more content to
|
|
// an already sent HTTP response.
|
|
//
|
|
// Inputs: response_type: Value describing HTTP code and content type in response header
|
|
// buf: Pointer to buffer with HTTP response content
|
|
// len: Length of buffer with HTTP response content
|
|
// Output: None
|
|
//
|
|
void __fastcall__ httpd_send_response(uint8_t response_type,
|
|
const uint8_t* buf, uint16_t len);
|
|
|
|
// Retrieve the value of a variable defined in the previously received HTTP request
|
|
//
|
|
// Calling http_get_value is only valid in the context of a httpd_start callback.
|
|
// Only the first letter in a variable name is significant. E.g. if a querystring contains
|
|
// the variables 'a','alpha' and 'alabama', then only the first one will be retrievable.
|
|
//
|
|
// Inputs: name: Variable to retrieve
|
|
// Output: Variable value (zero terminated string) if variable exists, null otherwise.
|
|
//
|
|
char* __fastcall__ http_get_value(char name);
|
|
|
|
// Get number of milliseconds since initialization
|
|
//
|
|
// Inputs: None
|
|
// Output: Current number of milliseconds
|
|
//
|
|
uint16_t timer_read(void);
|
|
|
|
// Check if specified period of time has passed yet
|
|
//
|
|
// Inputs: time: Number of milliseconds we are willing to wait for
|
|
// Output: true if timeout occured, false otherwise
|
|
//
|
|
bool __fastcall__ timer_timeout(uint16_t time);
|
|
|
|
// Check whether the abort key is being pressed
|
|
//
|
|
// Inputs: None
|
|
// Output: true if abort key pressed, false otherwise
|
|
//
|
|
bool input_check_for_abort_key(void);
|
|
|
|
// Control abort key
|
|
//
|
|
// Control if the user can abort blocking functions with the abort key
|
|
// (making them return IP65_ERROR_ABORTED_BY_USER). Initially the abort
|
|
// key is enabled.
|
|
//
|
|
// Inputs: enable: false to disable the key, true to enable the key
|
|
// Output: None
|
|
//
|
|
void __fastcall__ input_set_abort_key(bool enable);
|
|
|
|
// Access to actual abort key code
|
|
//
|
|
extern uint8_t abort_key;
|
|
|
|
#endif
|