diff --git a/inc/ip65.h b/inc/ip65.h index 5cbde52..0d2f72d 100644 --- a/inc/ip65.h +++ b/inc/ip65.h @@ -45,11 +45,6 @@ extern unsigned long cfg_dns; // extern unsigned long dhcp_server; -// -// -extern unsigned char* tcp_packet; -extern unsigned int tcp_packet_len; - // Initialise the IP stack // // This calls the individual protocol & driver initialisations, so this is @@ -178,6 +173,56 @@ unsigned char __fastcall__ udp_send(const unsigned char* buf, unsigned int len, unsigned long dest, unsigned int dest_port, unsigned int 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 +// Output: 1 if an error occured, 0 otherwise +// +unsigned char __fastcall__ tcp_listen(unsigned int port, void (*callback)(void)); + +// Make outbound TCP connection +// +// Inputs: dest: Destination IP address +// dest_port: Destination port +// callback: Vector to call when data arrives on this connection +// Output: 1 if an error occured, 0 otherwise +// +unsigned char __fastcall__ tcp_connect(unsigned long dest, unsigned int dest_port, + void (*callback)(void)); + +// Close the current TCP connection +// +// Inputs: None +// Output: 1 if an error occured, 0 otherwise +// +unsigned char tcp_close(void); + +// Access to received TCP data +// +// Access to the two items below is only valid in the context of a callback +// set with tcp_listen or tcp_connect. +// +extern unsigned char* tcp_recv_buf; // Pointer to buffer with data received +extern int tcp_recv_len; // -1 on close, otherwise length of data received + +// Send data on the current TCP connection +// +// Inputs: buf: Pointer to buffer containing data to be sent +// len: Length of data to send (exclusive of any headers) +// Output: 1 if an error occured, 0 otherwise +// +unsigned char __fastcall__ tcp_send(const unsigned char* buf, unsigned int len); + +// Send an empty ACK packet on the current TCP connection +// +// Inputs: None +// Output: 1 if an error occured, 0 otherwise +// +unsigned char tcp_send_keep_alive(void); + // Get number of milliseconds since initialization // // Inputs: None diff --git a/ip65/Makefile b/ip65/Makefile index 8b0858f..3ffe3b8 100644 --- a/ip65/Makefile +++ b/ip65/Makefile @@ -28,6 +28,7 @@ IP65OBJS=\ input_c.o \ ip65.o \ ip65_c.o \ + tcp_c.o \ tftp.o \ timer.o \ timer_c.o \ diff --git a/ip65/tcp_c.s b/ip65/tcp_c.s new file mode 100644 index 0000000..0926e2e --- /dev/null +++ b/ip65/tcp_c.s @@ -0,0 +1,75 @@ +.include "../inc/common.i" + +.export _tcp_listen +.export _tcp_connect +.export _tcp_close +.export _tcp_recv_buf +.export _tcp_recv_len +.export _tcp_send +.export _tcp_send_keep_alive + +.import tcp_listen +.import tcp_connect +.import tcp_close +.import tcp_inbound_data_ptr +.import tcp_inbound_data_length +.import tcp_send +.import tcp_send_keep_alive + +.import tcp_callback +.import tcp_connect_ip +.import tcp_send_data_len + +.import popax, popeax +.importzp ptr1, sreg + +_tcp_listen: + stax tcp_callback + jsr popax + jsr tcp_listen + ldx #$00 + txa + rol + rts + +_tcp_connect: + stax tcp_callback + jsr popax + stax ptr1 + jsr popeax + stax tcp_connect_ip + ldax sreg + stax tcp_connect_ip+2 + ldax ptr1 + jsr tcp_connect + ldx #$00 + txa + rol + rts + +_tcp_close: + jsr tcp_close + ldx #$00 + txa + rol + rts + +_tcp_recv_buf := tcp_inbound_data_ptr + +_tcp_recv_len := tcp_inbound_data_length + +_tcp_send: + stax tcp_send_data_len + jsr popax + jsr tcp_send + ldx #$00 + txa + rol + rts + +_tcp_send_keep_alive: + jsr tcp_send_keep_alive + ldx #$00 + txa + rol + rts diff --git a/test/Makefile b/test/Makefile index 9014027..5af28a0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -37,7 +37,8 @@ TCP =\ httpd \ math \ parser \ - ping + ping \ + tcp all: $(UDP) $(TCP) .PHONY: $(UDP) $(TCP) @@ -128,6 +129,7 @@ ip65test.d64: prg $(C1541) -attach $@ -write parser.prg parser,p $(C1541) -attach $@ -write ping.prg ping,p $(C1541) -attach $@ -write sntp.prg sntp,p + $(C1541) -attach $@ -write tcp.prg tcp,p $(C1541) -attach $@ -write tftp.prg tftp,p $(C1541) -attach $@ -write udp.prg udp,p $(C1541) -attach $@ -write vt100.prg vt100,p @@ -143,9 +145,9 @@ ip65test.dsk: bin java -jar $(AC) -cc65 $@ parser bin < parser.bin java -jar $(AC) -cc65 $@ ping bin < ping.bin java -jar $(AC) -cc65 $@ sntp bin < sntp.bin + java -jar $(AC) -cc65 $@ tcp bin < tcp.bin java -jar $(AC) -cc65 $@ tftp bin < tftp.bin java -jar $(AC) -cc65 $@ udp bin < udp.bin - java -jar $(AC) -cc65 $@ vt100 bin < vt100.bin ip65test.atr: com mkdir atr @@ -159,6 +161,7 @@ ip65test.atr: com cp parser.com atr/parser.com cp ping.com atr/ping.com cp sntp.com atr/sntp.com + cp tcp.com atr/tcp.com cp tftp.com atr/tftp.com cp udp.com atr/udp.com cp vt100.com atr/vt100.com diff --git a/test/tcp.c b/test/tcp.c new file mode 100644 index 0000000..3751c9e --- /dev/null +++ b/test/tcp.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +#include "../inc/ip65.h" + +#define LEN 500 +#define SRV "192.168.0.10" + +unsigned char buf[1500]; +int len; + +void error_exit(void) +{ + printf("Error $%X\n", ip65_error); + if (doesclrscrafterexit()) + { + printf("Press any key\n"); + cgetc(); + } + exit(1); +} + +void tcp_recv(void) +{ + if (len) + { + return; + } + len = tcp_recv_len; + if (len != -1) + { + memcpy(buf, tcp_recv_buf, len); + } +} + +void main(void) +{ + unsigned i; + unsigned long srv; + char key; + + if(!(srv = parse_dotted_quad(SRV))) + { + error_exit(); + } + + printf("Init\n"); + if (ip65_init()) + { + error_exit(); + } + + printf("DHCP\n"); + if (dhcp_init()) + { + error_exit(); + } + + printf("IP Addr: %s\n", dotted_quad(cfg_ip)); + printf("Netmask: %s\n", dotted_quad(cfg_netmask)); + printf("Gateway: %s\n", dotted_quad(cfg_gateway)); + printf("DNS Srv: %s\n", dotted_quad(cfg_dns)); + + printf("Connect to %s\n", SRV); + if (tcp_connect(srv, 6502, tcp_recv)) + { + error_exit(); + } + + printf("(T)CP or e(X)it\n"); + do + { + ip65_process(); + + if (kbhit()) + { + key = cgetc(); + } + else + { + key = '\0'; + } + + if (key == 't') + { + printf("Send Len %d", LEN); + for (i = 0; i < LEN; ++i) + { + buf[i] = i; + } + if (tcp_send(buf, LEN)) + { + printf("!\n"); + } + else + { + printf(".\n"); + } + } + + if (len == -1) + { + printf("Disconnect\n"); + } + else if (len) + { + printf("Recv Len %d", len); + for (i = 0; i < len; ++i) + { + if ((i % 11) == 0) + { + ip65_process(); + printf("\n$%04X:", i); + } + printf(" %02X", buf[i]); + } + len = 0; + printf(".\n"); + } + } + while (key != 'x' && len != -1); + + printf("Close\n"); + if (tcp_close()) + { + error_exit(); + } + + printf("Done\n"); +}