generated from Comet/Comet-C-External-Lib
bug fixes, added shutdown method, resolve hostnames as well as ips
This commit is contained in:
112
src/socket.c
112
src/socket.c
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user