src/lib/tcp_internal.h
author Tero Marttila <terom@fixme.fi>
Thu, 28 May 2009 01:17:36 +0300
branchnew-lib-errors
changeset 219 cefec18b8268
parent 177 src/tcp_internal.h@a74b55104fb9
permissions -rw-r--r--
some of the lib/transport stuff compiles
#ifndef LIBQMSK_TCP_INTERNAL_H
#define LIBQMSK_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 */