on master help sign in
Make Network.Socket work on Windows

Consolidate the network stuff in one file.

commitcecf6bf2685628a18052c7b28925ac2c93ec0f0d authorNiklas Larsson <niklas@mm.st> dateTue 22 Aug 2017, 23:19 (9 years ago) parent82114d1
6 files changed+48−214
libs/contrib/Network/Socket.idr+1−5 libs/contrib/Network/Socket/Raw.idr−3 rts/Makefile+2−3 rts/idris_net.c+32−3 rts/idris_net.h+13 rts/windows/idris_net.c−200
libs/contrib/Network/Socket.idr+1−5
@@ -8,10 +8,6 @@ import public Network.Socket.Data
88import Network.Socket.Raw
99
1010%include C "idris_net.h"
11−%include C "sys/types.h"
12−%include C "sys/socket.h"
13−%include C "unistd.h"
14−%include C "netdb.h"
1511
1612%access export
1713
@@ -24,7 +20,7 @@ socket : (fam : SocketFamily)
2420 -> (pnum : ProtocolNumber)
2521 -> IO (Either SocketError Socket)
2622socket sf st pn = do
27− socket_res <- foreign FFI_C "socket"
23+ socket_res <- foreign FFI_C "idrnet_socket"
2824 (Int -> Int -> Int -> IO Int)
2925 (toCode sf) (toCode st) pn
3026
libs/contrib/Network/Socket/Raw.idr−3
@@ -8,9 +8,6 @@ module Network.Socket.Raw
88import public Network.Socket.Data
99
1010%include C "idris_net.h"
11−%include C "sys/types.h"
12−%include C "sys/socket.h"
13−%include C "netdb.h"
1411
1512%access public export
1613
rts/Makefile+2−3
@@ -2,7 +2,7 @@ include ../config.mk
22
33OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_bitstring.o \
44 idris_opts.o idris_stats.o idris_utf8.o idris_stdfgn.o mini-gmp.o \
5− idris_buffer.o getline.o
5+ idris_buffer.o getline.o idris_net.o
66HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_bitstring.h \
77 idris_opts.h idris_stats.h mini-gmp.h idris_stdfgn.h idris_net.h \
88 idris_buffer.h idris_utf8.h getline.h
@@ -20,10 +20,9 @@ endif
2020endif
2121
2222ifeq ($(OS), windows)
23− OBJS += windows/idris_net.o windows/win_utils.o
23+ OBJS += windows/win_utils.o
2424else
2525 CFLAGS += -fPIC
26− OBJS += idris_net.o
2726endif
2827
2928LIBTARGET = libidris_rts.a
rts/idris_net.c+32−3
@@ -3,15 +3,34 @@
33// MIT Licensed. Have fun!
44#include "idris_net.h"
55#include <errno.h>
6−#include <netdb.h>
76#include <stdbool.h>
87#include <stdlib.h>
98#include <stdio.h>
109#include <string.h>
11−#include <sys/types.h>
12−#include <sys/socket.h>
10+
11+#ifndef WIN32
1312#include <netinet/in.h>
1413#include <arpa/inet.h>
14+#else
15+static int socket_inited = 0;
16+static WSADATA wsa_data;
17+
18+static void clean_sockets(void) {
19+ WSACleanup();
20+}
21+
22+static int check_init(void) {
23+ if (!socket_inited) {
24+ int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
25+ if (result == NO_ERROR) {
26+ socket_inited = 1;
27+ atexit(clean_sockets);
28+ }
29+ }
30+ return socket_inited;
31+}
32+#endif
33+
1534
1635void buf_htonl(void* buf, int len) {
1736 int* buf_i = (int*) buf;
@@ -37,6 +56,16 @@ void idrnet_free(void* ptr) {
3756 free(ptr);
3857}
3958
59+
60+int idrnet_socket(int domain, int type, int protocol) {
61+#ifdef WIN32
62+ if (!check_init()) {
63+ return -1;
64+ }
65+#endif
66+ return socket(domain, type, protocol);
67+}
68+
4069// We call this from quite a few functions. Given a textual host and an int port,
4170// populates a struct addrinfo.
4271int idrnet_getaddrinfo(struct addrinfo** address_res, char* host, int port,
rts/idris_net.h+13
@@ -1,6 +1,17 @@
11#ifndef IDRISNET_H
22#define IDRISNET_H
33
4+// Includes used by the idris-file.
5+#ifdef WIN32
6+#include <winsock2.h>
7+#include <Ws2tcpip.h>
8+#else
9+#include <netdb.h>
10+#include <unistd.h>
11+#include <sys/types.h>
12+#include <sys/socket.h>
13+#endif
14+
415struct sockaddr_storage;
516struct addrinfo;
617
@@ -24,6 +35,8 @@ void idrnet_free(void* ptr);
2435// Gets value of errno
2536int idrnet_errno();
2637
38+int idrnet_socket(int domain, int type, int protocol);
39+
2740// Bind
2841int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port);
2942
rts/windows/idris_net.cdeleted−200
@@ -1,200 +0,0 @@
1−// C-Side of the Idris network library
2−// (C) Simon Fowler, 2014
3−// MIT Licensed. Have fun!
4−#include "../idris_net.h"
5−
6−#include <errno.h>
7−#include <stdbool.h>
8−#include <stdlib.h>
9−#include <stdio.h>
10−#include <string.h>
11−#include <Winsock2.h>
12−#include <Ws2tcpip.h>
13−
14−
15−// inet_ntop isn't defined in the old mingw delivered with GHC,
16−// so put the prototype here, cribbed from a newer version of it
17−WINSOCK_API_LINKAGE LPCSTR WSAAPI InetNtopA(INT Family, PVOID pAddr,
18− LPSTR pStringBuf, size_t StringBufSize);
19−
20−static int socket_inited = 0;
21−static WSADATA wsa_data;
22−
23−void* idrnet_malloc(int size) {
24− return malloc(size);
25−}
26−
27−void idrnet_free(void* ptr) {
28− free(ptr);
29−}
30−
31−static void clean_sockets(void) {
32− WSACleanup();
33−}
34−
35−static int check_init(void)
36−{
37− if (!socket_inited) {
38− int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
39− if (result == NO_ERROR) {
40− socket_inited = 1;
41− atexit(clean_sockets);
42− }
43− }
44− return socket_inited;
45−}
46−
47−int idrnet_bind(int sockfd, int family, int socket_type, char* host, int port) {
48− struct addrinfo hints;
49− struct addrinfo* address_res;
50− // Convert port into string
51− char str_port[8];
52− sprintf(str_port, "%d", port);
53−
54− if (!check_init()) {
55− return -1;
56− }
57− // Set up hints structure
58− memset(&hints, 0, sizeof(hints)); // zero out hints
59− hints.ai_family = family;
60− hints.ai_socktype = socket_type;
61−
62− // If the length of the hostname is 0 (i.e, it was set to Nothing in Idris)
63− // then we want to instruct the C library to fill in the IP automatically
64− if (strlen(host) == 0) {
65− hints.ai_flags = AI_PASSIVE; // fill in IP automatically
66− }
67−
68− int addr_res = getaddrinfo(host, str_port, &hints, &address_res);
69− if (addr_res == -1) {
70− return -1;
71− }
72−
73− int bind_res = bind(sockfd, address_res->ai_addr, address_res->ai_addrlen);
74− if (bind_res == -1) {
75− return -1;
76− }
77−
78− return 0;
79−}
80−
81−int idrnet_connect(int sockfd, int family, int socket_type, char* host, int port) {
82− char str_port[8];
83− sprintf(str_port, "%d", port);
84− struct addrinfo hints;
85− struct addrinfo* remote_host;
86−
87− if (!check_init()) {
88− return -1;
89− }
90− // Set up hints structure for getaddrinfo
91− memset(&hints, 0, sizeof(hints));
92− hints.ai_family = family;
93− hints.ai_socktype = socket_type;
94−
95− // Get info about the remote host (DNS lookup etc)
96− int addr_res = getaddrinfo(host, str_port, &hints, &remote_host);
97− if (addr_res != 0) {
98− return -1;
99− }
100−
101− int connect_res = connect(sockfd, remote_host->ai_addr, remote_host->ai_addrlen);
102− if (connect_res == -1) {
103− return -1;
104− }
105−
106− return 0;
107−}
108−
109−
110−int idrnet_sockaddr_family(void* sockaddr) {
111− struct sockaddr* addr = (struct sockaddr*) sockaddr;
112− return (int) addr->sa_family;
113−}
114−
115−char* idrnet_sockaddr_ipv4(void* sockaddr) {
116− struct sockaddr_in* addr = (struct sockaddr_in*) sockaddr;
117− char* ip_addr = (char*) malloc(sizeof(char) * INET_ADDRSTRLEN);
118− InetNtopA(AF_INET, &(addr->sin_addr), ip_addr, INET_ADDRSTRLEN);
119− return ip_addr;
120−}
121−
122−void* idrnet_create_sockaddr() {
123− return malloc(sizeof(struct sockaddr_storage));
124−}
125−
126−
127−int idrnet_accept(int sockfd, void* sockaddr) {
128− struct sockaddr* addr = (struct sockaddr*) sockaddr;
129− socklen_t addr_size = 0;
130− if (!check_init()) {
131− return -1;
132− }
133− return accept(sockfd, addr, &addr_size);
134−}
135−
136−int idrnet_send(int sockfd, char* data) {
137− int len = strlen(data); // For now.
138− if (!check_init()) {
139− return -1;
140− }
141− return send(sockfd, (void*) data, len, 0);
142−}
143−
144−int idrnet_send_buf(int sockfd, void* data, int len) {
145− if (!check_init()) {
146− return -1;
147− }
148− return send(sockfd, data, len, 0);
149−}
150−
151−void* idrnet_recv(int sockfd, int len) {
152− if (!check_init()) {
153− return NULL;
154− }
155− idrnet_recv_result* res_struct =
156− (idrnet_recv_result*) malloc(sizeof(idrnet_recv_result));
157−
158− char* buf = malloc(len + 1);
159− int recv_res = recv(sockfd, buf, len, 0);
160− res_struct->result = recv_res;
161−
162− if (recv_res > 0) { // Data was received
163− buf[recv_res + 1] = 0x00; // Null-term, so Idris can interpret it
164− }
165− res_struct->payload = (void*) buf;
166− return (void*) res_struct;
167−}
168−
169−int idrnet_recv_buf(int sockfd, void* buf, int len) {
170− if (!check_init()) {
171− return -1;
172− }
173− return recv(sockfd, buf, len, 0);
174−}
175−
176−int idrnet_get_recv_res(void* res_struct) {
177− return (((idrnet_recv_result*) res_struct)->result);
178−}
179−
180−char* idrnet_get_recv_payload(void* res_struct) {
181− return (((idrnet_recv_result*) res_struct)->payload);
182−}
183−
184−void idrnet_free_recv_struct(void* res_struct) {
185− idrnet_recv_result* i_res_struct =
186− (idrnet_recv_result*) res_struct;
187− if (i_res_struct->payload != NULL) {
188− free(i_res_struct->payload);
189− }
190− free(res_struct);
191−}
192−
193−int idrnet_errno() {
194− return errno;
195−}
196−
197−int idrnet_geteagain() {
198− return EAGAIN;
199−}
200−