implemented socket send and receive

This commit is contained in:
Timerix 2025-07-22 23:57:11 +03:00
parent 94091d7797
commit 7cd7535eb0
9 changed files with 129 additions and 62 deletions

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit 447c15bc467546aa80245a7c5bc15d46d1349661
Subproject commit a9fa42c23f8419ef80f7b74074030d54388cf410

View File

@ -4,6 +4,7 @@
#include <pthread.h>
#include "tlibc/time.h"
#include "errno.h"
#include <stdlib.h>
Result(void) test_aes(){
const str password = STR("abobus");
@ -54,33 +55,45 @@ void* test_server(void* data){
printf_safe("[server]: opening main socket\n");
try_fatal(main_socket, socket_open_TCP(), );
EndpointIPv4 server_end = EndpointIPv4_create(AddressIPv4_LOOPBACK, 24500);
try_fatal(_20, socket_bind(main_socket.v_i64, server_end), socket_close(main_socket.v_i64));
try_fatal(_30, socket_listen(main_socket.v_i64, 64), socket_close(main_socket.v_i64));
try_fatal(_20, socket_bind(main_socket.i, server_end), socket_close(main_socket.i));
try_fatal(_30, socket_listen(main_socket.i, 64), socket_close(main_socket.i));
printf_safe("[server]: accepting client connection\n");
try_fatal(client_conn, socket_accept(main_socket.v_i64), socket_close(main_socket.v_i64));
try_fatal(client_conn, socket_accept(main_socket.i, NULL), socket_close(main_socket.i));
Array buf = Array_alloc(u8, 1024);
i32 read_n;
// last byte is reserved for '\0'
Array buf = Array_construct(malloc(1024), u8, 1023);
printf_safe("[server]: receiving data from client\n");
while((read_n = recv(client_conn.v_i64, buf.data, buf.size - 1, 0)) != -1){
if(read_n == 0){
while(true){
try_fatal(read_n,
socket_recv(client_conn.i, buf),
socket_close(client_conn.i));
if(read_n.i == 0){
sleepMsec(20);
continue;
}
char* data_s = (char*)buf.data;
char last_char;
while((last_char = data_s[read_n - 1]) == '\n'
|| last_char == '\r' || last_char == ' ' || last_char == ' ')
bool stop = false;
while(read_n.i > 0 && !stop)
{
read_n--;
last_char = data_s[read_n.i - 1];
switch(last_char){
case '\0': case '\r': case '\n':
case '\t': case ' ':
read_n.i--;
break;
default:
stop = true;
break;
}
data_s[read_n] = '\0';
printf_safe("[server/out]: %s\n", (char*)buf.data);
}
socket_close(client_conn.v_i64);
data_s[read_n.i] = '\0';
printf_safe("[server]: got '%s'\n", data_s);
}
socket_close(client_conn.i);
printf_safe("[server]: client socket closed\n");
perror("errno:");
socket_close(main_socket.v_i64);
socket_close(main_socket.i);
return NULL;
}
@ -89,19 +102,20 @@ void* test_client(void* data){
try_fatal(client_socket, socket_open_TCP(), );
printf_safe("[client]: connecting to server\n");
EndpointIPv4 server_end = EndpointIPv4_create(AddressIPv4_LOOPBACK, 24500);
try_fatal(_20, socket_connect(client_socket.v_i64, server_end), socket_close(client_socket.v_i64));
try_fatal(_20,
socket_connect(client_socket.i, server_end),
socket_close(client_socket.i));
Array buf = Array_alloc(u8, 1024);
i32 read_n = 999;
i32 read_n;
printf_safe("[client]: reading stdin\n");
while((read_n = read(STDIN_FILENO, buf.data, buf.size - 1)) > 0){
if(send(client_socket.v_i64, buf.data, read_n, 0) < 0){
socket_close(client_socket.v_i64);
printf_safe("[client]: can't send data to server\n");
exit(20);
}
while(fgets(buf.data, buf.size, stdin) != NULL){
read_n = strlen(buf.data) + 1;
try_fatal(_50,
socket_send(client_socket.i, Array_construct_size(buf.data, read_n)),
socket_close(client_socket.i));
}
printf_safe("[client]: stdin end\n");
socket_close(client_socket.v_i64);
socket_close(client_socket.i);
return NULL;
}

View File

@ -1,5 +1,5 @@
#include "std_includes.h"
#include "endpoint.h"
#include "network.h"
struct sockaddr_in EndpointIPv4_toSockaddr(EndpointIPv4 end){
struct sockaddr_in saddr = {0};
@ -18,6 +18,7 @@ EndpointIPv4 EndpointIPv4_fromSockaddr(struct sockaddr_in saddr){
return end;
}
//TODO Endpoint functions
AddressIPv4 AddressIPv4_fromStr(cstr);
str AddressIPv4_toStr(AddressIPv4 address);

View File

@ -1,7 +1,6 @@
#pragma once
#include "tlibc/std.h"
#include "tlibc/string/str.h"
#include "network.h"
#define port_INVALID ((port)~0)
#define port_is_invalid(PORT) (PORT == port_INVALID)

View File

@ -1,5 +1,5 @@
#include "network.h"
#include "network.h"
#include "std_includes.h"
Result(void) network_init(){
#if _WIN32

View File

@ -1,22 +1,5 @@
#pragma once
#include "tlibc/errors.h"
#if defined(_WIN64) || defined(_WIN32)
#define KN_USE_WINSOCK 1
#else
#define KN_USE_WINSOCK 0
#endif
#if KN_USE_WINSOCK
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
Result(void) network_init();
Result(void) network_deinit();

View File

@ -1,14 +1,15 @@
#include "network.h"
#include "network.h"
#include "std_includes.h"
#include "socket.h"
#include "errno.h"
#include "assert.h"
Result(Socket) socket_open_TCP(){
Socket s = socket(AF_INET, SOCK_STREAM, 0);
if(s == -1){
return RESULT_ERROR("can't create socket", false);
return RESULT_ERROR(strerror(errno), false);
}
return RESULT_VALUE(i64, s);
return RESULT_VALUE(i, s);
}
void socket_close(Socket s){
@ -21,33 +22,79 @@ void socket_close(Socket s){
Result(void) socket_shutdown(Socket s, SocketShutdownType direction){
if(shutdown(s, (int)direction) == -1)
return RESULT_ERROR("shutdown() failed", false);
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(void) socket_bind(Socket s, EndpointIPv4 local_end){
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(local_end);
if(bind(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
return RESULT_ERROR("bind() failed", false);
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(void) socket_listen(Socket s, i32 backlog){
if(listen(s, backlog) != 0)
return RESULT_ERROR("listen() failed", false);
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(Socket) socket_accept(Socket main_socket) {
Result(Socket) socket_accept(Socket main_socket, NULLABLE(EndpointIPv4*) remote_end) {
struct sockaddr_in remote_addr = {0};
i32 sockaddr_size = sizeof(remote_addr);
Socket user_connection = accept(main_socket, (struct sockaddr*)&remote_addr, (void*)&sockaddr_size);
return RESULT_VALUE(i64, user_connection);
Socket user_connection = accept(main_socket, (void*)&remote_addr, (void*)&sockaddr_size);
if(user_connection == -1)
return RESULT_ERROR(strerror(errno), false);
//TODO: add IPV6 support (struct sockaddr_in6)
assert(sockaddr_size == sizeof(remote_addr));
if(remote_end)
*remote_end = EndpointIPv4_fromSockaddr(remote_addr);
return RESULT_VALUE(i, user_connection);
}
Result(void) socket_connect(Socket s, EndpointIPv4 remote_end){
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(remote_end);
if(connect(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
return RESULT_ERROR("connect() failed", false);
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(void) socket_send(Socket s, Array buffer){
i32 r = send(s, buffer.data, buffer.size, 0);
if(r < 0)
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(void) socket_sendto(Socket s, Array buffer, EndpointIPv4 dst){
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(dst);
i32 r = sendto(s, buffer.data, buffer.size, 0, (void*)&sockaddr, sizeof(sockaddr));
if(r < 0)
return RESULT_ERROR(strerror(errno), false);
return RESULT_VOID;
}
Result(i32) socket_recv(Socket s, Array buffer){
i32 r = recv(s, buffer.data, buffer.size, 0);
if(r < 0)
return RESULT_ERROR(strerror(errno), false);
return RESULT_VALUE(i, r);
}
Result(i32) socket_recvfrom(Socket s, Array buffer, NULLABLE(EndpointIPv4*) remote_end){
struct sockaddr_in remote_addr = {0};
i32 sockaddr_size = sizeof(remote_addr);
i32 r = recvfrom(s, buffer.data, buffer.size, 0,
(struct sockaddr*)&remote_addr, (void*)&sockaddr_size);
if(r < 0)
return RESULT_ERROR(strerror(errno), false);
//TODO: add IPV6 support (struct sockaddr_in6)
assert(sockaddr_size == sizeof(remote_addr));
if(remote_end)
*remote_end = EndpointIPv4_fromSockaddr(remote_addr);
return RESULT_VALUE(i, r);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "endpoint.h"
#include "tlibc/errors.h"
#include "tlibc/collections/Array.h"
typedef enum SocketShutdownType {
SocketShutdownType_Receive = 0,
@ -15,5 +16,9 @@ void socket_close(Socket s);
Result(void) socket_shutdown(Socket s, SocketShutdownType direction);
Result(void) socket_bind(Socket s, EndpointIPv4 local_end);
Result(void) socket_listen(Socket s, i32 backlog);
Result(Socket) socket_accept(Socket s);
Result(Socket) socket_accept(Socket s, NULLABLE(EndpointIPv4*) remote_end);
Result(void) socket_connect(Socket s, EndpointIPv4 remote_end);
Result(void) socket_send(Socket s, Array buffer);
Result(void) socket_sendto(Socket s, Array buffer, EndpointIPv4 dst);
Result(i32) socket_recv(Socket s, Array buffer);
Result(i32) socket_recvfrom(Socket s, Array buffer, NULLABLE(EndpointIPv4*) remote_end);

View File

@ -0,0 +1,18 @@
#pragma once
#if defined(_WIN64) || defined(_WIN32)
#define KN_USE_WINSOCK 1
#else
#define KN_USE_WINSOCK 0
#endif
#if KN_USE_WINSOCK
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif