/* ====================================================================
* The Kannel Software License, Version 1.0
*
* Copyright (c) 2001-2005 Kannel Group
* Copyright (c) 1998-2001 WapIT Ltd.
* All rights reserved.
*
* 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. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Kannel Group (http://www.kannel.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Kannel" and "Kannel Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please
* contact org@kannel.org.
*
* 5. Products derived from this software may not be called "Kannel",
* nor may "Kannel" appear in their name, without prior written
* permission of the Kannel Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 KANNEL GROUP OR ITS CONTRIBUTORS
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Kannel Group. For more information on
* the Kannel Group, please see .
*
* Portions of this software are based upon software originally written at
* WapIT Ltd., Helsinki, Finland for the Kannel project.
*/
/*
* conn.h - declare Connection type to wrap a file descriptor
*
* This file defines operations on the Connection type, which provides
* input and output buffers for a two-way file descriptor, such as a
* socket or a serial device.
*
* The operations are designed for non-blocking use. Blocking can be
* done explicitly with conn_wait() or conn_flush(). A thread that
* blocks in these functions can be woken up with gwthread_wakeup.
*
* The write operations will queue the data for sending. They will
* try to send whatever data can be sent immediately, if there's enough
* of it queued. "Enough" is defined by a value which can be set with
* conn_set_output_buffering. The caller must call either conn_wait
* or conn_flush to actually send the data.
*
* The read operations will return whatever data is immediately
* available. If none is, then the caller should not simply re-try
* the request (that would cause a busy-loop); instead, it should
* wait for more data with conn_wait().
*
* The Connection structure has internal locks, so it can be shared
* safely between threads. There is a race condition in the interface,
* however, that can cause threads to wait unnecessarily if there are
* multiple readers. But in that case there will always be at least one
* thread busy reading.
*
* The overhead of locking can be avoided by "claiming" a Connection.
* This means that only one thread will ever do operations on that
* Connection; the caller must guarantee this.
*
* If any operation returns a code that indicates that the connection
* is broken (due to an I/O error, normally), it will also have closed
* the connection. Most operations work only on open connections;
* not much can be done with a closed connection except destroy it.
*/
typedef struct Connection Connection;
/* If conn_register was called for this connection, a callback function
* of type conn_callback_t will be called when new input is available,
* or when all data that was previously queued for output is sent.
* The data pointer is the one supplied by the caller of conn_register.
* NOTE: Beware of concurrency issues. The callback function will run
* in the fdset's private thread, not in the caller's thread.
* This also means that if the callback does a lot of work it will slow
* down the polling process. This may be good or bad. */
typedef void conn_callback_t(Connection *conn, void *data);
/*
* If conn_register was called for this connection, a callback data destroyer
* function will be called if conn_unregister, conn_destroy or conn_register
* (with different data) called for this connection.
* This function is responsible to destroy callback data.
*/
typedef void conn_callback_data_destroyer_t(void *data);
#ifdef HAVE_LIBSSL
/* Open an SSL connection to the given host and port. Same behavior
* as conn_open_tcp() below. 'certkeyfile' specifies a PEM-encoded
* file where OpenSSL looks for a private key and a certificate.
*/
Connection *conn_open_ssl(Octstr *host, int port, Octstr *certkeyfile,
Octstr *our_host);
void server_ssl_init(void); /* used by http.c */
#endif /* HAVE_LIBSSL */
/*
* get the SSL config parameters from the provided Config group.
* For a non-SSL system this is a no-op that does nothing.
*/
void conn_config_ssl (CfgGroup *grp);
/* Open a TCP/IP connection to the given host and port. Return the
* new Connection. If the connection can not be made, return NULL
* and log the problem. */
Connection *conn_open_tcp(Octstr *host, int port, Octstr *our_host);
/* As above, but binds our end to 'our_port'. If 'our_port' is 0, uses
* any port like conn_open_tcp. */
Connection *conn_open_tcp_with_port(Octstr *host, int port, int our_port,
Octstr *our_host);
/* Open a TCP/IP connection to the given host and port. Return NULL in case of
* error. Overwise return new Connection. */
Connection *conn_open_tcp_nb(Octstr *host, int port, Octstr *our_host);
/* As above, but binds our end to 'our_port'. If 'our_port' is 0, uses
* any port like conn_open_tcp. */
Connection *conn_open_tcp_nb_with_port(Octstr *host, int port, int our_port,
Octstr *our_host);
/* Returns 0 if socket is connected, -1 overwise */
int conn_is_connected(Connection *conn);
/* If socket is in the 'connecting' state, it must be listen by poller.
* After poller returns, connection must be checked for connection
* procedure's result. Return 0 if connection done successfully */
int conn_get_connect_result(Connection *conn);
/* Create a Connection structure around the given file descriptor.
* The file descriptor must not be used for anything else after this;
* it must always be accessed via the Connection operations. This
* operation cannot fail. Second var indicates if the is a SSL enabled
* connection. */
Connection *conn_wrap_fd(int fd, int ssl);
/* Close and deallocate a Connection. Log any errors reported by
* the close operation. */
void conn_destroy(Connection *conn);
/* Assert that the calling thread will be the only one to ever
* use this Connection. From now on no locking will be done
* on this Connection.
* It is a fatal error for two threads to try to claim one Connection,
* or for another thread to try to use a Connection that has been claimed.
*/
void conn_claim(Connection *conn);
/* Return the length of the unsent data queued for sending, in octets. */
long conn_outbuf_len(Connection *conn);
/* Return the length of the unprocessed data ready for reading, in octets. */
long conn_inbuf_len(Connection *conn);
/* Return 1 if there was an end-of-file indication from the last read or
* wait operation. */
int conn_eof(Connection *conn);
/* Return 1 if there was an error indication from the last read or wait
* operation. */
int conn_error(Connection *conn);
/* Try to write data in chunks of this size or more. Set it to 0 to
* get an unbuffered connection. See the discussion on output buffering
* at the top of this file for more information. */
void conn_set_output_buffering(Connection *conn, unsigned int size);
/* Register this connection with an FDSet. This will make it unnecessary
* to call conn_wait. Instead, the callback function will be called when
* there is new data available, or when all data queued for output is
* sent (note that small amounts are usually sent immediately without
* queuing, and thus won't trigger the callback). A connection can be
* registered with only one FDSet at a time. Return -1 if it was
* already registered with a different FDSet, otherwise return 0.
* A connection can be re-registered with the same FDSet. This will
* change only the callback information, and is much more efficient
* than calling conn_unregister first.
* NOTE: Using conn_register will always mean that the Connection will be
* used by more than one thread, so don't also call conn_claim. */
#define conn_register(conn, fdset, callback, data) \
conn_register_real(conn, fdset, callback, data, NULL)
int conn_register_real(Connection *conn, FDSet *fdset,
conn_callback_t callback, void *data, conn_callback_data_destroyer_t destroyer);
/*
* Remove the current registration and call data destroyer if not NULL.
*/
void conn_unregister(Connection *conn);
/* Block the thread until one of the following is true:
* - The timeout expires
* - New data is available for reading
* - Some data queued for output is sent (if there was any)
* - The thread is woken up via the wakeup interface (in gwthread.h)
* Return 1 if the timeout expired. Return 0 otherwise, if the
* connection is okay. Return -1 if the connection is broken.
* If the timeout is 0 seconds, check for the conditions above without
* actually blocking. If it is negative, block indefinitely.
*/
int conn_wait(Connection *conn, double seconds);
/* Try to send all data currently queued for output. Block until this
* is done, or until the thread is interrupted or woken up. Return 0
* if it worked, 1 if there was an interruption, or -1 if the connection
* is broken. */
int conn_flush(Connection *conn);
/* Output functions. Each of these takes an open connection and some
* data, formats the data and queues it for sending. It may also
* try to send the data immediately. The current implementation always
* does so.
* Return 0 if the data was sent, 1 if it was queued for sending,
* and -1 if the connection is broken.
*/
int conn_write(Connection *conn, Octstr *data);
int conn_write_data(Connection *conn, unsigned char *data, long length);
/* Write the length of the octstr as a standard network long, then
* write the octstr itself. */
int conn_write_withlen(Connection *conn, Octstr *data);
/* Input functions. Each of these takes an open connection and
* returns data if it's available, or NULL if it's not. They will
* not block. They will try to read in more data if there's not
* enough in the buffer to fill the request. */
/* Return whatever data is available. */
Octstr *conn_read_everything(Connection *conn);
/* Return exactly "length" octets of data, if at least that many
* are available. Otherwise return NULL.
*/
Octstr *conn_read_fixed(Connection *conn, long length);
/* If the input buffer starts with a full line of data (terminated by
* LF or CR LF), then return that line as an Octstr and remove it
* from the input buffer. Otherwise return NULL.
*/
Octstr *conn_read_line(Connection *conn);
/* Read a standard network long giving the length of the following
* data, then read the data itself, and pack it into an Octstr and
* remove it from the input buffer. Otherwise return NULL.
*/
Octstr *conn_read_withlen(Connection *conn);
/* If the input buffer contains a packet delimited by the "startmark"
* and "endmark" characters, then return that packet (including the marks)
* and delete everything up to the end of that packet from the input buffer.
* Otherwise return NULL.
* Everything up to the first startmark is discarded.
*/
Octstr *conn_read_packet(Connection *conn, int startmark, int endmark);
#ifdef HAVE_LIBSSL
#include
#include
/* Returns the SSL peer certificate for the given Connection or NULL
* if none.
*/
X509 *get_peer_certificate(Connection *conn);
/* These are called to initialize and shutdown the OpenSSL mutex locks.
* They should be called before the _init_ssl, _shutdown_ssl functions.
*/
void openssl_init_locks(void);
void openssl_shutdown_locks(void);
/* These must be called if SSL is used. Currently http.c calls
* conn_init_ssl and server_init_ssl from http_init and
* conn_shutdown_ssl and server_shutdown_ssl from http_shutdown.
*/
void conn_init_ssl(void);
void conn_shutdown_ssl(void);
void server_init_ssl(void);
void server_shutdown_ssl(void);
/* Specifies a global PEM-encoded certificate and a private key file
* to be used with SSL client connections (outgoing HTTP requests).
* conn_init_ssl() must be called first. This checks that the private
* key matches with the certificate and will panic if it doesn't.
*/
void use_global_client_certkey_file(Octstr *certkeyfile);
/* Specifies a global PEM-encoded certificate and a private key file
* to be used with SSL server connections (incoming HTTP requests).
* conn_init_ssl() must be called first. This checks that the private
* key matches with the certificate and will panic if it doesn't.
*/
void use_global_server_certkey_file(Octstr *certfile, Octstr *keyfile);
/* Specifies files containing certificates Kannel is willing to trusted when
* actins as https clients
*/
void use_global_trusted_ca_file(Octstr *ssl_trusted_ca_file);
/* Configures all global variables for client and server SSL mode
* from the values specified within the configuration file.
*/
void conn_config_ssl(CfgGroup *grp);
/* Returns the pointer to the SSL structure of the Connection given.
* This should be used for determining if certain connections are
* SSL enabled outside of the scope of conn.c.
*/
SSL *conn_get_ssl(Connection *conn);
X509 *conn_get_peer_certificate(Connection *conn);
#endif /* HAVE_LIBSSL */
int conn_get_id(Connection *conn);