2 Commits
0.1.0 ... main

5 changed files with 118 additions and 22 deletions

View File

@@ -2,7 +2,7 @@
"configVersion": 1,
"rock": {
"name": "socket",
"version": "0.1.0",
"version": "0.1.1",
"gccArgs": [],
"description": "Socket implementation in Comet.",
"dependencies": {},

View File

@@ -19,18 +19,37 @@ ResultType(int64_t, objectPtr) impl_Socket_INIT(int64_t* args, CometVM* vm) {
self->fields[0] = fd;
self->fields[1] = family;
self->fields[2] = type;
return Success(int64_t, objectPtr, (int64_t)self);
}
struct sockaddr_in createIPV4Address(int family, char* ip, int port) {
struct sockaddr_in address;
typedef struct sockaddr_in SocketAddress;
inet_pton(family, ip, &address.sin_addr.s_addr);
address.sin_family = family;
address.sin_port = htons(port);
Result(SocketAddress, objectPtr);
ResultType(SocketAddress, objectPtr) createIPV4Address(CometVM* vm, int family, int type, char* host, int port) {
struct sockaddr_in address = {};
return address;
struct addrinfo hints = {};
struct addrinfo* result;
hints.ai_family = family;
hints.ai_socktype = type;
char portString[16];
snprintf(portString, sizeof(portString), "%d", port);
int status = getaddrinfo(host, portString, &hints, &result);
if (status < 0) {
char* errMsg = strerror(errno);
ResultType(int64_t, objectPtr) error = cometError(vm, "SocketError", errMsg);
return Error(SocketAddress, objectPtr, error.as.error);
}
memcpy(&address, result->ai_addr, sizeof(address));
freeaddrinfo(result);
return Success(SocketAddress, objectPtr, address);
}
ResultType(int64_t, objectPtr) impl_connect(int64_t* args, CometVM* vm) {
@@ -40,11 +59,14 @@ ResultType(int64_t, objectPtr) impl_connect(int64_t* args, CometVM* vm) {
int fd = self->fields[0];
int family = self->fields[1];
int type = self->fields[2];
struct sockaddr_in address = createIPV4Address(family, ip, port);
ResultType(SocketAddress, objectPtr) address = createIPV4Address(vm, family, type, ip, port);
if (address.error)
return Error(int64_t, objectPtr, address.as.error);
// then connect
int result = connect(fd, (struct sockaddr*)&address, sizeof(address));
int result = connect(fd, (struct sockaddr*)&address.as.success, sizeof(address));
if (result != 0) {
char* errMsg = strerror(errno);
@@ -61,11 +83,13 @@ ResultType(int64_t, objectPtr) impl_bind(int64_t* args, CometVM* vm) {
int fd = self->fields[0];
int family = self->fields[1];
int type = self->fields[2];
struct sockaddr_in address = createIPV4Address(family, ip, port);
ResultType(SocketAddress, objectPtr) address = createIPV4Address(vm, family, type, ip, port);
if (address.error)
return Error(int64_t, objectPtr, address.as.error);
int result = bind(fd, (struct sockaddr*)&address, sizeof(address));
int result = bind(fd, (struct sockaddr*)&address.as.success, sizeof(address));
if (result != 0) {
char* errMsg = strerror(errno);
return cometError(vm, "SocketError", errMsg);
@@ -107,7 +131,9 @@ ResultType(int64_t, objectPtr) impl_accept(int64_t* args, CometVM* vm) {
CometObject* clientCometSocket = cometCreateObject(socketStruct);
clientCometSocket->fields[0] = clientSocket;
clientCometSocket->fields[1] = clientAddr.sin_port;
clientCometSocket->fields[1] = self->fields[1];
clientCometSocket->fields[2] = self->fields[2];
clientCometSocket->fields[3] = clientAddr.sin_port;
return Success(int64_t, objectPtr, (int64_t)clientCometSocket);
}
@@ -148,17 +174,22 @@ ResultType(int64_t, objectPtr) impl_readExact(int64_t* args, CometVM* vm) {
return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for buffer (readExact)");
ssize_t amountReceived = recv(fd, buffer, amount, 0);
if (amountReceived != amount) {
char* buffer = malloc(128);
snprintf(buffer, 128, "Expected to read %d bytes but only got %zu", amount, amountReceived);
return cometError(vm, "UnexpectedEOF", buffer);
} else if (amountReceived == -1) { // connection closed by peer
if (amountReceived < 0) { // connection closed by peer
char* errMsg = strerror(errno);
close(fd);
free(buffer);
return cometError(vm, "SocketError", errMsg);
}
if (amountReceived != amount) {
char* buffer = malloc(128);
snprintf(buffer, 128, "Expected to read %d bytes but only got %zu", amount, amountReceived);
return cometError(vm, "UnexpectedEOF", buffer);
}
buffer[amountReceived] = 0;
int64_t serializedString = cometSerializeString(buffer);
@@ -238,7 +269,28 @@ ResultType(int64_t, objectPtr) impl_send(int64_t* args, CometVM* vm) {
return cometError(vm, "SocketError", errMsg);
}
return Success(int64_t, objectPtr, 0);
return Success(int64_t, objectPtr, bytesSent);
}
ResultType(int64_t, objectPtr) impl_sendAll(int64_t* args, CometVM* vm) {
char* buffer = cometArgString(args[0]);
CometObject* self = (CometObject*)args[1];
int fd = self->fields[0];
size_t length = strlen(buffer);
ssize_t bytesSent = 0;
while (bytesSent < length) {
bytesSent += send(fd, buffer + bytesSent, length - bytesSent, MSG_NOSIGNAL);
if (bytesSent < 0) {
char* errMsg = strerror(errno);
return cometError(vm, "SocketError", errMsg);
}
}
return Success(int64_t, objectPtr, bytesSent);
}
ResultType(int64_t, objectPtr) impl_sendByte(int64_t* args, CometVM* vm) {
@@ -262,13 +314,28 @@ 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);
}
self->fields[0] = -1;
return Success(int64_t, objectPtr, 0);
}
ResultType(int64_t, objectPtr) impl_shutdown(int64_t* args, CometVM* vm) {
int method = mapLanguageShutdownToOS(cometArgSmall(args[0]));
CometObject* self = (CometObject*)args[1];
int fd = self->fields[0];
int result = shutdown(fd, method);
if (result != 0) {
char* errMsg = strerror(errno);
return cometError(vm, "SocketError", errMsg);
}
return Success(int64_t, objectPtr, 0);
}
@@ -427,6 +494,7 @@ ResultType(int64_t, objectPtr) impl_waitWriteable(int64_t* args, CometVM* vm) {
void defineSocketStruct(CometEnvironment* env, CometTypeMap* typeMap) {
CometType familyEnum = defineFamilyEnum(env, typeMap);
CometType typeEnum = defineTypeEnum(env, typeMap);
CometType shutdownEnum = defineShutdownEnum(env, typeMap);
CometStruct* socketStruct = cometDefineStruct(env, "Socket", NULL);
@@ -438,6 +506,8 @@ void defineSocketStruct(CometEnvironment* env, CometTypeMap* typeMap) {
List(StructField) fields = newList(StructField);
append(fields, cometCreateField("fd", cometTypeInt, FIELD_PRIVATE));
append(fields, cometCreateField("family", cometTypeSmall, FIELD_READ_ONLY));
append(fields, cometCreateField("type", cometTypeSmall, FIELD_READ_ONLY));
append(fields, cometCreateField("port", cometTypeInt, FIELD_READ_ONLY));
/// METHODS ///
List(externalMethodPtr) methods = newList(externalMethodPtr);
@@ -454,8 +524,10 @@ void defineSocketStruct(CometEnvironment* env, CometTypeMap* typeMap) {
append(methods, cometDefineMethod(env, "readAll", socketStruct, FIELD_PUBLIC, cometTypeString, 0, false));
append(methods, cometDefineMethod(env, "readExact", socketStruct, FIELD_PUBLIC, cometTypeString, 1, false, cometTypeInt));
append(methods, cometDefineMethod(env, "readByte", socketStruct, FIELD_PUBLIC, cometTypeSmall, 0, false));
append(methods, cometDefineMethod(env, "send", socketStruct, FIELD_PUBLIC, cometTypeVoid, 1, false, cometTypeString));
append(methods, cometDefineMethod(env, "send", socketStruct, FIELD_PUBLIC, cometTypeInt, 1, false, cometTypeString));
append(methods, cometDefineMethod(env, "sendAll", socketStruct, FIELD_PUBLIC, cometTypeVoid, 1, false, cometTypeString));
append(methods, cometDefineMethod(env, "sendByte", socketStruct, FIELD_PUBLIC, cometTypeVoid, 1, false, cometTypeSmall));
append(methods, cometDefineMethod(env, "shutdown", socketStruct, FIELD_PUBLIC, cometTypeVoid, 1, false, shutdownEnum));
append(methods, cometDefineMethod(env, "close", socketStruct, FIELD_PUBLIC, cometTypeVoid, 0, false));
// options

View File

@@ -7,6 +7,7 @@
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

View File

@@ -74,6 +74,18 @@ CometType defineTypeEnum(CometEnvironment* env, CometTypeMap* typeMap) {
return domainEnum;
}
CometType defineShutdownEnum(CometEnvironment* env, CometTypeMap* typeMap) {
char* items[] = {
"Read",
"Write",
"ReadWrite"
};
CometType shutdownEnum = cometDefineEnum(env, typeMap, "Shutdown", items, sizeof(items)/sizeof(items[0]));
return shutdownEnum;
}
int mapLanguageTypeToOS(int cometType) {
/*
ughhhh...
@@ -149,3 +161,12 @@ int mapLanguageFamilyToOS(int cometFamily) {
default: return -1;
}
}
int mapLanguageShutdownToOS(int cometShutdown) {
switch (cometShutdown) {
case 0: return SHUT_RD;
case 1: return SHUT_WR;
case 2: return SHUT_RDWR;
default: return -1;
}
}

View File

@@ -6,7 +6,9 @@
CometType defineFamilyEnum(CometEnvironment* env, CometTypeMap* typeMap);
CometType defineTypeEnum(CometEnvironment* env, CometTypeMap* typeMap);
CometType defineShutdownEnum(CometEnvironment* env, CometTypeMap* typeMap);
int mapLanguageFamilyToOS(int cometFamily);
int mapLanguageTypeToOS(int cometFamily);
int mapLanguageShutdownToOS(int cometShutdown);
#endif