#ifndef TCP_INTERNAL_H
#define TCP_INTERNAL_H
/**
* @file
*
* Internal TCP interface for implementations
*/
#include "tcp.h"
#include "resolve.h"
#include "transport_fd.h"
#include "transport_internal.h"
#include "service_internal.h"
#include "error.h"
#include <event2/event.h>
#include <event2/util.h>
/**
* Create a new socket() using the given addr's family/socktype/protocol and return it.
*
* In case of errors, this returns -err_t
*
* @param addr the addrinfo to create the socket for
* @param err returned error info
* @return new fd on success, -err_t on error
*/
int tcp_sock_create (const struct addrinfo *addr, error_t *err);
/**
* Return the socket's current error code via err->extra.
*
* In case getting the socket error code itself fails, this will return normal error code/info.
*
* Otherwise, this will return SUCCESS, with the errno value stored in err->extra.
*/
err_t tcp_sock_error (evutil_socket_t sock, error_t *err);
/**
* TCP transport type
*/
extern const struct transport_type tcp_transport_type;
/**
* Base TCP transport
*
* XXX: currently just the same as transport_fd, but this will probably change
*/
struct tcp_transport {
/** Base FD-based implementation */
struct transport_fd base_fd;
};
/**
* Initialize the tcp_transport state.
*
* This initializes the transport_fd base using the global sock_ctx::ev_base and the given socket.
*/
void tcp_transport_init (struct tcp_transport *trans, evutil_socket_t sock);
/**
* Create a new tcp_transport with the given sock.
*
* For convenience, this will also make the sock nonblocking.
*
* In case of errors, this will the socket.
*
* @param trans_ptr returned tcp_transport
* @param info the transport user settings
* @param sock the unused TCP socket
* @param err returned error info
*/
err_t tcp_transport_create (struct tcp_transport **trans_ptr, const struct transport_info *info, evutil_socket_t sock, error_t *err);
/**
* The transport as now connected, this sets up the intitial user settings, and invokes the callback.
*
* XXX: this does an 'indirect' call to transport_connected().
*
* @param err returned error info
*/
err_t tcp_transport_connected (struct tcp_transport *trans, error_t *err);
/**
* Deinitialize the transport state, terminating the connection and releasing resources.
*/
void tcp_transport_deinit (struct tcp_transport *trans);
/**
* Deinitialize and free the given tcp_transport
*/
void tcp_transport_destroy (struct tcp_transport *trans);
/**
* TCP client transport type
*/
extern const struct transport_type tcp_client_type;
/**
* TCP client state
*/
struct tcp_client {
/** Base transport stuff */
struct tcp_transport base_trans;
/** The resolver lookup result for the async connect process */
struct resolve_result rr;
};
/**
* Initialize the tcp_client state
*/
void tcp_client_init (struct tcp_client *client);
/**
* Attempt to connect asyncronously to the given hostname/service. Once a connection has been established, this will
* call transport_connected(), so you can register transport_methods::_connected if layering on top of TCP.
*
* In case of errors while starting the async connect process, an error code will be returned. If the connect fails
* later on, transport_connected() will be called with the error code.
*
* The sock must have been initialized using sock_tcp_init().
*
* @param client the unconnected TCP client socket to connect with
* @param hostname the hostname to resolve
* @param service the service to connect to
* @param err returned error info for immediate errors
*/
err_t tcp_client_connect_async (struct tcp_client *client, const char *hostname, const char *service, error_t *err);
/**
* Deinitialize the tcp_client's state, including the tcp_transport state.
*/
void tcp_client_deinit (struct tcp_client *client);
/**
* TCP service type
*/
extern const struct service_type tcp_server_type;
/**
* TCP service state
*/
struct tcp_server {
/** Base service state */
struct service base_service;
/** The input event with our listen() socket */
struct event *ev;
};
/**
* The listen() backlog
*/
#define TCP_SERVER_BACKLOG 5
/**
* Open the listening socket on the given interface/service.
*/
err_t tcp_server_listen (struct tcp_server *serv, const char *interface, const char *service, error_t *err);
/**
* Release the tcp_server's state, and cleanup the struct.
*/
void tcp_server_deinit (struct tcp_server *serv);
#endif /* TCP_INTERNAL_H */