chore: remove trailing whitespace from README.md line 42
This commit is contained in:
+242
-13
@@ -782,6 +782,10 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
if (start > end) start = end;
|
||||
size_t sub_len = end - start;
|
||||
char *sub = malloc(sub_len + 1);
|
||||
if (!sub) {
|
||||
rava_stack_push(stack, rava_value_string(""));
|
||||
break;
|
||||
}
|
||||
strncpy(sub, str_val.data.string_val + start, sub_len);
|
||||
sub[sub_len] = '\0';
|
||||
rava_stack_push(stack, rava_value_string(sub));
|
||||
@@ -864,6 +868,10 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
if (str_val.type == RAVA_VAL_STRING && str_val.data.string_val) {
|
||||
size_t len = strlen(str_val.data.string_val);
|
||||
char *lower = malloc(len + 1);
|
||||
if (!lower) {
|
||||
rava_stack_push(stack, rava_value_string(""));
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
lower[i] = (char)tolower((unsigned char)str_val.data.string_val[i]);
|
||||
}
|
||||
@@ -879,6 +887,10 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
if (str_val.type == RAVA_VAL_STRING && str_val.data.string_val) {
|
||||
size_t len = strlen(str_val.data.string_val);
|
||||
char *upper = malloc(len + 1);
|
||||
if (!upper) {
|
||||
rava_stack_push(stack, rava_value_string(""));
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
upper[i] = (char)toupper((unsigned char)str_val.data.string_val[i]);
|
||||
}
|
||||
@@ -898,6 +910,10 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
while (end > start && isspace((unsigned char)*(end - 1))) end--;
|
||||
size_t len = (size_t)(end - start);
|
||||
char *trimmed = malloc(len + 1);
|
||||
if (!trimmed) {
|
||||
rava_stack_push(stack, rava_value_string(""));
|
||||
break;
|
||||
}
|
||||
strncpy(trimmed, start, len);
|
||||
trimmed[len] = '\0';
|
||||
rava_stack_push(stack, rava_value_string(trimmed));
|
||||
@@ -1093,6 +1109,18 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_INPUT_STREAM_SKIP: {
|
||||
RavaValue_t n_val = rava_stack_pop(stack);
|
||||
RavaValue_t stream_val = rava_stack_pop(stack);
|
||||
long skipped = 0;
|
||||
if (stream_val.type == RAVA_VAL_STREAM && stream_val.data.stream_val) {
|
||||
long n = (n_val.type == RAVA_VAL_INT) ? n_val.data.int_val : 0;
|
||||
skipped = rava_stream_skip(stream_val.data.stream_val, n);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_int(skipped));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_OUTPUT_STREAM_WRITE: {
|
||||
int arg_count = instr->operand.int_value;
|
||||
if (arg_count >= 1) {
|
||||
@@ -1109,6 +1137,14 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_OUTPUT_STREAM_FLUSH: {
|
||||
RavaValue_t stream_val = rava_stack_pop(stack);
|
||||
if (stream_val.type == RAVA_VAL_STREAM && stream_val.data.stream_val) {
|
||||
rava_stream_flush(stream_val.data.stream_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SOCKET_CLOSE: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
if (val.type == RAVA_VAL_SOCKET && val.data.socket_val) {
|
||||
@@ -1189,6 +1225,46 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_INETADDRESS_GET_ALL_BY_NAME: {
|
||||
RavaValue_t host_val = rava_stack_pop(stack);
|
||||
const char *host = (host_val.type == RAVA_VAL_STRING) ? host_val.data.string_val : NULL;
|
||||
RavaArray_t *addrs = rava_inetaddress_get_all_by_name(host);
|
||||
rava_stack_push(stack, rava_value_array(addrs));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_INETADDRESS_GET_ADDRESS: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
RavaArray_t *bytes = NULL;
|
||||
if (val.type == RAVA_VAL_INETADDRESS && val.data.inetaddress_val) {
|
||||
bytes = rava_inetaddress_get_address(val.data.inetaddress_val);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_array(bytes));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_INETADDRESS_IS_MULTICAST_ADDRESS: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
bool result = false;
|
||||
if (val.type == RAVA_VAL_INETADDRESS && val.data.inetaddress_val) {
|
||||
result = rava_inetaddress_is_multicast_address(val.data.inetaddress_val);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_boolean(result));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_INETADDRESS_IS_REACHABLE: {
|
||||
RavaValue_t timeout_val = rava_stack_pop(stack);
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
bool result = false;
|
||||
if (val.type == RAVA_VAL_INETADDRESS && val.data.inetaddress_val) {
|
||||
int timeout = (timeout_val.type == RAVA_VAL_INT) ? (int)timeout_val.data.int_val : 5000;
|
||||
result = rava_inetaddress_is_reachable(val.data.inetaddress_val, timeout);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_boolean(result));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SOCKET_GET_PORT: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
int port = -1;
|
||||
@@ -1259,6 +1335,45 @@ static bool _rava_vm_execute_instruction(RavaVM_t *vm, RavaCallFrame_t *frame, R
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SERVER_SOCKET_SET_RECEIVE_BUFFER_SIZE: {
|
||||
RavaValue_t size_val = rava_stack_pop(stack);
|
||||
RavaValue_t socket_val = rava_stack_pop(stack);
|
||||
if (socket_val.type == RAVA_VAL_SOCKET && socket_val.data.socket_val) {
|
||||
rava_server_socket_set_receive_buffer_size(socket_val.data.socket_val, (int)size_val.data.int_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SERVER_SOCKET_GET_RECEIVE_BUFFER_SIZE: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
int size = 0;
|
||||
if (val.type == RAVA_VAL_SOCKET && val.data.socket_val) {
|
||||
size = rava_server_socket_get_receive_buffer_size(val.data.socket_val);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_int(size));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SERVER_SOCKET_SET_REUSE_ADDRESS: {
|
||||
RavaValue_t reuse_val = rava_stack_pop(stack);
|
||||
RavaValue_t socket_val = rava_stack_pop(stack);
|
||||
if (socket_val.type == RAVA_VAL_SOCKET && socket_val.data.socket_val) {
|
||||
bool reuse = (reuse_val.type == RAVA_VAL_INT && reuse_val.data.int_val != 0);
|
||||
rava_server_socket_set_reuse_address(socket_val.data.socket_val, reuse);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SERVER_SOCKET_GET_REUSE_ADDRESS: {
|
||||
RavaValue_t val = rava_stack_pop(stack);
|
||||
bool result = false;
|
||||
if (val.type == RAVA_VAL_SOCKET && val.data.socket_val) {
|
||||
result = rava_server_socket_get_reuse_address(val.data.socket_val);
|
||||
}
|
||||
rava_stack_push(stack, rava_value_boolean(result));
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_OP_SOCKET_SET_SO_TIMEOUT: {
|
||||
RavaValue_t timeout_val = rava_stack_pop(stack);
|
||||
RavaValue_t socket_val = rava_stack_pop(stack);
|
||||
@@ -3197,15 +3312,20 @@ bool _rava_vm_execute_ultrafast(RavaVM_t *vm, RavaMethod_t *entry_method) {
|
||||
&&uf_socket_close, &&uf_server_socket_new, &&uf_server_socket_accept,
|
||||
&&uf_socket_get_input_stream, &&uf_socket_get_output_stream,
|
||||
&&uf_input_stream_read, &&uf_input_stream_read_bytes, &&uf_input_stream_available,
|
||||
&&uf_output_stream_write, &&uf_stream_close,
|
||||
&&uf_input_stream_skip,
|
||||
&&uf_output_stream_write, &&uf_output_stream_flush, &&uf_stream_close,
|
||||
&&uf_inetaddress_get_by_name, &&uf_inetaddress_get_local_host,
|
||||
&&uf_inetaddress_get_loopback, &&uf_inetaddress_get_host_name,
|
||||
&&uf_inetaddress_get_host_address, &&uf_inetaddress_is_loopback,
|
||||
&&uf_inetaddress_is_any_local,
|
||||
&&uf_inetaddress_get_all_by_name, &&uf_inetaddress_get_address,
|
||||
&&uf_inetaddress_is_multicast_address, &&uf_inetaddress_is_reachable,
|
||||
&&uf_socket_get_port, &&uf_socket_get_local_port,
|
||||
&&uf_socket_get_inet_address, &&uf_socket_get_local_address,
|
||||
&&uf_server_socket_get_local_port, &&uf_server_socket_is_bound,
|
||||
&&uf_server_socket_is_closed,
|
||||
&&uf_server_socket_set_receive_buffer_size, &&uf_server_socket_get_receive_buffer_size,
|
||||
&&uf_server_socket_set_reuse_address, &&uf_server_socket_get_reuse_address,
|
||||
&&uf_socket_set_so_timeout, &&uf_socket_get_so_timeout,
|
||||
&&uf_socket_set_tcp_nodelay, &&uf_socket_get_tcp_nodelay,
|
||||
&&uf_socket_bind, &&uf_socket_is_connected,
|
||||
@@ -3931,10 +4051,14 @@ uf_string_tolowercase: {
|
||||
if (str) {
|
||||
size_t len = strlen(str);
|
||||
char *lower = malloc(len + 1);
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
lower[i] = (char)tolower((unsigned char)str[i]);
|
||||
if (!lower) {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
} else {
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
lower[i] = (char)tolower((unsigned char)str[i]);
|
||||
}
|
||||
UF_PUSH(rava_nanbox_string(lower));
|
||||
}
|
||||
UF_PUSH(rava_nanbox_string(lower));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
}
|
||||
@@ -3947,10 +4071,14 @@ uf_string_touppercase: {
|
||||
if (str) {
|
||||
size_t len = strlen(str);
|
||||
char *upper = malloc(len + 1);
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
upper[i] = (char)toupper((unsigned char)str[i]);
|
||||
if (!upper) {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
} else {
|
||||
for (size_t i = 0; i <= len; i++) {
|
||||
upper[i] = (char)toupper((unsigned char)str[i]);
|
||||
}
|
||||
UF_PUSH(rava_nanbox_string(upper));
|
||||
}
|
||||
UF_PUSH(rava_nanbox_string(upper));
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
}
|
||||
@@ -3967,9 +4095,13 @@ uf_string_trim: {
|
||||
while (end > start && isspace((unsigned char)*(end - 1))) end--;
|
||||
size_t len = (size_t)(end - start);
|
||||
char *trimmed = malloc(len + 1);
|
||||
strncpy(trimmed, start, len);
|
||||
trimmed[len] = '\0';
|
||||
UF_PUSH(rava_nanbox_string(trimmed));
|
||||
if (!trimmed) {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
} else {
|
||||
strncpy(trimmed, start, len);
|
||||
trimmed[len] = '\0';
|
||||
UF_PUSH(rava_nanbox_string(trimmed));
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
}
|
||||
@@ -4060,9 +4192,13 @@ uf_string_substring: {
|
||||
if (str && start >= 0 && end >= start && (size_t)end <= strlen(str)) {
|
||||
size_t len = (size_t)(end - start);
|
||||
char *sub = malloc(len + 1);
|
||||
strncpy(sub, str + start, len);
|
||||
sub[len] = '\0';
|
||||
UF_PUSH(rava_nanbox_string(sub));
|
||||
if (!sub) {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
} else {
|
||||
strncpy(sub, str + start, len);
|
||||
sub[len] = '\0';
|
||||
UF_PUSH(rava_nanbox_string(sub));
|
||||
}
|
||||
} else {
|
||||
UF_PUSH(rava_nanbox_string(""));
|
||||
}
|
||||
@@ -4787,6 +4923,19 @@ uf_input_stream_available: {
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_input_stream_skip: {
|
||||
RavaNanboxValue_t n_nb = UF_POP();
|
||||
RavaNanboxValue_t stream_nb = UF_POP();
|
||||
RavaStream_t *stream = (RavaStream_t*)rava_nanbox_as_object(stream_nb);
|
||||
long skipped = 0;
|
||||
if (stream) {
|
||||
long n = rava_nanbox_as_int(n_nb);
|
||||
skipped = rava_stream_skip(stream, n);
|
||||
}
|
||||
UF_PUSH(rava_nanbox_int(skipped));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_output_stream_write: {
|
||||
int arg_count = instr->operand.int_value;
|
||||
if (arg_count >= 1) {
|
||||
@@ -4804,6 +4953,15 @@ uf_output_stream_write: {
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_output_stream_flush: {
|
||||
RavaNanboxValue_t stream_nb = UF_POP();
|
||||
RavaStream_t *stream = (RavaStream_t*)rava_nanbox_as_object(stream_nb);
|
||||
if (stream) {
|
||||
rava_stream_flush(stream);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_socket_close: {
|
||||
RavaNanboxValue_t val = UF_POP();
|
||||
void *ptr = rava_nanbox_as_object(val);
|
||||
@@ -4870,6 +5028,40 @@ uf_inetaddress_is_any_local: {
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_inetaddress_get_all_by_name: {
|
||||
RavaNanboxValue_t host_nb = UF_POP();
|
||||
const char *host = rava_nanbox_as_string(host_nb);
|
||||
RavaArray_t *addrs = rava_inetaddress_get_all_by_name(host);
|
||||
UF_PUSH(rava_nanbox_object(addrs));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_inetaddress_get_address: {
|
||||
RavaNanboxValue_t addr_nb = UF_POP();
|
||||
RavaInetAddress_t *addr = (RavaInetAddress_t*)rava_nanbox_as_object(addr_nb);
|
||||
RavaArray_t *bytes = rava_inetaddress_get_address(addr);
|
||||
UF_PUSH(rava_nanbox_object(bytes));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_inetaddress_is_multicast_address: {
|
||||
RavaNanboxValue_t addr_nb = UF_POP();
|
||||
RavaInetAddress_t *addr = (RavaInetAddress_t*)rava_nanbox_as_object(addr_nb);
|
||||
bool result = rava_inetaddress_is_multicast_address(addr);
|
||||
UF_PUSH(rava_nanbox_bool(result));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_inetaddress_is_reachable: {
|
||||
RavaNanboxValue_t timeout_nb = UF_POP();
|
||||
RavaNanboxValue_t addr_nb = UF_POP();
|
||||
RavaInetAddress_t *addr = (RavaInetAddress_t*)rava_nanbox_as_object(addr_nb);
|
||||
int timeout = rava_nanbox_as_int(timeout_nb);
|
||||
bool result = rava_inetaddress_is_reachable(addr, timeout);
|
||||
UF_PUSH(rava_nanbox_bool(result));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_socket_get_port: {
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
RavaSocket_t *sock = (RavaSocket_t*)rava_nanbox_as_object(sock_nb);
|
||||
@@ -4926,6 +5118,43 @@ uf_server_socket_is_closed: {
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_server_socket_set_receive_buffer_size: {
|
||||
RavaNanboxValue_t size_nb = UF_POP();
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
RavaSocket_t *sock = (RavaSocket_t*)rava_nanbox_as_object(sock_nb);
|
||||
if (sock) {
|
||||
rava_server_socket_set_receive_buffer_size(sock, rava_nanbox_as_int(size_nb));
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_server_socket_get_receive_buffer_size: {
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
RavaSocket_t *sock = (RavaSocket_t*)rava_nanbox_as_object(sock_nb);
|
||||
int size = rava_server_socket_get_receive_buffer_size(sock);
|
||||
UF_PUSH(rava_nanbox_int(size));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_server_socket_set_reuse_address: {
|
||||
RavaNanboxValue_t reuse_nb = UF_POP();
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
RavaSocket_t *sock = (RavaSocket_t*)rava_nanbox_as_object(sock_nb);
|
||||
if (sock) {
|
||||
bool reuse = rava_nanbox_as_bool(reuse_nb);
|
||||
rava_server_socket_set_reuse_address(sock, reuse);
|
||||
}
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_server_socket_get_reuse_address: {
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
RavaSocket_t *sock = (RavaSocket_t*)rava_nanbox_as_object(sock_nb);
|
||||
bool result = rava_server_socket_get_reuse_address(sock);
|
||||
UF_PUSH(rava_nanbox_bool(result));
|
||||
UF_DISPATCH();
|
||||
}
|
||||
|
||||
uf_socket_set_so_timeout: {
|
||||
RavaNanboxValue_t timeout_nb = UF_POP();
|
||||
RavaNanboxValue_t sock_nb = UF_POP();
|
||||
|
||||
@@ -384,6 +384,8 @@ void rava_stream_write_byte(RavaStream_t *stream, int byte);
|
||||
void rava_stream_close(RavaStream_t *stream);
|
||||
int rava_stream_read_bytes(RavaStream_t *stream, RavaArray_t *arr, int off, int len);
|
||||
int rava_stream_available(RavaStream_t *stream);
|
||||
void rava_stream_flush(RavaStream_t *stream);
|
||||
long rava_stream_skip(RavaStream_t *stream, long n);
|
||||
|
||||
RavaInetAddress_t* rava_inetaddress_create(void);
|
||||
RavaInetAddress_t* rava_inetaddress_get_by_name(const char *host);
|
||||
@@ -393,6 +395,10 @@ char* rava_inetaddress_get_host_name(RavaInetAddress_t *addr);
|
||||
char* rava_inetaddress_get_host_address(RavaInetAddress_t *addr);
|
||||
bool rava_inetaddress_is_loopback(RavaInetAddress_t *addr);
|
||||
bool rava_inetaddress_is_any_local(RavaInetAddress_t *addr);
|
||||
RavaArray_t* rava_inetaddress_get_all_by_name(const char *host);
|
||||
RavaArray_t* rava_inetaddress_get_address(RavaInetAddress_t *addr);
|
||||
bool rava_inetaddress_is_multicast_address(RavaInetAddress_t *addr);
|
||||
bool rava_inetaddress_is_reachable(RavaInetAddress_t *addr, int timeout);
|
||||
int rava_socket_get_port(RavaSocket_t *socket);
|
||||
int rava_socket_get_local_port(RavaSocket_t *socket);
|
||||
RavaInetAddress_t* rava_socket_get_inet_address(RavaSocket_t *socket);
|
||||
@@ -402,6 +408,10 @@ bool rava_server_socket_is_bound(RavaSocket_t *socket);
|
||||
bool rava_server_socket_is_closed(RavaSocket_t *socket);
|
||||
void rava_server_socket_set_so_timeout(RavaSocket_t *socket, int timeout);
|
||||
int rava_server_socket_get_so_timeout(RavaSocket_t *socket);
|
||||
void rava_server_socket_set_receive_buffer_size(RavaSocket_t *socket, int size);
|
||||
int rava_server_socket_get_receive_buffer_size(RavaSocket_t *socket);
|
||||
void rava_server_socket_set_reuse_address(RavaSocket_t *socket, bool reuse);
|
||||
bool rava_server_socket_get_reuse_address(RavaSocket_t *socket);
|
||||
void rava_socket_set_so_timeout(RavaSocket_t *socket, int timeout_ms);
|
||||
int rava_socket_get_so_timeout(RavaSocket_t *socket);
|
||||
void rava_socket_set_tcp_nodelay(RavaSocket_t *socket, bool nodelay);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
@@ -248,6 +249,28 @@ int rava_stream_available(RavaStream_t *stream) {
|
||||
return available;
|
||||
}
|
||||
|
||||
void rava_stream_flush(RavaStream_t *stream) {
|
||||
if (!stream || stream->closed || stream->fd < 0) return;
|
||||
if (stream->stream_type != RAVA_STREAM_TYPE_OUTPUT) return;
|
||||
fsync(stream->fd);
|
||||
}
|
||||
|
||||
long rava_stream_skip(RavaStream_t *stream, long n) {
|
||||
if (!stream || stream->closed || stream->fd < 0) return 0;
|
||||
if (stream->stream_type != RAVA_STREAM_TYPE_INPUT) return 0;
|
||||
if (n <= 0) return 0;
|
||||
|
||||
long skipped = 0;
|
||||
char buffer[1024];
|
||||
while (skipped < n) {
|
||||
long to_read = (n - skipped > 1024) ? 1024 : (n - skipped);
|
||||
ssize_t read_count = read(stream->fd, buffer, (size_t)to_read);
|
||||
if (read_count <= 0) break;
|
||||
skipped += read_count;
|
||||
}
|
||||
return skipped;
|
||||
}
|
||||
|
||||
RavaInetAddress_t* rava_inetaddress_create(void) {
|
||||
RavaInetAddress_t *addr = rava_gc_alloc(sizeof(RavaInetAddress_t), RAVA_GC_TYPE_INETADDRESS);
|
||||
if (!addr) return NULL;
|
||||
@@ -372,6 +395,136 @@ bool rava_inetaddress_is_any_local(RavaInetAddress_t *addr) {
|
||||
return memcmp(addr->address, ipv6_any, 16) == 0;
|
||||
}
|
||||
|
||||
RavaArray_t* rava_inetaddress_get_all_by_name(const char *host) {
|
||||
if (!host) return NULL;
|
||||
|
||||
struct addrinfo hints, *res, *p;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo(host, NULL, &hints, &res) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for (p = res; p != NULL; p = p->ai_next) {
|
||||
count++;
|
||||
}
|
||||
|
||||
RavaArray_t *array = rava_gc_alloc(sizeof(RavaArray_t), RAVA_GC_TYPE_ARRAY);
|
||||
if (!array) {
|
||||
freeaddrinfo(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array->length = count;
|
||||
array->element_type = RAVA_VAL_INETADDRESS;
|
||||
array->data = calloc(count, sizeof(RavaValue_t));
|
||||
if (!array->data && count > 0) {
|
||||
freeaddrinfo(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RavaValue_t *values = (RavaValue_t *)array->data;
|
||||
size_t i = 0;
|
||||
for (p = res; p != NULL; p = p->ai_next) {
|
||||
RavaInetAddress_t *addr = rava_inetaddress_create();
|
||||
if (addr) {
|
||||
if (p->ai_family == AF_INET) {
|
||||
addr->address_type = RAVA_INETADDRESS_IPV4;
|
||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
||||
memcpy(addr->address, &ipv4->sin_addr, 4);
|
||||
} else if (p->ai_family == AF_INET6) {
|
||||
addr->address_type = RAVA_INETADDRESS_IPV6;
|
||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||
memcpy(addr->address, &ipv6->sin6_addr, 16);
|
||||
}
|
||||
addr->hostname = host ? strdup(host) : NULL;
|
||||
values[i] = rava_value_inetaddress(addr);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
return array;
|
||||
}
|
||||
|
||||
RavaArray_t* rava_inetaddress_get_address(RavaInetAddress_t *addr) {
|
||||
if (!addr) return NULL;
|
||||
|
||||
size_t len = (addr->address_type == RAVA_INETADDRESS_IPV4) ? 4 : 16;
|
||||
RavaArray_t *array = rava_gc_alloc(sizeof(RavaArray_t), RAVA_GC_TYPE_ARRAY);
|
||||
if (!array) return NULL;
|
||||
|
||||
array->length = len;
|
||||
array->element_type = RAVA_VAL_INT;
|
||||
array->data = calloc(len, sizeof(int64_t));
|
||||
if (!array->data && len > 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t *values = (int64_t *)array->data;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
values[i] = addr->address[i];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
bool rava_inetaddress_is_multicast_address(RavaInetAddress_t *addr) {
|
||||
if (!addr) return false;
|
||||
|
||||
if (addr->address_type == RAVA_INETADDRESS_IPV4) {
|
||||
return (addr->address[0] >= 224 && addr->address[0] <= 239);
|
||||
} else {
|
||||
return addr->address[0] == 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
bool rava_inetaddress_is_reachable(RavaInetAddress_t *addr, int timeout) {
|
||||
if (!addr) return false;
|
||||
|
||||
int sock = socket(addr->address_type == RAVA_INETADDRESS_IPV4 ? AF_INET : AF_INET6, SOCK_STREAM, 0);
|
||||
if (sock < 0) return false;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
|
||||
bool result = false;
|
||||
if (addr->address_type == RAVA_INETADDRESS_IPV4) {
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(7);
|
||||
memcpy(&sa.sin_addr, addr->address, 4);
|
||||
|
||||
int res = connect(sock, (struct sockaddr*)&sa, sizeof(sa));
|
||||
if (res == 0 || (res < 0 && errno == EINPROGRESS)) {
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
struct timeval tv2;
|
||||
tv2.tv_sec = timeout / 1000;
|
||||
tv2.tv_usec = (timeout % 1000) * 1000;
|
||||
if (select(sock + 1, NULL, &fdset, NULL, &tv2) > 0) {
|
||||
int so_error;
|
||||
socklen_t len = sizeof(so_error);
|
||||
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
|
||||
result = (so_error == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
int rava_socket_get_port(RavaSocket_t *socket) {
|
||||
if (!socket || socket->fd < 0) return -1;
|
||||
|
||||
@@ -470,6 +623,37 @@ int rava_server_socket_get_so_timeout(RavaSocket_t *socket) {
|
||||
return (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
|
||||
}
|
||||
|
||||
void rava_server_socket_set_receive_buffer_size(RavaSocket_t *socket, int size) {
|
||||
if (!socket || socket->fd < 0) return;
|
||||
setsockopt(socket->fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
|
||||
}
|
||||
|
||||
int rava_server_socket_get_receive_buffer_size(RavaSocket_t *socket) {
|
||||
if (!socket || socket->fd < 0) return 0;
|
||||
int size = 0;
|
||||
socklen_t len = sizeof(size);
|
||||
if (getsockopt(socket->fd, SOL_SOCKET, SO_RCVBUF, &size, &len) == 0) {
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rava_server_socket_set_reuse_address(RavaSocket_t *socket, bool reuse) {
|
||||
if (!socket || socket->fd < 0) return;
|
||||
int val = reuse ? 1 : 0;
|
||||
setsockopt(socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
}
|
||||
|
||||
bool rava_server_socket_get_reuse_address(RavaSocket_t *socket) {
|
||||
if (!socket || socket->fd < 0) return false;
|
||||
int val = 0;
|
||||
socklen_t len = sizeof(val);
|
||||
if (getsockopt(socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, &len) == 0) {
|
||||
return val != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void rava_socket_set_so_timeout(RavaSocket_t *socket, int timeout_ms) {
|
||||
if (!socket || socket->fd < 0) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user