implemented socket send and receive
This commit is contained in:
parent
94091d7797
commit
7cd7535eb0
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 447c15bc467546aa80245a7c5bc15d46d1349661
|
Subproject commit a9fa42c23f8419ef80f7b74074030d54388cf410
|
||||||
60
src/main.c
60
src/main.c
@ -4,6 +4,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "tlibc/time.h"
|
#include "tlibc/time.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
Result(void) test_aes(){
|
Result(void) test_aes(){
|
||||||
const str password = STR("abobus");
|
const str password = STR("abobus");
|
||||||
@ -54,33 +55,45 @@ void* test_server(void* data){
|
|||||||
printf_safe("[server]: opening main socket\n");
|
printf_safe("[server]: opening main socket\n");
|
||||||
try_fatal(main_socket, socket_open_TCP(), );
|
try_fatal(main_socket, socket_open_TCP(), );
|
||||||
EndpointIPv4 server_end = EndpointIPv4_create(AddressIPv4_LOOPBACK, 24500);
|
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(_20, socket_bind(main_socket.i, server_end), socket_close(main_socket.i));
|
||||||
try_fatal(_30, socket_listen(main_socket.v_i64, 64), socket_close(main_socket.v_i64));
|
try_fatal(_30, socket_listen(main_socket.i, 64), socket_close(main_socket.i));
|
||||||
printf_safe("[server]: accepting client connection\n");
|
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);
|
// last byte is reserved for '\0'
|
||||||
i32 read_n;
|
Array buf = Array_construct(malloc(1024), u8, 1023);
|
||||||
printf_safe("[server]: receiving data from client\n");
|
printf_safe("[server]: receiving data from client\n");
|
||||||
while((read_n = recv(client_conn.v_i64, buf.data, buf.size - 1, 0)) != -1){
|
while(true){
|
||||||
if(read_n == 0){
|
try_fatal(read_n,
|
||||||
|
socket_recv(client_conn.i, buf),
|
||||||
|
socket_close(client_conn.i));
|
||||||
|
if(read_n.i == 0){
|
||||||
sleepMsec(20);
|
sleepMsec(20);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char* data_s = (char*)buf.data;
|
char* data_s = (char*)buf.data;
|
||||||
char last_char;
|
char last_char;
|
||||||
while((last_char = data_s[read_n - 1]) == '\n'
|
bool stop = false;
|
||||||
|| last_char == '\r' || last_char == ' ' || last_char == ' ')
|
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';
|
data_s[read_n.i] = '\0';
|
||||||
printf_safe("[server/out]: %s\n", (char*)buf.data);
|
printf_safe("[server]: got '%s'\n", data_s);
|
||||||
}
|
}
|
||||||
socket_close(client_conn.v_i64);
|
socket_close(client_conn.i);
|
||||||
printf_safe("[server]: client socket closed\n");
|
printf_safe("[server]: client socket closed\n");
|
||||||
perror("errno:");
|
perror("errno:");
|
||||||
socket_close(main_socket.v_i64);
|
socket_close(main_socket.i);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,19 +102,20 @@ void* test_client(void* data){
|
|||||||
try_fatal(client_socket, socket_open_TCP(), );
|
try_fatal(client_socket, socket_open_TCP(), );
|
||||||
printf_safe("[client]: connecting to server\n");
|
printf_safe("[client]: connecting to server\n");
|
||||||
EndpointIPv4 server_end = EndpointIPv4_create(AddressIPv4_LOOPBACK, 24500);
|
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);
|
Array buf = Array_alloc(u8, 1024);
|
||||||
i32 read_n = 999;
|
i32 read_n;
|
||||||
printf_safe("[client]: reading stdin\n");
|
printf_safe("[client]: reading stdin\n");
|
||||||
while((read_n = read(STDIN_FILENO, buf.data, buf.size - 1)) > 0){
|
while(fgets(buf.data, buf.size, stdin) != NULL){
|
||||||
if(send(client_socket.v_i64, buf.data, read_n, 0) < 0){
|
read_n = strlen(buf.data) + 1;
|
||||||
socket_close(client_socket.v_i64);
|
try_fatal(_50,
|
||||||
printf_safe("[client]: can't send data to server\n");
|
socket_send(client_socket.i, Array_construct_size(buf.data, read_n)),
|
||||||
exit(20);
|
socket_close(client_socket.i));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printf_safe("[client]: stdin end\n");
|
printf_safe("[client]: stdin end\n");
|
||||||
socket_close(client_socket.v_i64);
|
socket_close(client_socket.i);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
#include "std_includes.h"
|
||||||
#include "endpoint.h"
|
#include "endpoint.h"
|
||||||
#include "network.h"
|
|
||||||
|
|
||||||
struct sockaddr_in EndpointIPv4_toSockaddr(EndpointIPv4 end){
|
struct sockaddr_in EndpointIPv4_toSockaddr(EndpointIPv4 end){
|
||||||
struct sockaddr_in saddr = {0};
|
struct sockaddr_in saddr = {0};
|
||||||
@ -18,6 +18,7 @@ EndpointIPv4 EndpointIPv4_fromSockaddr(struct sockaddr_in saddr){
|
|||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO Endpoint functions
|
||||||
AddressIPv4 AddressIPv4_fromStr(cstr);
|
AddressIPv4 AddressIPv4_fromStr(cstr);
|
||||||
|
|
||||||
str AddressIPv4_toStr(AddressIPv4 address);
|
str AddressIPv4_toStr(AddressIPv4 address);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "tlibc/std.h"
|
#include "tlibc/std.h"
|
||||||
#include "tlibc/string/str.h"
|
#include "tlibc/string/str.h"
|
||||||
#include "network.h"
|
|
||||||
|
|
||||||
#define port_INVALID ((port)~0)
|
#define port_INVALID ((port)~0)
|
||||||
#define port_is_invalid(PORT) (PORT == port_INVALID)
|
#define port_is_invalid(PORT) (PORT == port_INVALID)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "network.h"
|
#include "std_includes.h"
|
||||||
|
|
||||||
Result(void) network_init(){
|
Result(void) network_init(){
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
|||||||
@ -1,22 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "tlibc/errors.h"
|
#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_init();
|
||||||
Result(void) network_deinit();
|
Result(void) network_deinit();
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
#include "network.h"
|
#include "std_includes.h"
|
||||||
#include "network.h"
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include "errno.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
Result(Socket) socket_open_TCP(){
|
Result(Socket) socket_open_TCP(){
|
||||||
Socket s = socket(AF_INET, SOCK_STREAM, 0);
|
Socket s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if(s == -1){
|
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){
|
void socket_close(Socket s){
|
||||||
@ -21,33 +22,79 @@ void socket_close(Socket s){
|
|||||||
|
|
||||||
Result(void) socket_shutdown(Socket s, SocketShutdownType direction){
|
Result(void) socket_shutdown(Socket s, SocketShutdownType direction){
|
||||||
if(shutdown(s, (int)direction) == -1)
|
if(shutdown(s, (int)direction) == -1)
|
||||||
return RESULT_ERROR("shutdown() failed", false);
|
return RESULT_ERROR(strerror(errno), false);
|
||||||
return RESULT_VOID;
|
return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result(void) socket_bind(Socket s, EndpointIPv4 local_end){
|
Result(void) socket_bind(Socket s, EndpointIPv4 local_end){
|
||||||
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(local_end);
|
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(local_end);
|
||||||
if(bind(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
|
if(bind(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
|
||||||
return RESULT_ERROR("bind() failed", false);
|
return RESULT_ERROR(strerror(errno), false);
|
||||||
return RESULT_VOID;
|
return RESULT_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result(void) socket_listen(Socket s, i32 backlog){
|
Result(void) socket_listen(Socket s, i32 backlog){
|
||||||
if(listen(s, backlog) != 0)
|
if(listen(s, backlog) != 0)
|
||||||
return RESULT_ERROR("listen() failed", false);
|
return RESULT_ERROR(strerror(errno), false);
|
||||||
return RESULT_VOID;
|
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};
|
struct sockaddr_in remote_addr = {0};
|
||||||
i32 sockaddr_size = sizeof(remote_addr);
|
i32 sockaddr_size = sizeof(remote_addr);
|
||||||
Socket user_connection = accept(main_socket, (struct sockaddr*)&remote_addr, (void*)&sockaddr_size);
|
Socket user_connection = accept(main_socket, (void*)&remote_addr, (void*)&sockaddr_size);
|
||||||
return RESULT_VALUE(i64, user_connection);
|
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){
|
Result(void) socket_connect(Socket s, EndpointIPv4 remote_end){
|
||||||
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(remote_end);
|
struct sockaddr_in sockaddr = EndpointIPv4_toSockaddr(remote_end);
|
||||||
if(connect(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
|
if(connect(s, (void*)&sockaddr, sizeof(sockaddr)) != 0)
|
||||||
return RESULT_ERROR("connect() failed", false);
|
return RESULT_ERROR(strerror(errno), false);
|
||||||
return RESULT_VOID;
|
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);
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "endpoint.h"
|
#include "endpoint.h"
|
||||||
#include "tlibc/errors.h"
|
#include "tlibc/errors.h"
|
||||||
|
#include "tlibc/collections/Array.h"
|
||||||
|
|
||||||
typedef enum SocketShutdownType {
|
typedef enum SocketShutdownType {
|
||||||
SocketShutdownType_Receive = 0,
|
SocketShutdownType_Receive = 0,
|
||||||
@ -10,10 +11,14 @@ typedef enum SocketShutdownType {
|
|||||||
|
|
||||||
typedef i64 Socket;
|
typedef i64 Socket;
|
||||||
|
|
||||||
Result(Socket) socket_open_TCP();
|
Result(Socket) socket_open_TCP();
|
||||||
void socket_close(Socket s);
|
void socket_close(Socket s);
|
||||||
Result(void) socket_shutdown(Socket s, SocketShutdownType direction);
|
Result(void) socket_shutdown(Socket s, SocketShutdownType direction);
|
||||||
Result(void) socket_bind(Socket s, EndpointIPv4 local_end);
|
Result(void) socket_bind(Socket s, EndpointIPv4 local_end);
|
||||||
Result(void) socket_listen(Socket s, i32 backlog);
|
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_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);
|
||||||
|
|||||||
18
src/network/std_includes.h
Normal file
18
src/network/std_includes.h
Normal 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
|
||||||
Loading…
Reference in New Issue
Block a user