From 57c0d7c910faf15bec5d5538fe3af3096fcb7474 Mon Sep 17 00:00:00 2001 From: cozis Date: Sat, 4 Dec 2021 15:22:10 +0100 Subject: [PATCH] added some other network builtins --- build.sh | 6 +- samples/client.noja | 26 ++ samples/server.noja | 38 +++ samples/socket.noja | 29 +- src/o_builtins.c | 4 +- src/o_net_builtins.c | 673 +++++++++++++++++++++++++++++++++++++++ src/o_network_builtins.c | 218 ------------- 7 files changed, 766 insertions(+), 228 deletions(-) create mode 100644 samples/client.noja create mode 100644 samples/server.noja create mode 100644 src/o_net_builtins.c delete mode 100644 src/o_network_builtins.c diff --git a/build.sh b/build.sh index 958ddd4..23564ae 100755 --- a/build.sh +++ b/build.sh @@ -40,8 +40,8 @@ gcc -c src/runtime/runtime.c -o temp/runtime/runtime.o $FLAGS gcc -c src/runtime/o_nfunc.c -o temp/runtime/o_nfunc.o $FLAGS gcc -c src/runtime/o_func.c -o temp/runtime/o_func.o $FLAGS -gcc -c src/o_builtins.c -o temp/o_builtins.o $FLAGS -gcc -c src/o_network_builtins.c -o temp/o_network_builtins.o $FLAGS +gcc -c src/o_builtins.c -o temp/o_builtins.o $FLAGS +gcc -c src/o_net_builtins.c -o temp/o_net_builtins.o $FLAGS rm -rf build mkdir build @@ -74,7 +74,7 @@ gcc tests/src/test-objects.c -o build/test-objects $FLAGS -Lbuild/ -lnoja-object gcc src/main.c \ src/debug.c \ temp/o_builtins.o \ - temp/o_network_builtins.o \ + temp/o_net_builtins.o \ temp/utils/hash.o \ temp/utils/stack.o \ temp/utils/source.o \ diff --git a/samples/client.noja b/samples/client.noja new file mode 100644 index 0000000..241aec1 --- /dev/null +++ b/samples/client.noja @@ -0,0 +1,26 @@ + +port = 8080; +addr = "127.0.0.1"; + +fd = net.socket(net.AF_INET, net.SOCK_STREAM, 0); + +if fd < 0: + { + print('Failed to create socket.\n'); + return none; + } + +sin_addr = {}; +if net.inet_aton(addr, sin_addr) == 0: + { + print('Bad address string format.\n'); + return none; + } + +if net.connect(fd, { sin_family: net.AF_INET, sin_port: net.htons(port), sin_addr: sin_addr }) != 0: + { + print('Failed to connect.\n'); + return none; + } + +print('Connected!\n'); \ No newline at end of file diff --git a/samples/server.noja b/samples/server.noja new file mode 100644 index 0000000..c4c8aac --- /dev/null +++ b/samples/server.noja @@ -0,0 +1,38 @@ + +port = 8080; +backlog = 5; + +fd = net.socket(net.AF_INET, net.SOCK_STREAM, 0); + +if fd < 0: + { + print('Failed to create socket.\n'); + return none; + } + +if net.bind(fd, {sin_family: net.AF_INET, sin_port: net.htons(port), sin_addr: {s_addr: net.htonl(net.INADDR_ANY)}}) != 0: + { + print('Failed to bind.\n'); + return none; + } + +if net.listen(fd, backlog) != 0: + { + print('Failed to listen.\n'); + return none; + } + +while true: + { + client_addr = {}; + client_fd = net.accept(fd, client_addr); + + if client_fd < 0: + print('Warning! Failed to accept!\n'); + + print('Got a connection!\n'); + print('client_fd = ', client_fd, '\n'); + print('client_addr = {', client_addr, '}\n'); + + # ..continue.. + } \ No newline at end of file diff --git a/samples/socket.noja b/samples/socket.noja index f0ed191..36d9295 100644 --- a/samples/socket.noja +++ b/samples/socket.noja @@ -1,9 +1,28 @@ -print('test 0\n'); +addr = "216.58.208.142"; +port = 80; -print('SOCK_STREAM = ', network.SOCK_STREAM, ';\n'); +fd = net.socket(net.AF_INET, net.SOCK_STREAM, 0); -print('test 1\n'); +if fd < 0: + { + print('Failed to create socket\n'); + return none; + } -fd = network.socket(network.AF_INET, network.SOCK_STREAM, 0); -print(fd); \ No newline at end of file +in_addr = {}; +if net.inet_aton(addr, in_addr) == 0: + { + print('Bad address string format\n'); + return none; + } + +r = net.connect(fd, {sin_family: net.AF_INET, sin_port: net.htons(port), sin_addr: in_addr}); + +if r < 0: + { + print('Failed to connect\n'); + return none; + } + +print('Connected!\n'); \ No newline at end of file diff --git a/src/o_builtins.c b/src/o_builtins.c index 6ee1c6c..28d4fc8 100644 --- a/src/o_builtins.c +++ b/src/o_builtins.c @@ -79,9 +79,9 @@ static Object *select_(Object *self, Object *key, Heap *heap, Error *err) return NULL; } - case PAIR(sizeof("network")-1, 'n'): + case PAIR(sizeof("net")-1, 'n'): { - if(!strcmp(s, "network")) + if(!strcmp(s, "net")) return Object_NewNetworkBuiltinsMap(bm->runtime, heap, err); return NULL; diff --git a/src/o_net_builtins.c b/src/o_net_builtins.c new file mode 100644 index 0000000..12f3972 --- /dev/null +++ b/src/o_net_builtins.c @@ -0,0 +1,673 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "runtime/runtime.h" +#include "utils/defs.h" + +static Object *select_(Object *self, Object *key, Heap *heap, Error *err); + +static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error); + + +typedef struct { + Object base; + Runtime *runtime; +} NetworkBuiltinsMapOjbect; + +static const Type t_builtins_map = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "network builtins map", + .size = sizeof(NetworkBuiltinsMapOjbect), + .select = select_, +}; + +static Object *select_(Object *self, Object *key, Heap *heap, Error *err) +{ + NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) self; + + if(!Object_IsString(key)) + { + Error_Report(err, 0, "Non string key"); + return NULL; + } + + int n; + const char *s; + + s = Object_ToString(key, &n, heap, err); + + if(s == NULL) + return NULL; + + #define PAIR(p, q) \ + (((uint64_t) (p) << 32) | (uint32_t) (q)) + + switch(PAIR(n, s[0])) + { + case PAIR(10, 'I'): + { + if(!strcmp(s, "INADDR_ANY")) + return Object_FromInt(INADDR_ANY, heap, err); + + return NULL; + } + + case PAIR(6, 'a'): + { + if(!strcmp(s, "accept")) + return Object_FromNativeFunction(bm->runtime, bin_accept, 2, heap, err); + + return NULL; + } + + case PAIR(4, 'b'): + { + if(!strcmp(s, "bind")) + return Object_FromNativeFunction(bm->runtime, bin_bind, 2, heap, err); + + return NULL; + } + + case PAIR(6, 'l'): + { + if(!strcmp(s, "listen")) + return Object_FromNativeFunction(bm->runtime, bin_listen, 2, heap, err); + + return NULL; + } + + case PAIR(5, 'n'): + { + if(!strcmp(s, "ntohl")) + return Object_FromNativeFunction(bm->runtime, bin_ntohl, 1, heap, err); + + if(!strcmp(s, "ntohs")) + return Object_FromNativeFunction(bm->runtime, bin_ntohs, 1, heap, err); + + return NULL; + } + + case PAIR(5, 'h'): + { + if(!strcmp(s, "htonl")) + return Object_FromNativeFunction(bm->runtime, bin_htonl, 1, heap, err); + + if(!strcmp(s, "htons")) + return Object_FromNativeFunction(bm->runtime, bin_htons, 1, heap, err); + + return NULL; + } + + case PAIR(9, 'i'): + { + if(!strcmp(s, "inet_aton")) + return Object_FromNativeFunction(bm->runtime, bin_inet_aton, 2, heap, err); + return NULL; + } + + case PAIR(6, 's'): + { + if(!strcmp(s, "socket")) + return Object_FromNativeFunction(bm->runtime, bin_socket, 3, heap, err); + return NULL; + } + + case PAIR(7, 'c'): + { + if(!strcmp(s, "connect")) + return Object_FromNativeFunction(bm->runtime, bin_connect, 2, heap, err); + return NULL; + } + + case PAIR(8, 'S'): + { + if(!strcmp(s, "SOCK_RAW")) + return Object_FromInt(SOCK_RAW, heap, err); + + if(!strcmp(s, "SOCK_RDM")) + return Object_FromInt(SOCK_RDM, heap, err); + + return NULL; + } + + case PAIR(10, 'S'): + { + if(!strcmp(s, "SOCK_DGRAM")) + return Object_FromInt(SOCK_DGRAM, heap, err); + + return NULL; + } + + case PAIR(11, 'S'): + { + if(!strcmp(s, "SOCK_STREAM")) + return Object_FromInt(SOCK_STREAM, heap, err); + + if(!strcmp(s, "SOCK_PACKET")) + return Object_FromInt(SOCK_PACKET, heap, err); + + return NULL; + } + + case PAIR(12, 'S'): + { + if(!strcmp(s, "SOCK_CLOEXEC")) + return Object_FromInt(SOCK_CLOEXEC, heap, err); + + return NULL; + } + + case PAIR(13, 'S'): + { + if(!strcmp(s, "SOCK_NONBLOCK")) + return Object_FromInt(SOCK_NONBLOCK, heap, err); + + return NULL; + } + + case PAIR(14, 'S'): + { + if(!strcmp(s, "SOCK_SEQPACKET")) + return Object_FromInt(SOCK_SEQPACKET, heap, err); + + return NULL; + } + + case PAIR(5, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "IB")) + return Object_FromInt(AF_IB, heap, err); + } + return NULL; + } + + case PAIR(6, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "IPX")) + return Object_FromInt(AF_IPX, heap, err); + + if(!strcmp(s+3, "X25")) + return Object_FromInt(AF_X25, heap, err); + + if(!strcmp(s+3, "KEY")) + return Object_FromInt(AF_KEY, heap, err); + + if(!strcmp(s+3, "RDS")) + return Object_FromInt(AF_RDS, heap, err); + + if(!strcmp(s+3, "LLC")) + return Object_FromInt(AF_LLC, heap, err); + + if(!strcmp(s+3, "CAN")) + return Object_FromInt(AF_CAN, heap, err); + + if(!strcmp(s+3, "ALG")) + return Object_FromInt(AF_ALG, heap, err); + + if(!strcmp(s+3, "KCM")) + return Object_FromInt(AF_KCM, heap, err); + + if(!strcmp(s+3, "XDP")) + return Object_FromInt(AF_XDP, heap, err); + } + return NULL; + } + + case PAIR(7, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "UNIX")) + return Object_FromInt(AF_UNIX, heap, err); + + if(!strcmp(s+3, "INET")) + return Object_FromInt(AF_INET, heap, err); + + if(!strcmp(s+3, "AX25")) + return Object_FromInt(AF_AX25, heap, err); + + if(!strcmp(s+3, "MPLS")) + return Object_FromInt(AF_MPLS, heap, err); + + if(!strcmp(s+3, "TIPC")) + return Object_FromInt(AF_TIPC, heap, err); + } + return NULL; + } + + case PAIR(8, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "LOCAL")) + return Object_FromInt(AF_LOCAL, heap, err); + + if(!strcmp(s+3, "INET6")) + return Object_FromInt(AF_INET6, heap, err); + + if(!strcmp(s+3, "PPPOX")) + return Object_FromInt(AF_PPPOX, heap, err); + + if(!strcmp(s+3, "VSOCK")) + return Object_FromInt(AF_VSOCK, heap, err); + } + return NULL; + } + + case PAIR(9, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "DECnet")) + return Object_FromInt(AF_DECnet, heap, err); + + if(!strcmp(s+3, "PACKET")) + return Object_FromInt(AF_PACKET, heap, err); + } + return NULL; + } + + case PAIR(10, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "NETLINK")) + return Object_FromInt(AF_NETLINK, heap, err); + } + return NULL; + } + + case PAIR(12, 'A'): + { + if(s[1] == 'F' && s[2] == '_') + { + if(!strcmp(s+3, "BLUETOOTH")) + return Object_FromInt(AF_BLUETOOTH, heap, err); + + if(!strcmp(s+3, "APPLETALK")) + return Object_FromInt(AF_APPLETALK, heap, err); + } + return NULL; + } + } + + // Not found. + return NULL; +} + +Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err) +{ + NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err); + + if(bm == NULL) + return NULL; + + bm->runtime = runtime; + + return (Object*) bm; +} + +static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 3); + + int domain, type, protocol; + + domain = Object_ToInt(argv[0], error); + if(error->occurred == 1) return NULL; + + type = Object_ToInt(argv[1], error); + if(error->occurred == 1) return NULL; + + protocol = Object_ToInt(argv[2], error); + if(error->occurred == 1) return NULL; + + int fd = socket(domain, type, protocol); + + return Object_FromInt(fd, Runtime_GetHeap(runtime), error); +} + + +static _Bool get_in_addr_from_map(Object *map, struct in_addr *addr, Heap *heap, Error *error) +{ + Object *o_key = Object_FromString("s_addr", -1, heap, error); + if(o_key == NULL) return 0; + + Object *o_s_addr = Object_Select(map, o_key, heap, error); + if(o_s_addr == NULL) + { + if(error->occurred == 0) + Error_Report(error, 0, "Missing the \"s_addr\" key"); + return 0; + } + + long long int s_addr = Object_ToInt(o_s_addr, error); + if(error->occurred) return 0; + + if(s_addr < 0 || s_addr >= ULONG_MAX) + { + Error_Report(error, 0, "s_addr must be in range [0, %lu]", ULONG_MAX); + return 0; + } + + if(addr) + addr->s_addr = s_addr; + + return 1; +} + +static _Bool get_sockaddr_in_from_map(Object *map, struct sockaddr_in *addr, Heap *heap, Error *error) +{ + Object *o_key = Object_FromString("sin_family", -1, heap, error); + if(o_key == NULL) return 0; + + Object *o_sin_family = Object_Select(map, o_key, heap, error); + if(o_sin_family == NULL) + { + if(error->occurred == 0) + Error_Report(error, 0, "Argument 2 is missing the \"sin_family\" key"); + return 0; + } + + long long int sin_family = Object_ToInt(o_sin_family, error); + if(error->occurred) return 0; + + if(sin_family < 0 || sin_family >= 65536) + { + Error_Report(error, 0, "sin_family must be in range [0, 65535]"); + return 0; + } + + o_key = Object_FromString("sin_port", -1, heap, error); + if(o_key == NULL) return 0; + + Object *o_sin_port = Object_Select(map, o_key, heap, error); + if(o_sin_port == NULL) + { + if(error->occurred == 0) + Error_Report(error, 0, "Argument 2 is missing the \"sin_port\" key"); + return 0; + } + + long long int sin_port = Object_ToInt(o_sin_port, error); + if(error->occurred) return 0; + + if(sin_port < 0 || sin_port >= 65536) + { + Error_Report(error, 0, "sin_port must be in range [0, 65535]"); + return 0; + } + + o_key = Object_FromString("sin_addr", -1, heap, error); + if(o_key == NULL) return 0; + + Object *o_sin_addr = Object_Select(map, o_key, heap, error); + if(o_sin_addr == NULL) + { + if(error->occurred == 0) + Error_Report(error, 0, "Argument 2 is missing the \"sin_addr\" key"); + return 0; + } + + struct in_addr sin_addr; + + if(!get_in_addr_from_map(o_sin_addr, &sin_addr, heap, error)) + return 0; + + if(addr) + { + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = sin_family; + addr->sin_port = sin_port; + addr->sin_addr = sin_addr; + } + return 1; +} + +static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + Heap *heap = Runtime_GetHeap(runtime); + + int sockfd; + struct sockaddr_in addr; + + sockfd = Object_ToInt(argv[0], error); + if(error->occurred == 1) return NULL; + + if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error)) + return NULL; + + int r = connect(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)); + + return Object_FromInt(r, Runtime_GetHeap(runtime), error); +} + +static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + Heap *heap = Runtime_GetHeap(runtime); + + const char *s = Object_ToString(argv[0], NULL, heap, error); + if(s == NULL) return NULL; + + // Note that the string must be zero-terminated. + + struct in_addr addr; + + int r = inet_aton(s, &addr); + + if(r != 0) + { + // inet_aton succeded. + + Object *o_key = Object_FromString("s_addr", -1, heap, error); + if(o_key == NULL) return NULL; + + Object *o_val = Object_FromInt(addr.s_addr, heap, error); + if(o_val == NULL) return NULL; + + if(!Object_Insert(argv[1], o_key, o_val, heap, error)) + return NULL; + } + + return Object_FromInt(r, heap, error); +} + +static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + Heap *heap = Runtime_GetHeap(runtime); + + + uint32_t r, p; + + p = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + r = htonl(p); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + Heap *heap = Runtime_GetHeap(runtime); + + + uint32_t r, p; + + p = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + r = ntohl(p); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + Heap *heap = Runtime_GetHeap(runtime); + + int p = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + if(p < 0 || p > 65535) + { + Error_Report(error, 0, "Argument is not in range [0, 65535]"); + return NULL; + } + + uint16_t r = ntohs(p); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + Heap *heap = Runtime_GetHeap(runtime); + + int p = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + if(p < 0 || p > 65535) + { + Error_Report(error, 0, "Argument is not in range [0, 65535]"); + return NULL; + } + + uint16_t r = htons(p); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + Heap *heap = Runtime_GetHeap(runtime); + + int sockfd; + struct sockaddr_in addr; + + sockfd = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error)) + return 0; + + int r = bind(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + Heap *heap = Runtime_GetHeap(runtime); + + int sockfd, backlog; + + sockfd = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + backlog = Object_ToInt(argv[1], error); + if(error->occurred) return NULL; + + int r = listen(sockfd, backlog); + + return Object_FromInt(r, heap, error); +} + +static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + Heap *heap = Runtime_GetHeap(runtime); + + int sockfd = Object_ToInt(argv[0], error); + if(error->occurred) return NULL; + + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + int r = accept(sockfd, (struct sockaddr*) &addr, &len); + + if(r >= 0) { + + // accept succeded. + + Object *o_key, + *o_sin_family, + *o_sin_addr, + *o_sin_port, + *o_s_addr; + + o_sin_family = Object_FromInt(addr.sin_family, heap, error); + if(error->occurred) return NULL; + + o_sin_port = Object_FromInt(addr.sin_port, heap, error); + if(error->occurred) return NULL; + + o_sin_addr = Object_NewMap(1, heap, error); + if(error->occurred) return NULL; + + o_s_addr = Object_FromInt(addr.sin_addr.s_addr, heap, error); + if(error->occurred) return NULL; + + o_key = Object_FromString("s_addr", -1, heap, error); + if(error->occurred) return NULL; + + if(!Object_Insert(o_sin_addr, o_key, o_s_addr, heap, error)) + return NULL; + + o_key = Object_FromString("sin_family", -1, heap, error); + if(error->occurred) return NULL; + + if(!Object_Insert(argv[1], o_key, o_sin_family, heap, error)) + return NULL; + + o_key = Object_FromString("sin_port", -1, heap, error); + if(error->occurred) return NULL; + + if(!Object_Insert(argv[1], o_key, o_sin_port, heap, error)) + return NULL; + + o_key = Object_FromString("sin_addr", -1, heap, error); + if(error->occurred) return NULL; + + if(!Object_Insert(argv[1], o_key, o_sin_addr, heap, error)) + return NULL; + } + + return Object_FromInt(r, heap, error); +} \ No newline at end of file diff --git a/src/o_network_builtins.c b/src/o_network_builtins.c deleted file mode 100644 index 5b35596..0000000 --- a/src/o_network_builtins.c +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "runtime/runtime.h" -#include "utils/defs.h" - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err); - -static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error); - -typedef struct { - Object base; - Runtime *runtime; -} NetworkBuiltinsMapOjbect; - -static const Type t_builtins_map = { - .base = (Object) { .type = &t_type, .flags = Object_STATIC }, - .name = "network builtins map", - .size = sizeof(NetworkBuiltinsMapOjbect), - .select = select_, -}; - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err) -{ - NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) self; - - if(!Object_IsString(key)) - { - Error_Report(err, 0, "Non string key"); - return NULL; - } - - int n; - const char *s; - - s = Object_ToString(key, &n, heap, err); - - if(s == NULL) - return NULL; - - #define PAIR(p, q) \ - (((uint64_t) (p) << 32) | (uint32_t) (q)) - - switch(PAIR(n, s[0])) - { - case PAIR(6, 's'): - { - if(!strcmp(s, "socket")) - return Object_FromNativeFunction(bm->runtime, bin_socket, 3, heap, err); - return NULL; - } - - case PAIR(5, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "IB")) - return Object_FromInt(AF_IB, heap, err); - } - return NULL; - } - - case PAIR(6, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "IPX")) - return Object_FromInt(AF_IPX, heap, err); - - if(!strcmp(s+3, "X25")) - return Object_FromInt(AF_X25, heap, err); - - if(!strcmp(s+3, "KEY")) - return Object_FromInt(AF_KEY, heap, err); - - if(!strcmp(s+3, "RDS")) - return Object_FromInt(AF_RDS, heap, err); - - if(!strcmp(s+3, "LLC")) - return Object_FromInt(AF_LLC, heap, err); - - if(!strcmp(s+3, "CAN")) - return Object_FromInt(AF_CAN, heap, err); - - if(!strcmp(s+3, "ALG")) - return Object_FromInt(AF_ALG, heap, err); - - if(!strcmp(s+3, "KCM")) - return Object_FromInt(AF_KCM, heap, err); - - if(!strcmp(s+3, "XDP")) - return Object_FromInt(AF_XDP, heap, err); - } - return NULL; - } - - case PAIR(7, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "UNIX")) - return Object_FromInt(AF_UNIX, heap, err); - - if(!strcmp(s+3, "INET")) - return Object_FromInt(AF_INET, heap, err); - - if(!strcmp(s+3, "AX25")) - return Object_FromInt(AF_AX25, heap, err); - - if(!strcmp(s+3, "MPLS")) - return Object_FromInt(AF_MPLS, heap, err); - - if(!strcmp(s+3, "TIPC")) - return Object_FromInt(AF_TIPC, heap, err); - } - return NULL; - } - - case PAIR(8, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "LOCAL")) - return Object_FromInt(AF_LOCAL, heap, err); - - if(!strcmp(s+3, "INET6")) - return Object_FromInt(AF_INET6, heap, err); - - if(!strcmp(s+3, "PPPOX")) - return Object_FromInt(AF_PPPOX, heap, err); - - if(!strcmp(s+3, "VSOCK")) - return Object_FromInt(AF_VSOCK, heap, err); - } - return NULL; - } - - case PAIR(9, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "DECnet")) - return Object_FromInt(AF_DECnet, heap, err); - - if(!strcmp(s+3, "PACKET")) - return Object_FromInt(AF_PACKET, heap, err); - } - return NULL; - } - - case PAIR(10, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "NETLINK")) - return Object_FromInt(AF_NETLINK, heap, err); - } - return NULL; - } - - case PAIR(12, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "BLUETOOTH")) - return Object_FromInt(AF_BLUETOOTH, heap, err); - - if(!strcmp(s+3, "APPLETALK")) - return Object_FromInt(AF_APPLETALK, heap, err); - } - return NULL; - } - } - - // Not found. - return NULL; -} - -Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err) -{ - NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err); - - if(bm == NULL) - return NULL; - - bm->runtime = runtime; - - return (Object*) bm; -} - -static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 3); - - int domain, type, protocol; - - domain = Object_ToInt(argv[0], error); - if(error->occurred == 1) return NULL; - - type = Object_ToInt(argv[1], error); - if(error->occurred == 1) return NULL; - - protocol = Object_ToInt(argv[2], error); - if(error->occurred == 1) return NULL; - - int fd = socket(domain, type, protocol); - - if(fd < 0) - { - Error_Report(error, 0, "Failed to create socket (%s)", strerror(errno)); - return NULL; - } - - return Object_FromInt(fd, Runtime_GetHeap(runtime), error); -} \ No newline at end of file