From 055a5f24490d65382348629ee0279079881c5935 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Thu, 25 Jul 2019 09:43:33 +0200 Subject: [PATCH] got a first basic test passing --- libs/network/Echo.idr | 85 ++++++++++++++-------------- libs/network/Makefile | 11 ++-- libs/network/Network/Socket/Data.idr | 2 +- libs/network/Network/Socket/Raw.idr | 6 +- libs/network/expected | 4 ++ libs/network/idris_net.c | 6 +- libs/network/test.c | 21 +++++-- 7 files changed, 77 insertions(+), 58 deletions(-) create mode 100644 libs/network/expected diff --git a/libs/network/Echo.idr b/libs/network/Echo.idr index f3a1b2f..4eeb883 100644 --- a/libs/network/Echo.idr +++ b/libs/network/Echo.idr @@ -1,50 +1,50 @@ module Main +import System import Network.Socket import Network.Socket.Data import Network.Socket.Raw -runServer : IO (Either String (Port, Maybe ThreadID)) +%cg chez libidris_net.dylib + +runServer : IO (Either String (Port, ThreadID)) runServer = do osock <- socket AF_INET Stream 0 case osock of Left fail => pure (Left $ "Failed to open socket: " ++ show fail) Right sock => do - putStrLn "success" - pure $ Right (0,Nothing) - -- do - -- res <- bind sock (Just (Hostname "localhost")) 0 - -- if res /= 0 - -- then pure (Left $ "Failed to bind socket with error: " ++ show res) - -- else do - -- port <- getSockPort sock - -- res <- listen sock - -- if res /= 0 - -- then pure (Left $ "Failed to listen on socket with error: " ++ show res) - -- else do - -- forked <- fork (serve sock) - -- pure $ Right (port, forked) + res <- bind sock (Just (Hostname "localhost")) 0 + if res /= 0 + then pure (Left $ "Failed to bind socket with error: " ++ show res) + else do + port <- getSockPort sock + res <- listen sock + if res /= 0 + then pure (Left $ "Failed to listen on socket with error: " ++ show res) + else do + forked <- fork (serve port sock) + pure $ Right (port, forked) - -- where - -- serve : Socket -> IO () - -- serve sock = do - -- res <- accept sock - -- case res of - -- Left err => do - -- putStrLn ("Failed to accept on socket with error: " ++ show err) - -- Right (s, _) => do - -- received <- recv s 1024 - -- case received of - -- Left err => do - -- putStrLn ("Failed to accept on socket with error: " ++ show err) - -- Right (str, _) => do - -- putStrLn ("Received: " ++ str) - -- sent <- send s ("echo: " ++ str) - -- case sent of - -- Left err => do - -- putStrLn ("Server failed to send data with error: " ++ show err) - -- Right n => - -- putStrLn ("Server sent " ++ show n ++ " bytes") + where + serve : Port -> Socket -> IO () + serve port sock = do + res <- accept sock + case res of + Left err => do + putStrLn ("Failed to accept on socket with error: " ++ show err) + Right (s, _) => do + received <- recv s 1024 + case received of + Left err => do + putStrLn ("Failed to accept on socket with error: " ++ show err) + Right (str, _) => do + putStrLn ("Received: " ++ str) + sent <- send s ("echo: " ++ str) + case sent of + Left err => do + putStrLn ("Server failed to send data with error: " ++ show err) + Right n => + putStrLn ("Server sent " ++ show n ++ " bytes") runClient : Port -> IO () runClient serverPort = do @@ -54,7 +54,7 @@ runClient serverPort = do Right sock => do res <- connect sock (Hostname "localhost") serverPort if res /= 0 - then putStrLn ("Failed to connect client to port " ++ show serverPort) + then putStrLn ("Failed to connect client to port " ++ show serverPort ++ ": " ++ show res) else do sent <- send sock ("hello world!") case sent of @@ -69,9 +69,10 @@ runClient serverPort = do Right (str, _) => do putStrLn ("Received: " ++ str) --- main : IO () --- main = do --- server <- runServer --- case server of --- Left err => putStrLn $ "[server] " ++ err --- Right (serverPort, tid) => runClient serverPort +main : IO () +main = do + server <- runServer + case server of + Left err => putStrLn $ "[server] " ++ err + Right (serverPort, tid) => do + runClient serverPort diff --git a/libs/network/Makefile b/libs/network/Makefile index 6c040fd..4d2b59c 100644 --- a/libs/network/Makefile +++ b/libs/network/Makefile @@ -29,16 +29,17 @@ LIBNAME=idris_net OBJS = $(LIBNAME).o HDRS = $(LIBNAME).h CFLAGS := $(CFLAGS) +IDRIS_SRCS = Network/Socket.idr Network/Socket/Data.idr Network/Socket/Raw.idr ifneq ($(OS), windows) CFLAGS += -fPIC endif -DYLIBTARGET = lib$(LIBNAME)$(SHLIB_SUFFIX) +DYLIBTARGET = $(LIBNAME)$(SHLIB_SUFFIX) LIBTARGET = $(LIBNAME).a TARGET=${HOME}/.idris2 -build: $(DYLIBTARGET) +build: $(DYLIBTARGET) $(IDRIS_SRCS) @if ! [ -d build ]; then echo "creating 'build' directory"; mkdir build ; else echo "directory 'build' exists"; fi @if [ -z "${IDRIS2}" ]; then echo 'variable $$IDRIS2 is not set, aborting'; exit 1; fi ${IDRIS2} --build network.ipkg @@ -53,13 +54,15 @@ install: clean : rm -rf $(OBJS) $(LIBTARGET) $(DYLIBTARGET) build -test: $(DYLIBTARGET) +test: build test.c $(CC) -o network-tests -L. -I. -l$(LIBNAME) test.c ./network-tests + ${IDRIS2} --exec main Echo.idr > build/output + @if ! [ -z "$(diff build/output expected)" ]; then echo "TEST FAILURE: unexpected build/output"; exit 2; else echo "TEST SUCCESS"; fi $(OBJS): $(HDRS) all: $(DYLIBTARGET) $(LIBTARGET) ${IDRIS2} --build network.ipkg -.PHONY: build install clean +.PHONY: install clean diff --git a/libs/network/Network/Socket/Data.idr b/libs/network/Network/Socket/Data.idr index b4f8874..4070f83 100644 --- a/libs/network/Network/Socket/Data.idr +++ b/libs/network/Network/Socket/Data.idr @@ -60,7 +60,7 @@ EAGAIN = export getErrno : IO SocketError -getErrno = cCall SocketError "idrnet_errno" [] +getErrno = cCall Int "idrnet_errno" [] export nullPtr : Ptr -> IO Bool diff --git a/libs/network/Network/Socket/Raw.idr b/libs/network/Network/Socket/Raw.idr index 90edd5e..41515f3 100644 --- a/libs/network/Network/Socket/Raw.idr +++ b/libs/network/Network/Socket/Raw.idr @@ -40,7 +40,7 @@ sock_alloc bl = map BPtr $ cCall Ptr "idrnet_malloc" [bl] ||| Retrieves the port the given socket is bound to export getSockPort : Socket -> IO Port -getSockPort sock = cCall Port "idrnet_sockaddr_port" [descriptor sock] +getSockPort sock = cCall Int "idrnet_sockaddr_port" [descriptor sock] ||| Retrieves a socket address from a sockaddr pointer @@ -101,7 +101,7 @@ recvBuf : (sock : Socket) -> (len : ByteLength) -> IO (Either SocketError ResultCode) recvBuf sock (BPtr ptr) len = do - recv_res <- cCall ResultCode "idrnet_recv_buf" [ descriptor sock, ptr, len ] + recv_res <- cCall Int "idrnet_recv_buf" [ descriptor sock, ptr, len ] if (recv_res == (-1)) then map Left getErrno @@ -125,7 +125,7 @@ sendToBuf : (sock : Socket) -> (len : ByteLength) -> IO (Either SocketError ResultCode) sendToBuf sock addr p (BPtr dat) len = do - sendto_res <- cCall ResultCode "idrnet_sendto_buf" + sendto_res <- cCall Int "idrnet_sendto_buf" [ descriptor sock, dat, len, show addr, p, toCode $ family sock ] if sendto_res == (-1) diff --git a/libs/network/expected b/libs/network/expected new file mode 100644 index 0000000..bf70af7 --- /dev/null +++ b/libs/network/expected @@ -0,0 +1,4 @@ +Client sent 12 bytes +Received: hello world! +Server sent 18 bytes +Received: echo: hello world! diff --git a/libs/network/idris_net.c b/libs/network/idris_net.c index f11089d..84505f7 100644 --- a/libs/network/idris_net.c +++ b/libs/network/idris_net.c @@ -92,7 +92,7 @@ int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port, } int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) { - struct addrinfo* address_res; + struct addrinfo *address_res; int addr_res = idrnet_getaddrinfo(&address_res, host, port, family, socket_type); if (addr_res != 0) { //printf("Lib err: bind getaddrinfo\n"); @@ -128,9 +128,9 @@ int idrnet_sockaddr_port(int sockfd) { switch(address.sa_family) { case AF_INET: - return ((struct sockaddr_in*)&address)->sin_port; + return ntohs(((struct sockaddr_in*)&address)->sin_port); case AF_INET6: - return ((struct sockaddr_in6*)&address)->sin6_port; + return ntohs(((struct sockaddr_in6*)&address)->sin6_port); default: return -1; } diff --git a/libs/network/test.c b/libs/network/test.c index 81392bb..80e94ef 100644 --- a/libs/network/test.c +++ b/libs/network/test.c @@ -11,9 +11,7 @@ void test_eagain() { } -void test_bind_to_0_assigns_random_port() { - struct sockaddr_in address; - socklen_t addrlen = sizeof(struct sockaddr); +void test_sockaddr_port_returns_random_port_when_bind_port_is_0() { int sock = idrnet_socket(AF_INET, 1, 0); assert(sock > 0); @@ -23,14 +21,27 @@ void test_bind_to_0_assigns_random_port() { res = idrnet_sockaddr_port(sock); assert(res > 0); - printf("socket bound to %d\n",res); + close(sock); +} + +void test_sockaddr_port_returns_explicitly_assigned_port() { + int sock = idrnet_socket(AF_INET, 1, 0); + assert(sock > 0); + + int res = idrnet_bind(sock, AF_INET, 1, "127.0.0.1", 34567); + assert(res == 0); + + res = idrnet_sockaddr_port(sock); + assert(res == 34567); + close(sock); } int main(int argc, char**argv) { test_eagain(); - test_bind_to_0_assigns_random_port(); + test_sockaddr_port_returns_explicitly_assigned_port(); + test_sockaddr_port_returns_random_port_when_bind_port_is_0(); printf("network library tests SUCCESS\n"); return 0;