From 36b2e37bda62bb6595096068e168061ed86f4c28 Mon Sep 17 00:00:00 2001 From: SpookyDervish Date: Thu, 9 Jul 2026 21:56:09 +1000 Subject: [PATCH] minimal working version going --- rock.json | 4 +- src/main.c | 10 +-- src/socket.c | 124 +++++++++++++++++++++++++++++++++++++ src/socket.h | 14 +++++ src/socket_enums.c | 151 +++++++++++++++++++++++++++++++++++++++++++++ src/socket_enums.h | 12 ++++ test.comet | 16 +++++ test.py | 4 ++ 8 files changed, 325 insertions(+), 10 deletions(-) create mode 100644 src/socket.c create mode 100644 src/socket.h create mode 100644 src/socket_enums.c create mode 100644 src/socket_enums.h create mode 100644 test.comet create mode 100644 test.py diff --git a/rock.json b/rock.json index 53e695a..03d22f2 100644 --- a/rock.json +++ b/rock.json @@ -1,10 +1,10 @@ { "configVersion": 1, "rock": { - "name": "template", + "name": "socket", "version": "0.0.1", "gccArgs": [], - "description": "Your description here", + "description": "Socket implementation in Comet.", "dependencies": {}, "nativeComet": false } diff --git a/src/main.c b/src/main.c index f38805d..e12a8ee 100644 --- a/src/main.c +++ b/src/main.c @@ -1,12 +1,6 @@ #include -#include +#include "socket.h" on_import { - /* - This is where you define all your functions and structs. - - The on_import function is called by the compiler so you can let - it know about all your symbols you want to expose. - */ - printf("We've been imported!\n") + defineSocketStruct(env, typeMap); } \ No newline at end of file diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..6df66e9 --- /dev/null +++ b/src/socket.c @@ -0,0 +1,124 @@ +#include "socket.h" + +ResultType(int64_t, objectPtr) impl_Socket_INIT(int64_t* args, CometVM* vm) { + + CometObject* self = (CometObject*)args[0]; + + int family = mapLanguageFamilyToOS(cometArgInt(args[1])); + int type = mapLanguageTypeToOS(cometArgInt(args[2])); + + int fd = socket( + family, + type, + cometArgInt(args[3]) + ); + + if (fd < 0) { + return cometError(vm, "SocketError", "Failed to create socket"); + } + + self->fields[0] = fd; + self->fields[1] = family; + + return Success(int64_t, objectPtr, (int64_t)self); +} + +ResultType(int64_t, objectPtr) impl_connect(int64_t* args, CometVM* vm) { + char* ip = cometArgString(args[0]); + int port = cometArgInt(args[1]); + CometObject* self = (CometObject*)args[2]; + + int fd = self->fields[0]; + int family = self->fields[1]; + + // create the address struct + struct sockaddr_in address; + + inet_pton(family, ip, &address.sin_addr.s_addr); + address.sin_family = family; + address.sin_port = htons(port); + + // then connect + int result = connect(fd, (struct sockaddr*)&address, sizeof(address)); + + if (result != 0) { + char* errMsg = strerror(errno); + return cometError(vm, "SocketError", errMsg); + } + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_recv(int64_t* args, CometVM* vm) { + int amount = cometArgInt(args[0]); + CometObject* self = (CometObject*)args[1]; + + int fd = self->fields[0]; + + char* buffer = malloc(amount + 1); + if (!buffer) + return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for buffer (recv)"); + + ssize_t amountReceived = recv(fd, buffer, amount, 0); + if (amountReceived > 0) { + buffer[amountReceived] = 0; + } else { // connection closed by peer + char* errMsg = strerror(errno); + close(fd); + free(buffer); + return cometError(vm, "SocketError", errMsg); + } + + int64_t serializedString = cometSerializeString(buffer); + free(buffer); + return Success(int64_t, objectPtr, serializedString); +} + +ResultType(int64_t, objectPtr) impl_send(int64_t* args, CometVM* vm) { + char* buffer = cometArgString(args[0]); + CometObject* self = (CometObject*)args[1]; + + int fd = self->fields[0]; + + ssize_t bytesSent = send(fd, buffer, strlen(buffer), MSG_NOSIGNAL); + if (bytesSent < 0) { + char* errMsg = strerror(errno); + return cometError(vm, "SocketError", errMsg); + } + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_close(int64_t* args, CometVM* vm) { + CometObject* self = (CometObject*)args[0]; + + int fd = self->fields[0]; + + int result = close(fd); + if (result < 0) { + char* errMsg = strerror(errno); + return cometError(vm, "IOError", errMsg); + } + + return Success(int64_t, objectPtr, 0); +} + +void defineSocketStruct(CometEnvironment* env, CometTypeMap* typeMap) { + CometType familyEnum = defineFamilyEnum(env, typeMap); + CometType typeEnum = defineTypeEnum(env, typeMap); + + CometStruct* socketStruct = cometDefineStruct(env, "Socket", NULL); + + List(StructField) fields = newList(StructField); + append(fields, cometCreateField("fd", cometTypeInt, FIELD_PRIVATE)); + append(fields, cometCreateField("family", cometTypeSmall, FIELD_READ_ONLY)); + + List(externalMethodPtr) methods = newList(externalMethodPtr); + append(methods, cometDefineMethod(env, "connect", socketStruct, FIELD_PUBLIC, cometTypeVoid, 2, false, cometTypeString, cometTypeInt)); + append(methods, cometDefineMethod(env, "recv", socketStruct, FIELD_PUBLIC, cometTypeString, 1, false, cometTypeInt)); + append(methods, cometDefineMethod(env, "send", socketStruct, FIELD_PUBLIC, cometTypeVoid, 1, false, cometTypeString)); + append(methods, cometDefineMethod(env, "close", socketStruct, FIELD_PUBLIC, cometTypeVoid, 0, false)); + + cometSetStructFieldsAndMethods(socketStruct, fields, methods); + cometDefineConstructor(env, socketStruct, 3, false, familyEnum, typeEnum, cometTypeInt); +} \ No newline at end of file diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..75adce9 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,14 @@ +#ifndef SOCKET_H +#define SOCKET_H + +#include +#include +#include +#include +#include +#include +#include "socket_enums.h" + +void defineSocketStruct(CometEnvironment* env, CometTypeMap* typeMap); + +#endif \ No newline at end of file diff --git a/src/socket_enums.c b/src/socket_enums.c new file mode 100644 index 0000000..08149a7 --- /dev/null +++ b/src/socket_enums.c @@ -0,0 +1,151 @@ +#include "socket_enums.h" + +CometType defineFamilyEnum(CometEnvironment* env, CometTypeMap* typeMap) { + char* items[] = { + "UNSPEC", + "LOCAL", + "INET", + "AX25", + "IPX", + "APPLETALK", + "NETROM", + "BRIDGE", + "ATMPVC", + "X25", + "INET6", + "ROSE", + "DECnet", + "NETBEUI", + "SECURITY", + "KEY", + "NETLINK", + "PACKET", + "ASH", + "ECONET", + "ATMSVC", + "RDS", + "SNA", + "IRDA", + "PPPOX", + "WANPIPE", + "LLC", + "IB", + "MPLS", + "CAN", + "TIPC", + "BLUETOOTH", + "IUCV", + "RXRPC", + "ISDN", + "PHONET", + "IEEE802154", + "CAIF", + "ALG", + "NFC", + "VSOCK", + "KCM", + "QIPCRTR", + "SMC", + "XDP", + "MCTP", + "MAX" + }; + + CometType domainEnum = cometDefineEnum(env, typeMap, "Family", items, sizeof(items)/sizeof(items[0])); + + return domainEnum; +} + +CometType defineTypeEnum(CometEnvironment* env, CometTypeMap* typeMap) { + char* items[] = { + "STREAM", + "DGRAM", + "RAW", + "RDM", + "SEQPACKET", + "DCCP", + "PACKET", + "CLOEXEC", + "NONBLOCK" + }; + + CometType domainEnum = cometDefineEnum(env, typeMap, "Type", items, sizeof(items)/sizeof(items[0])); + + return domainEnum; +} + +int mapLanguageTypeToOS(int cometType) { + /* + ughhhh... + */ + + switch (cometType) { + case 0: return SOCK_STREAM; + case 1: return SOCK_DGRAM; + case 2: return SOCK_RAW; + case 3: return SOCK_RDM; + case 4: return SOCK_SEQPACKET; + case 5: return SOCK_DCCP; + case 6: return SOCK_PACKET; + case 7: return SOCK_CLOEXEC; + case 8: return SOCK_NONBLOCK; + default: return -1; + } +} + +int mapLanguageFamilyToOS(int cometFamily) { + /* + why does every os have different mappings for this stuff... + */ + + switch (cometFamily) { + case 0: return AF_UNSPEC; + case 1: return AF_LOCAL; + case 2: return AF_INET; + case 3: return AF_AX25; + case 4: return AF_IPX; + case 5: return AF_APPLETALK; + case 6: return AF_NETROM; + case 7: return AF_BRIDGE; + case 8: return AF_ATMPVC; + case 9: return AF_X25; + case 10: return AF_INET6; + case 11: return AF_ROSE; + case 12: return AF_DECnet; + case 13: return AF_NETBEUI; + case 14: return AF_SECURITY; + case 15: return AF_KEY; + case 16: return AF_NETLINK; + case 17: return AF_PACKET; + case 18: return AF_ASH; + case 19: return AF_ECONET; + case 20: return AF_ATMSVC; + case 21: return AF_RDS; + case 22: return AF_SNA; + case 23: return AF_IRDA; + case 24: return AF_PPPOX; + case 25: return AF_WANPIPE; + case 26: return AF_LLC; + case 27: return AF_IB; + case 28: return AF_MPLS; + case 29: return AF_CAN; + case 30: return AF_TIPC; + case 31: return AF_BLUETOOTH; + case 32: return AF_IUCV; + case 33: return AF_RXRPC; + case 34: return AF_ISDN; + case 35: return AF_PHONET; + case 36: return AF_IEEE802154; + case 37: return AF_CAIF; + case 38: return AF_ALG; + case 39: return AF_NFC; + case 40: return AF_VSOCK; + case 41: return AF_KCM; + case 42: return AF_QIPCRTR; + case 43: return AF_SMC; + case 44: return AF_XDP; + case 45: return AF_MCTP; + case 46: return AF_MAX; + default: return -1; + } +} \ No newline at end of file diff --git a/src/socket_enums.h b/src/socket_enums.h new file mode 100644 index 0000000..3001d59 --- /dev/null +++ b/src/socket_enums.h @@ -0,0 +1,12 @@ +#ifndef SOCKET_ENUMS_H +#define SOCKET_ENUMS_H + +#include +#include + +CometType defineFamilyEnum(CometEnvironment* env, CometTypeMap* typeMap); +CometType defineTypeEnum(CometEnvironment* env, CometTypeMap* typeMap); +int mapLanguageFamilyToOS(int cometFamily); +int mapLanguageTypeToOS(int cometFamily); + +#endif \ No newline at end of file diff --git a/test.comet b/test.comet new file mode 100644 index 0000000..440569c --- /dev/null +++ b/test.comet @@ -0,0 +1,16 @@ +import socket +import io + +func main() -> int { + socket.Socket s = new socket.Socket(socket.Family.INET, socket.Type.STREAM, 0) + + s.connect("142.250.188.46", 80) + s.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n") + + string response = s.recv(1024) + io.println("Response: %s", response) + + s.close() + + return 0 +} \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..7fe7bd0 --- /dev/null +++ b/test.py @@ -0,0 +1,4 @@ +import socket + + +socket.socket(socket.AF_INET, socket.SOCK_STREAM) \ No newline at end of file