#define _POSIX_C_SOURCE 200809L #include "runtime.h" #include "gc/gc.h" #include #include #include #include #include #include #include #include RavaSocket_t* rava_socket_create(void) { RavaSocket_t *sock = rava_gc_alloc(sizeof(RavaSocket_t), RAVA_GC_TYPE_SOCKET); if (!sock) return NULL; memset((char*)sock + sizeof(RavaGCHeader_t), 0, sizeof(RavaSocket_t) - sizeof(RavaGCHeader_t)); sock->socket_type = RAVA_SOCKET_TYPE_CLIENT; sock->fd = socket(AF_INET, SOCK_STREAM, 0); sock->connected = false; sock->closed = false; return sock; } RavaSocket_t* rava_socket_create_connected(const char *host, int port) { RavaSocket_t *sock = rava_socket_create(); if (!sock) return NULL; if (sock->fd < 0) return sock; if (rava_socket_connect(sock, host, port)) { sock->connected = true; } return sock; } RavaSocket_t* rava_server_socket_create(int port) { RavaSocket_t *sock = rava_gc_alloc(sizeof(RavaSocket_t), RAVA_GC_TYPE_SOCKET); if (!sock) return NULL; memset((char*)sock + sizeof(RavaGCHeader_t), 0, sizeof(RavaSocket_t) - sizeof(RavaGCHeader_t)); sock->socket_type = RAVA_SOCKET_TYPE_SERVER; sock->fd = socket(AF_INET, SOCK_STREAM, 0); sock->connected = false; sock->closed = false; if (sock->fd < 0) return sock; int opt = 1; setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(port); if (bind(sock->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { close(sock->fd); sock->fd = -1; return sock; } if (listen(sock->fd, 10) < 0) { close(sock->fd); sock->fd = -1; return sock; } return sock; } void rava_socket_destroy(RavaSocket_t *socket) { if (!socket) return; if (!socket->closed && socket->fd >= 0) { close(socket->fd); } } bool rava_socket_connect(RavaSocket_t *socket, const char *host, int port) { if (!socket || socket->fd < 0) return false; struct hostent *server = gethostbyname(host); if (!server) return false; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; memcpy(&addr.sin_addr.s_addr, server->h_addr_list[0], server->h_length); addr.sin_port = htons(port); if (connect(socket->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { return false; } socket->connected = true; return true; } RavaSocket_t* rava_server_socket_accept(RavaSocket_t *server) { if (!server || server->fd < 0 || server->socket_type != RAVA_SOCKET_TYPE_SERVER) { return NULL; } struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_fd = accept(server->fd, (struct sockaddr*)&client_addr, &client_len); if (client_fd < 0) return NULL; RavaSocket_t *client = rava_gc_alloc(sizeof(RavaSocket_t), RAVA_GC_TYPE_SOCKET); if (!client) { close(client_fd); return NULL; } memset((char*)client + sizeof(RavaGCHeader_t), 0, sizeof(RavaSocket_t) - sizeof(RavaGCHeader_t)); client->socket_type = RAVA_SOCKET_TYPE_CLIENT; client->fd = client_fd; client->connected = true; client->closed = false; return client; } RavaStream_t* rava_socket_get_input_stream(RavaSocket_t *socket) { if (!socket || socket->fd < 0) return NULL; return rava_stream_create(socket->fd, RAVA_STREAM_TYPE_INPUT); } RavaStream_t* rava_socket_get_output_stream(RavaSocket_t *socket) { if (!socket || socket->fd < 0) return NULL; return rava_stream_create(socket->fd, RAVA_STREAM_TYPE_OUTPUT); } void rava_socket_close(RavaSocket_t *socket) { if (!socket || socket->closed) return; if (socket->fd >= 0) { close(socket->fd); } socket->closed = true; socket->connected = false; } RavaStream_t* rava_stream_create(int fd, int stream_type) { RavaStream_t *stream = rava_gc_alloc(sizeof(RavaStream_t), RAVA_GC_TYPE_STREAM); if (!stream) return NULL; memset((char*)stream + sizeof(RavaGCHeader_t), 0, sizeof(RavaStream_t) - sizeof(RavaGCHeader_t)); stream->stream_type = stream_type; stream->fd = fd; stream->closed = false; return stream; } void rava_stream_destroy(RavaStream_t *stream) { (void)stream; } char* rava_stream_read(RavaStream_t *stream) { if (!stream || stream->closed || stream->fd < 0) return NULL; if (stream->stream_type != RAVA_STREAM_TYPE_INPUT) return NULL; char buffer[4096]; ssize_t bytes = read(stream->fd, buffer, sizeof(buffer) - 1); if (bytes <= 0) return NULL; buffer[bytes] = '\0'; return strdup(buffer); } int rava_stream_read_byte(RavaStream_t *stream) { if (!stream || stream->closed || stream->fd < 0) return -1; if (stream->stream_type != RAVA_STREAM_TYPE_INPUT) return -1; unsigned char byte; ssize_t bytes = read(stream->fd, &byte, 1); if (bytes <= 0) return -1; return (int)byte; } void rava_stream_write(RavaStream_t *stream, const char *data) { if (!stream || stream->closed || stream->fd < 0 || !data) return; if (stream->stream_type != RAVA_STREAM_TYPE_OUTPUT) return; ssize_t result = write(stream->fd, data, strlen(data)); (void)result; } void rava_stream_write_byte(RavaStream_t *stream, int byte) { if (!stream || stream->closed || stream->fd < 0) return; if (stream->stream_type != RAVA_STREAM_TYPE_OUTPUT) return; unsigned char b = (unsigned char)byte; ssize_t result = write(stream->fd, &b, 1); (void)result; } void rava_stream_close(RavaStream_t *stream) { if (!stream) return; stream->closed = true; }