diff --git a/Shrine/mkdist.script b/Shrine/mkdist.script index d2988fe4..b66d0b32 100644 --- a/Shrine/mkdist.script +++ b/Shrine/mkdist.script @@ -76,12 +76,12 @@ put /Tmp/SnailNet/Http.HC.Z SnailNet/Http.HC put /Tmp/SnailNet/Icmp.HC.Z SnailNet/Icmp.HC put /Tmp/SnailNet/IPv4.HC.Z SnailNet/IPv4.HC put /Tmp/SnailNet/MakeSnailNet.HC.Z SnailNet/MakeSnailNet.HC +put /Tmp/SnailNet/NativeSocket.HC.Z SnailNet/NativeSocket.HC put /Tmp/SnailNet/Netcfg.HC.Z SnailNet/Netcfg.HC put /Tmp/SnailNet/NetFifo.HC.Z SnailNet/NetFifo.HC put /Tmp/SnailNet/NetHandlerTask.HC.Z SnailNet/NetHandlerTask.HC put /Tmp/SnailNet/SnailLib.HC.Z SnailNet/SnailLib.HC put /Tmp/SnailNet/Socket.HC.Z SnailNet/Socket.HC -put /Tmp/SnailNet/SocketLib.HC.Z SnailNet/SocketLib.HC put /Tmp/SnailNet/Tcp.HC.Z SnailNet/Tcp.HC put /Tmp/SnailNet/Udp.HC.Z SnailNet/Udp.HC put /Tmp/SnailNet/Url.HC.Z SnailNet/Url.HC diff --git a/SnailNet/Http.HC b/SnailNet/Http.HC index b18527aa..9e6bb7e3 100644 --- a/SnailNet/Http.HC +++ b/SnailNet/Http.HC @@ -12,8 +12,6 @@ I64 HttpOpenGet(U8* host, U16 port = 0, U8* path, I64* len_out) { U8 line[256]; I64 error = 0; - I64 sock = socket(AF_INET, SOCK_STREAM); - if (!port) port = 80; @@ -22,9 +20,9 @@ I64 HttpOpenGet(U8* host, U16 port = 0, U8* path, I64* len_out) { path = "/"; //"Connect(%s:%d)\n", host, port; - error = connectTcp(sock, host, port); - //"connect: %d\n", error; - if (error == 0) { + I64 sock = create_connection(host, port); + //"create_connection: %d\n", sock; + if (sock >= 0) { StrPrint(line, "GET %s HTTP/1.1\r\n", path); sendString(sock, line, 0); StrPrint(line, "Host: %s\r\n", host); diff --git a/SnailNet/MakeSnailNet.HC b/SnailNet/MakeSnailNet.HC index ce3f9fae..50dad43b 100644 --- a/SnailNet/MakeSnailNet.HC +++ b/SnailNet/MakeSnailNet.HC @@ -18,7 +18,7 @@ StreamPrint("#include \"::/Adam/HwSupp/%s\"", native_driver); // Contains a lot of common definitions, probably should be cleaned up - StreamPrint("#include \"::/Adam/Net/SocketLib\""); + StreamPrint("#include \"::/Adam/Net/NativeSocket\""); // L2 StreamPrint("#include \"::/Adam/Net/Ethernet\""); diff --git a/SnailNet/SocketLib.HC b/SnailNet/NativeSocket.HC similarity index 74% rename from SnailNet/SocketLib.HC rename to SnailNet/NativeSocket.HC index 74a33db2..12ef9e1d 100644 --- a/SnailNet/SocketLib.HC +++ b/SnailNet/NativeSocket.HC @@ -1,21 +1,21 @@ // vim: set ft=c: -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 -#define AF_UNSPEC 0 -#define AF_INET 2 -#define AF_INET6 10 +#define AF_UNSPEC 0 +#define AF_INET 2 +#define AF_INET6 10 -#define INADDR_ANY 0 +#define INADDR_ANY 0 -#define SOL_SOCKET 1 +#define SOL_SOCKET 1 // optval = I64* -#define SO_RCVTIMEO_MS 1 +#define SO_RCVTIMEO_MS 1 -#define AI_CACHED 0x8000 +#define AI_CACHED 0x8000 class in_addr { U32 s_addr; @@ -159,8 +159,6 @@ I64 setsockopt(I64 sockfd, I64 level, I64 optname, U8* optval, I64 optlen) { else return -1; } -I64 connectTcp(I64, U8*, U16) { return -1; } -I64 recvall(I64, U8*, I64, I64) { return -1; } I64 getaddrinfo(U8* node, U8* service, addrinfo* hints, addrinfo** res) { if (socket_addr_resolver) return socket_addr_resolver->getaddrinfo(node, service, hints, res); else return -1; @@ -194,6 +192,67 @@ U8* gai_strerror(I64 errcode) { return "Unspecified error"; } +// Inspired by https://docs.python.org/3.7/library/socket.html#socket.create_connection +I64 create_connection(U8* hostname, U16 port) { + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = 0; + + addrinfo* res; + I64 error = getaddrinfo(hostname, NULL, NULL, &res); + + if (error < 0) { + "$FG,4$getaddrinfo: error %d\n$FG$", error; + } + else { + addrinfo* curr = res; + + while (curr) { + if (curr->ai_family == AF_INET && (curr->ai_socktype == 0 || curr->ai_socktype == SOCK_STREAM)) { + addr.sin_addr.s_addr = (curr->ai_addr(sockaddr_in*))->sin_addr.s_addr; + freeaddrinfo(res); + + I64 sockfd = socket(AF_INET, SOCK_STREAM); + + if (sockfd < 0) + return sockfd; + + error = connect(sockfd, &addr, sizeof(addr)); + + if (error < 0) { + close(sockfd); + return error; + } + + return sockfd; + } + + curr = curr->ai_next; + } + + "$FG,4$create_connection: no suitable address\n$FG$"; + } + + freeaddrinfo(res); + return -1; +} + +I64 recvall(I64 sockfd, U8* buf, I64 len, I64 flags) { + I64 total = 0; + + while (len) { + I64 got = recv(sockfd, buf + total, len, flags); + + if (got < 0) + break; + + len -= got; + total += got; + } + + return total; +} U0 RegisterSocketClass(U16 domain, U16 type, CSocket* (*socket)(U16 domain, U16 type)) { CSocketClass* cls = MAlloc(sizeof(CSocketClass)); diff --git a/SnailNet/SnailLib.HC b/SnailNet/SnailLib.HC index 7d1235f1..6ca9c01e 100644 --- a/SnailNet/SnailLib.HC +++ b/SnailNet/SnailLib.HC @@ -99,14 +99,26 @@ I64 close(I64 sockfd) { return ReadI8(); } -I64 connectTcp(I64 sockfd, U8* addr, U16 port) { +I64 create_connection(U8* addr, U16 port) { + I64 sockfd = socket(AF_INET, SOCK_STREAM); + + if (sockfd < 0) + return sockfd; + CommPutChar(SNAIL_COM, CMD_CONNECT_TCP); CommPutChar(SNAIL_COM, sockfd); CommPutChar(SNAIL_COM, StrLen(addr)); CommPutS(SNAIL_COM, addr); CommPutChar(SNAIL_COM, port & 0xff); CommPutChar(SNAIL_COM, port >> 8); - return ReadI8(); + + I64 error = ReadI8(); + if (error < 0) { + close(sockfd); + return error; + } + + return sockfd; } I64 recvall(I64 sockfd, U8* buf, I64 len, I64 flags) { diff --git a/SnailNet/SocketDummy.HC b/SnailNet/SocketDummy.HC index fedab01a..2a8d3dcf 100644 --- a/SnailNet/SocketDummy.HC +++ b/SnailNet/SocketDummy.HC @@ -11,7 +11,7 @@ I64 SocketInit() { throw; return -1; } I64 socket(I64, I64) { return -1; } I64 close(I64) { return -1; } -I64 connectTcp(I64, U8*, U16) { return -1; } +I64 create_connection(U8*, U16) { return -1; } I64 recvall(I64, U8*, I64, I64) { return -1; } I64 send(I64, U8*, I64, I64) { return -1; } I64 recvLine(I64, U8*, I64, I64) { return -1; }