162 lines
5.9 KiB
C
162 lines
5.9 KiB
C
#ifndef INCLUDED_C_TCPCLIENT_H
|
|||
|
|
#define INCLUDED_C_TCPCLIENT_H
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_SOCKET_H
|
||
|
|
#include <c_Socket.h>
|
||
|
|
#endif /*INCLUDED_C_SOCKET_H*/
|
||
|
|
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_ALLOCATOR_H
|
||
|
|
#include <c_Allocator.h>
|
||
|
|
#endif /*INCLUDED_C_ALLOCATOR_H*/
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
#define C_TCPCLIENT_ERR_ON_POLL 1001
|
||
|
|
#define C_TCPCLIENT_ERR_ON_ACCEPT 1002
|
||
|
|
#define C_TCPCLIENT_ERR_ON_POLLERR 1003
|
||
|
|
#define C_TCPCLIENT_ERR_ON_RECV 1004
|
||
|
|
#define C_TCPCLIENT_ERR_ON_CONNECT 1005
|
||
|
|
|
||
|
|
#define C_TCPCLIENT_INITIALIZE {0}
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
typedef struct c_TcpClient_t c_TcpClient_t;
|
||
|
|
|
||
|
|
typedef bool (*c_TcpClient_OnConnect_t)(c_TcpClient_t* client, void* args);
|
||
|
|
typedef bool (*c_TcpClient_OnData_t)(c_TcpClient_t* client, void* args);
|
||
|
|
typedef void (*c_TcpClient_OnDisconnect_t)(c_TcpClient_t* client, void* args);
|
||
|
|
typedef void (*c_TcpClient_OnError_t)(c_TcpClient_t* client, c_err_t error_code, void* args);
|
||
|
|
|
||
|
|
typedef struct c_TcpClientReactor_t c_TcpClientReactor_t;
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
c_err_t (*add)(c_TcpClientReactor_t* self, c_socket_t sock, uint32_t events);
|
||
|
|
c_err_t (*remove)(c_TcpClientReactor_t* self, c_socket_t sock);
|
||
|
|
c_err_t (*poll)(c_TcpClientReactor_t* self, long timeout_ms, c_TcpClient_t* client, void* args);
|
||
|
|
void (*destroy)(c_TcpClientReactor_t* self);
|
||
|
|
} c_TcpClientReactorVtbl_t;
|
||
|
|
|
||
|
|
struct c_TcpClientReactor_t {
|
||
|
|
const c_TcpClientReactorVtbl_t* vtbl;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct c_TcpClient_t {
|
||
|
|
c_socket_t sock;
|
||
|
|
c_bool_t is_linked;
|
||
|
|
c_TcpClientReactor_t* reactor;
|
||
|
|
c_TcpClient_OnConnect_t fnOnConnect;
|
||
|
|
c_TcpClient_OnData_t fnOnData;
|
||
|
|
c_TcpClient_OnDisconnect_t fnOnDisconnect;
|
||
|
|
c_TcpClient_OnError_t fnOnError;
|
||
|
|
c_Allocator_t allocator;
|
||
|
|
};
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
c_err_t c_TcpClientReactor_Add(c_TcpClientReactor_t* self, c_socket_t sock, uint32_t events) {
|
||
|
|
if (!self || !self->vtbl || !self->vtbl->add || !c_Socket_IsValid(sock)) return C_ERR_PARAM;
|
||
|
|
return self->vtbl->add(self, sock, events);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
c_err_t c_TcpClientReactor_Remove(c_TcpClientReactor_t* self, c_socket_t sock) {
|
||
|
|
if (!self || !self->vtbl || !self->vtbl->remove || !c_Socket_IsValid(sock)) return C_ERR_PARAM;
|
||
|
|
return self->vtbl->remove(self, sock);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
c_err_t c_TcpClientReactor_Poll(c_TcpClientReactor_t* self, long timeout_ms, c_TcpClient_t* client, void* args) {
|
||
|
|
if (!self || !self->vtbl || !self->vtbl->poll || !client) return C_ERR_PARAM;
|
||
|
|
return self->vtbl->poll(self, timeout_ms, client, args);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClientReactor_Destroy(c_TcpClientReactor_t* self) {
|
||
|
|
if (!self || !self->vtbl || !self->vtbl->destroy) return;
|
||
|
|
self->vtbl->destroy(self);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Establishes a synchronous stream connection to a remote server host.
|
||
|
|
* @param family Address family (e.g., AF_INET, AF_INET6, or AF_UNSPEC)
|
||
|
|
* @param server Host destination string (e.g., "127.0.0.1" or "domain.com")
|
||
|
|
* @param port Service port string identifier (e.g., "8080")
|
||
|
|
* @param args User defined arguments
|
||
|
|
* @param allocator Explicit allocator context used to configure socket instances
|
||
|
|
*/
|
||
|
|
c_err_t c_TcpClient_Connect(c_TcpClient_t* self, int family, const char* server, const char* port,
|
||
|
|
void* args,
|
||
|
|
c_Allocator_t* allocator);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Sends a raw data block across the socket, looping until the full buffer is dispatched.
|
||
|
|
* @param buffer Pointer to the source data block payload to transmit.
|
||
|
|
* @param bytes_to_send Exact size threshold of the payload block in bytes.
|
||
|
|
* @param out_bytes_sent Receives the actual number of bytes written out to the wire.
|
||
|
|
*/
|
||
|
|
c_err_t c_TcpClient_Send(c_TcpClient_t* self, const void* buffer, c_size_t bytes_to_send, c_size_t* out_bytes_sent);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Reads a data block up to the requested size from the socket channel.
|
||
|
|
* @param buffer Pointer to the destination buffer to hold incoming data.
|
||
|
|
* @param max_bytes_to_read Upper ceiling threshold size of bytes to pull.
|
||
|
|
* @param out_bytes_read Receives the actual number of bytes fetched from the wire.
|
||
|
|
*/
|
||
|
|
c_err_t c_TcpClient_Recv(c_TcpClient_t* self, void* buffer, c_size_t max_bytes_to_read, c_size_t* out_bytes_read);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Safely shuts down pipelines, closes active sockets, and recycles memory.
|
||
|
|
*/
|
||
|
|
void c_TcpClient_Destroy(c_TcpClient_t* self);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Executes a non-recursive, single-pass asynchronous polling event dispatch iteration for the client.
|
||
|
|
*/
|
||
|
|
c_err_t c_TcpClient_PollEvents(c_TcpClient_t* self, long timeout_ms, void* args);
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClient_SetReactor(c_TcpClient_t* self, c_TcpClientReactor_t* reactor) {
|
||
|
|
if (!self || !reactor) return;
|
||
|
|
self->reactor = reactor;
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClient_SetOnConnect(c_TcpClient_t* self, c_TcpClient_OnConnect_t fnOnConnect) {
|
||
|
|
if (!self ) return;
|
||
|
|
self->fnOnConnect = fnOnConnect;
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClient_SetOnData(c_TcpClient_t* self, c_TcpClient_OnData_t fnOnData) {
|
||
|
|
if (!self ) return;
|
||
|
|
self->fnOnData = fnOnData;
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClient_SetOnDisconnect(c_TcpClient_t* self, c_TcpClient_OnDisconnect_t fnOnDisconnect) {
|
||
|
|
if (!self ) return;
|
||
|
|
self->fnOnDisconnect = fnOnDisconnect;
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
void c_TcpClient_SetOnError(c_TcpClient_t* self, c_TcpClient_OnError_t fnOnError) {
|
||
|
|
if (!self ) return;
|
||
|
|
self->fnOnError = fnOnError;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif /*INCLUDED_C_TCPCLIENT_H*/
|