370 lines
12 KiB
C
370 lines
12 KiB
C
|
/**
|
||
|
* @file BConnection.h
|
||
|
* @author Ambroz Bizjak <ambrop7@gmail.com>
|
||
|
*
|
||
|
* @section LICENSE
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. Neither the name of the author nor the
|
||
|
* names of its contributors may be used to endorse or promote products
|
||
|
* derived from this software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#ifndef BADVPN_SYSTEM_BCONNECTION
|
||
|
#define BADVPN_SYSTEM_BCONNECTION
|
||
|
|
||
|
#include <misc/debug.h>
|
||
|
#include <flow/StreamPassInterface.h>
|
||
|
#include <flow/StreamRecvInterface.h>
|
||
|
#include <system/BAddr.h>
|
||
|
#include <system/BReactor.h>
|
||
|
#include <system/BNetwork.h>
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Checks if the given address is supported by {@link BConnection} and related objects.
|
||
|
*
|
||
|
* @param addr address to check. Must be a proper {@link BAddr} object according to
|
||
|
* {@link BIPAddr_Assert}.
|
||
|
* @return 1 if supported, 0 if not
|
||
|
*/
|
||
|
int BConnection_AddressSupported (BAddr addr);
|
||
|
|
||
|
|
||
|
|
||
|
struct BListener_s;
|
||
|
|
||
|
/**
|
||
|
* Object which listens for connections on an address.
|
||
|
* When a connection is ready, the {@link BListener_handler} handler is called, from which
|
||
|
* the connection can be accepted into a new {@link BConnection} object.
|
||
|
*/
|
||
|
typedef struct BListener_s BListener;
|
||
|
|
||
|
/**
|
||
|
* Handler called when a new connection is ready.
|
||
|
* The connection can be accepted by calling {@link BConnection_Init} with the a
|
||
|
* BCONNECTION_SOURCE_LISTENER 'source' argument.
|
||
|
* If no attempt is made to accept the connection from the job closure of this handler,
|
||
|
* the connection will be discarded.
|
||
|
*
|
||
|
* @param user as in {@link BListener_Init}
|
||
|
*/
|
||
|
typedef void (*BListener_handler) (void *user);
|
||
|
|
||
|
/**
|
||
|
* Initializes the object.
|
||
|
* {@link BNetwork_GlobalInit} must have been done.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param addr address to listen on
|
||
|
* @param reactor reactor we live in
|
||
|
* @param user argument to handler
|
||
|
* @param handler handler called when a connection can be accepted
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
|
||
|
BListener_handler handler) WARN_UNUSED;
|
||
|
|
||
|
#ifndef BADVPN_USE_WINAPI
|
||
|
/**
|
||
|
* Initializes the object for listening on a Unix socket.
|
||
|
* {@link BNetwork_GlobalInit} must have been done.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param socket_path socket path for listening
|
||
|
* @param reactor reactor we live in
|
||
|
* @param user argument to handler
|
||
|
* @param handler handler called when a connection can be accepted
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor, void *user,
|
||
|
BListener_handler handler) WARN_UNUSED;
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* Frees the object.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BListener_Free (BListener *o);
|
||
|
|
||
|
|
||
|
|
||
|
struct BConnector_s;
|
||
|
|
||
|
/**
|
||
|
* Object which connects to an address.
|
||
|
* When the connection attempt finishes, the {@link BConnector_handler} handler is called, from which,
|
||
|
* if successful, the resulting connection can be moved to a new {@link BConnection} object.
|
||
|
*/
|
||
|
typedef struct BConnector_s BConnector;
|
||
|
|
||
|
/**
|
||
|
* Handler called when the connection attempt finishes.
|
||
|
* If the connection attempt succeeded (is_error==0), the new connection can be used by calling
|
||
|
* {@link BConnection_Init} with a BCONNECTION_SOURCE_TYPE_CONNECTOR 'source' argument.
|
||
|
* This handler will be called at most once. The connector object need not be freed after it
|
||
|
* is called.
|
||
|
*
|
||
|
* @param user as in {@link BConnector_Init}
|
||
|
* @param is_error whether the connection attempt succeeded (0) or failed (1)
|
||
|
*/
|
||
|
typedef void (*BConnector_handler) (void *user, int is_error);
|
||
|
|
||
|
/**
|
||
|
* Initializes the object.
|
||
|
* {@link BNetwork_GlobalInit} must have been done.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param addr address to connect to
|
||
|
* @param reactor reactor we live in
|
||
|
* @param user argument to handler
|
||
|
* @param handler handler called when the connection attempt finishes
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
|
||
|
BConnector_handler handler) WARN_UNUSED;
|
||
|
|
||
|
#ifndef BADVPN_USE_WINAPI
|
||
|
/**
|
||
|
* Initializes the object for connecting to a Unix socket.
|
||
|
* {@link BNetwork_GlobalInit} must have been done.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param socket_path socket path for connecting
|
||
|
* @param reactor reactor we live in
|
||
|
* @param user argument to handler
|
||
|
* @param handler handler called when the connection attempt finishes
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *reactor, void *user,
|
||
|
BConnector_handler handler) WARN_UNUSED;
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* Frees the object.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnector_Free (BConnector *o);
|
||
|
|
||
|
|
||
|
|
||
|
#define BCONNECTION_SOURCE_TYPE_LISTENER 1
|
||
|
#define BCONNECTION_SOURCE_TYPE_CONNECTOR 2
|
||
|
#define BCONNECTION_SOURCE_TYPE_PIPE 3
|
||
|
|
||
|
struct BConnection_source {
|
||
|
int type;
|
||
|
union {
|
||
|
struct {
|
||
|
BListener *listener;
|
||
|
BAddr *out_addr;
|
||
|
} listener;
|
||
|
struct {
|
||
|
BConnector *connector;
|
||
|
} connector;
|
||
|
#ifndef BADVPN_USE_WINAPI
|
||
|
struct {
|
||
|
int pipefd;
|
||
|
} pipe;
|
||
|
#endif
|
||
|
} u;
|
||
|
};
|
||
|
|
||
|
static struct BConnection_source BConnection_source_listener (BListener *listener, BAddr *out_addr)
|
||
|
{
|
||
|
struct BConnection_source s;
|
||
|
s.type = BCONNECTION_SOURCE_TYPE_LISTENER;
|
||
|
s.u.listener.listener = listener;
|
||
|
s.u.listener.out_addr = out_addr;
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
static struct BConnection_source BConnection_source_connector (BConnector *connector)
|
||
|
{
|
||
|
struct BConnection_source s;
|
||
|
s.type = BCONNECTION_SOURCE_TYPE_CONNECTOR;
|
||
|
s.u.connector.connector = connector;
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
#ifndef BADVPN_USE_WINAPI
|
||
|
static struct BConnection_source BConnection_source_pipe (int pipefd)
|
||
|
{
|
||
|
struct BConnection_source s;
|
||
|
s.type = BCONNECTION_SOURCE_TYPE_PIPE;
|
||
|
s.u.pipe.pipefd = pipefd;
|
||
|
return s;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
struct BConnection_s;
|
||
|
|
||
|
/**
|
||
|
* Object which represents a stream connection. This is usually a TCP connection, either client
|
||
|
* or server, but may also be used with any file descriptor (e.g. pipe) on Unix-like systems.
|
||
|
* Sending and receiving is performed via {@link StreamPassInterface} and {@link StreamRecvInterface},
|
||
|
* respectively.
|
||
|
*/
|
||
|
typedef struct BConnection_s BConnection;
|
||
|
|
||
|
#define BCONNECTION_EVENT_ERROR 1
|
||
|
#define BCONNECTION_EVENT_RECVCLOSED 2
|
||
|
|
||
|
/**
|
||
|
* Handler called when an error occurs or the receive end of the connection was closed
|
||
|
* by the remote peer.
|
||
|
* - If event is BCONNECTION_EVENT_ERROR, the connection is no longer usable and must be freed
|
||
|
* from withing the job closure of this handler. No further I/O or interface initialization
|
||
|
* must occur.
|
||
|
* - If event is BCONNECTION_EVENT_RECVCLOSED, no further receive I/O or receive interface
|
||
|
* initialization must occur. It is guarantted that the receive interface was initialized.
|
||
|
*
|
||
|
* @param user as in {@link BConnection_Init} or {@link BConnection_SetHandlers}
|
||
|
* @param event what happened - BCONNECTION_EVENT_ERROR or BCONNECTION_EVENT_RECVCLOSED
|
||
|
*/
|
||
|
typedef void (*BConnection_handler) (void *user, int event);
|
||
|
|
||
|
/**
|
||
|
* Initializes the object.
|
||
|
* {@link BNetwork_GlobalInit} must have been done.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param source specifies what the connection comes from. This argument must be created with one of the
|
||
|
* following macros:
|
||
|
* - BCONNECTION_SOURCE_LISTENER(BListener *, BAddr *)
|
||
|
* Accepts a connection ready on a {@link BListener} object. Must be called from the job
|
||
|
* closure of the listener's {@link BListener_handler}, and must be the first attempt
|
||
|
* for this handler invocation. The address of the client is written if the address
|
||
|
* argument is not NULL (theoretically an invalid address may be returned).
|
||
|
* - BCONNECTION_SOURCE_CONNECTOR(Bconnector *)
|
||
|
* Uses a connection establised with {@link BConnector}. Must be called from the job
|
||
|
* closure of the connector's {@link BConnector_handler}, the handler must be reporting
|
||
|
* successful connection, and must be the first attempt for this handler invocation.
|
||
|
* - BCONNECTION_SOURCE_PIPE(int)
|
||
|
* On Unix-like systems, uses the provided file descriptor. The file descriptor number must
|
||
|
* be >=0.
|
||
|
* @param reactor reactor we live in
|
||
|
* @param user argument to handler
|
||
|
* @param handler handler called when an error occurs or the receive end of the connection was closed
|
||
|
* by the remote peer.
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BConnection_Init (BConnection *o, struct BConnection_source source, BReactor *reactor, void *user,
|
||
|
BConnection_handler handler) WARN_UNUSED;
|
||
|
|
||
|
/**
|
||
|
* Frees the object.
|
||
|
* The send and receive interfaces must not be initialized.
|
||
|
* If the connection was created with a BCONNECTION_SOURCE_PIPE 'source' argument, the file descriptor
|
||
|
* will not be closed.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnection_Free (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Updates the handler function.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param user argument to handler
|
||
|
* @param handler new handler function, as in {@link BConnection_Init}. Additionally, may be NULL to
|
||
|
* remove the current handler. In this case, a proper handler must be set before anything
|
||
|
* can happen with the connection. This is used when moving the connection ownership from
|
||
|
* one module to another.
|
||
|
*/
|
||
|
void BConnection_SetHandlers (BConnection *o, void *user, BConnection_handler handler);
|
||
|
|
||
|
/**
|
||
|
* Sets the SO_SNDBUF socket option.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @param buf_size value for SO_SNDBUF option
|
||
|
* @return 1 on success, 0 on failure
|
||
|
*/
|
||
|
int BConnection_SetSendBuffer (BConnection *o, int buf_size);
|
||
|
|
||
|
/**
|
||
|
* Initializes the send interface for the connection.
|
||
|
* The send interface must not be initialized.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnection_SendAsync_Init (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Frees the send interface for the connection.
|
||
|
* The send interface must be initialized.
|
||
|
* If the send interface was busy when this is called, the connection is no longer usable and must be
|
||
|
* freed before any further I/O or interface initialization.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnection_SendAsync_Free (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Returns the send interface.
|
||
|
* The send interface must be initialized.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @return send interface
|
||
|
*/
|
||
|
StreamPassInterface * BConnection_SendAsync_GetIf (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Initializes the receive interface for the connection.
|
||
|
* The receive interface must not be initialized.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnection_RecvAsync_Init (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Frees the receive interface for the connection.
|
||
|
* The receive interface must be initialized.
|
||
|
* If the receive interface was busy when this is called, the connection is no longer usable and must be
|
||
|
* freed before any further I/O or interface initialization.
|
||
|
*
|
||
|
* @param o the object
|
||
|
*/
|
||
|
void BConnection_RecvAsync_Free (BConnection *o);
|
||
|
|
||
|
/**
|
||
|
* Returns the receive interface.
|
||
|
* The receive interface must be initialized.
|
||
|
*
|
||
|
* @param o the object
|
||
|
* @return receive interface
|
||
|
*/
|
||
|
StreamRecvInterface * BConnection_RecvAsync_GetIf (BConnection *o);
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef BADVPN_USE_WINAPI
|
||
|
#include "BConnection_win.h"
|
||
|
#else
|
||
|
#include "BConnection_unix.h"
|
||
|
#endif
|
||
|
|
||
|
#endif
|