feat(nopoll): Move nopoll to components

This commit is contained in:
Dong Heng
2018-04-04 17:24:40 +08:00
committed by Wu Jian Gang
parent 336f8bd969
commit 00646afc27
27 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,135 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_H__
#define __NOPOLL_H__
#include <nopoll_decl.h>
#include <nopoll_handlers.h>
BEGIN_C_DECLS
#if defined(NOPOLL_OS_WIN32)
#include <nopoll_win32.h>
#endif
#include <nopoll_ctx.h>
#include <nopoll_io.h>
#include <nopoll_conn_opts.h>
#include <nopoll_conn.h>
#include <nopoll_msg.h>
#include <nopoll_log.h>
#include <nopoll_listener.h>
#include <nopoll_io.h>
#include <nopoll_loop.h>
/**
* \addtogroup nopoll_module
* @{
*/
nopoll_bool nopoll_cmp (const char * string1, const char * string2);
nopoll_bool nopoll_ncmp (const char * string1, const char * string2, int bytes);
char * nopoll_strdup_printf (const char * chunk, ...);
char * nopoll_strdup_printfv (const char * chunk, va_list args);
void nopoll_trim (char * chunk, int * trimmed);
void nopoll_sleep (long microseconds);
void nopoll_thread_handlers (noPollMutexCreate mutex_create,
noPollMutexDestroy mutex_destroy,
noPollMutexLock mutex_lock,
noPollMutexUnlock mutex_unlock);
noPollPtr nopoll_mutex_create (void);
void nopoll_mutex_lock (noPollPtr mutex);
void nopoll_mutex_unlock (noPollPtr mutex);
void nopoll_mutex_destroy (noPollPtr mutex);
nopoll_bool nopoll_base64_encode (const char * content,
int length,
char * output,
int * output_size);
nopoll_bool nopoll_base64_decode (const char * content,
int length,
char * output,
int * output_size);
int nopoll_timeval_substract (struct timeval * a,
struct timeval * b,
struct timeval * result);
char * nopoll_strdup (const char * buffer);
nopoll_bool nopoll_nonce (char * buffer, int nonce_size);
void nopoll_cleanup_library (void);
int nopoll_get_bit (char byte, int position);
void nopoll_set_bit (char * buffer, int position);
void nopoll_show_byte (noPollCtx * ctx, char byte, const char * label);
char * nopoll_int2bin (int a, char *buffer, int buf_size);
void nopoll_int2bin_print (noPollCtx * ctx, int value);
int nopoll_get_8bit (const char * buffer);
int nopoll_get_16bit (const char * buffer);
void nopoll_set_16bit (int value, char * buffer);
void nopoll_set_32bit (int value, char * buffer);
int nopoll_get_32bit (const char * buffer);
/* @} */
END_C_DECLS
#endif

View File

@ -0,0 +1,67 @@
/*
* Nopoll Library nopoll_config.h
* Platform dependant definitions.
*
* This is a generated file. Please modify 'configure.in'
*/
#ifndef __NOPOLL_CONFIG_H__
#define __NOPOLL_CONFIG_H__
/**
* \addtogroup nopoll_decl_module
* @{
*/
/**
* @brief Allows to convert integer value (including constant values)
* into a pointer representation.
*
* Use the oposite function to restore the value from a pointer to a
* integer: \ref PTR_TO_INT.
*
* @param integer The integer value to cast to pointer.
*
* @return A \ref noPollPtr reference.
*/
#ifndef INT_TO_PTR
#define INT_TO_PTR(integer) ((noPollPtr) (long) ((int)integer))
#endif
/**
* @brief Allows to convert a pointer reference (\ref noPollPtr),
* which stores an integer that was stored using \ref INT_TO_PTR.
*
* Use the oposite function to restore the pointer value stored in the
* integer value.
*
* @param ptr The pointer to cast to a integer value.
*
* @return A int value.
*/
#ifndef PTR_TO_INT
#define PTR_TO_INT(ptr) ((int) (long) (ptr))
#endif
/**
* @brief Allows to get current platform configuration. This is used
* by Nopoll library but could be used by applications built on top of
* Nopoll to change its configuration based on the platform information.
*/
#define NOPOLL_OS_UNIX (0)
/**
* @internal Allows to now if the platform support vasprintf
* function. Do not use this macro as it is supposed to be for
* internal use.
*/
//#define NOPOLL_HAVE_VASPRINTF (1)
/**
* @brief Indicates that this platform have support for 64bits.
*/
//#define NOPOLL_64BIT_PLATFORM (0)
/* @} */
#endif

View File

@ -0,0 +1,198 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_CONN_H__
#define __NOPOLL_CONN_H__
#include <nopoll.h>
BEGIN_C_DECLS
noPollConn * nopoll_conn_new (noPollCtx * ctx,
const char * host_ip,
const char * host_port,
const char * host_name,
const char * get_url,
const char * protocols,
const char * origin);
noPollConn * nopoll_conn_new_opts (noPollCtx * ctx,
noPollConnOpts * opts,
const char * host_ip,
const char * host_port,
const char * host_name,
const char * get_url,
const char * protocols,
const char * origin);
noPollConn * nopoll_conn_tls_new (noPollCtx * ctx,
noPollConnOpts * options,
const char * host_ip,
const char * host_port,
const char * host_name,
const char * get_url,
const char * protocols,
const char * origin);
noPollConn * nopoll_conn_accept (noPollCtx * ctx, noPollConn * listener);
noPollConn * nopoll_conn_accept_socket (noPollCtx * ctx, noPollConn * listener, NOPOLL_SOCKET session);
nopoll_bool nopoll_conn_accept_complete (noPollCtx * ctx,
noPollConn * listener,
noPollConn * conn,
NOPOLL_SOCKET session,
nopoll_bool tls_on);
nopoll_bool nopoll_conn_ref (noPollConn * conn);
int nopoll_conn_ref_count (noPollConn * conn);
void nopoll_conn_unref (noPollConn * conn);
nopoll_bool nopoll_conn_is_ok (noPollConn * conn);
nopoll_bool nopoll_conn_is_ready (noPollConn * conn);
nopoll_bool nopoll_conn_is_tls_on (noPollConn * conn);
NOPOLL_SOCKET nopoll_conn_socket (noPollConn * conn);
void nopoll_conn_set_socket (noPollConn * conn, NOPOLL_SOCKET _socket);
int nopoll_conn_get_id (noPollConn * conn);
noPollCtx * nopoll_conn_ctx (noPollConn * conn);
noPollRole nopoll_conn_role (noPollConn * conn);
const char * nopoll_conn_host (noPollConn * conn);
const char * nopoll_conn_port (noPollConn * conn);
const char * nopoll_conn_get_origin (noPollConn * conn);
const char * nopoll_conn_get_host_header (noPollConn * conn);
const char * nopoll_conn_get_cookie (noPollConn * conn);
const char * nopoll_conn_get_accepted_protocol (noPollConn * conn);
const char * nopoll_conn_get_requested_protocol (noPollConn * conn);
void nopoll_conn_set_accepted_protocol (noPollConn * conn, const char * protocol);
int nopoll_conn_get_close_status (noPollConn * conn);
const char * nopoll_conn_get_close_reason (noPollConn * conn);
void nopoll_conn_shutdown (noPollConn * conn);
void nopoll_conn_close (noPollConn * conn);
void nopoll_conn_close_ext (noPollConn * conn, int status, const char * reason, int reason_size);
void nopoll_conn_set_hook (noPollConn * conn, noPollPtr ptr);
noPollPtr nopoll_conn_get_hook (noPollConn * conn);
nopoll_bool nopoll_conn_set_sock_block (NOPOLL_SOCKET socket,
nopoll_bool enable);
noPollMsg * nopoll_conn_get_msg (noPollConn * conn);
int nopoll_conn_send_text (noPollConn * conn, const char * content, long length);
int nopoll_conn_send_text_fragment (noPollConn * conn, const char * content, long length);
int nopoll_conn_send_binary (noPollConn * conn, const char * content, long length);
int nopoll_conn_send_binary_fragment (noPollConn * conn, const char * content, long length);
int nopoll_conn_complete_pending_write (noPollConn * conn);
int nopoll_conn_pending_write_bytes (noPollConn * conn);
int nopoll_conn_flush_writes (noPollConn * conn, long timeout, int previous_result);
int nopoll_conn_read (noPollConn * conn, char * buffer, int bytes, nopoll_bool block, long int timeout);
noPollConn * nopoll_conn_get_listener (noPollConn * conn);
nopoll_bool nopoll_conn_send_ping (noPollConn * conn);
nopoll_bool nopoll_conn_send_pong (noPollConn * conn);
void nopoll_conn_set_on_msg (noPollConn * conn,
noPollOnMessageHandler on_msg,
noPollPtr user_data);
void nopoll_conn_set_on_ready (noPollConn * conn,
noPollActionHandler on_ready,
noPollPtr user_data);
void nopoll_conn_set_on_close (noPollConn * conn,
noPollOnCloseHandler on_close,
noPollPtr user_data);
int nopoll_conn_send_frame (noPollConn * conn, nopoll_bool fin, nopoll_bool masked,
noPollOpCode op_code, long length, noPollPtr content,
long sleep_in_header);
int __nopoll_conn_send_common (noPollConn * conn,
const char * content,
long length,
nopoll_bool has_fin,
long sleep_in_header,
noPollOpCode frame_type);
nopoll_bool nopoll_conn_wait_until_connection_ready (noPollConn * conn,
int timeout);
/** internal api **/
void nopoll_conn_complete_handshake (noPollConn * conn);
int nopoll_conn_default_receive (noPollConn * conn, char * buffer, int buffer_size);
int nopoll_conn_default_send (noPollConn * conn, char * buffer, int buffer_size);
void nopoll_conn_mask_content (noPollCtx * ctx, char * payload, int payload_size, char * mask, int desp);
END_C_DECLS
#endif

View File

@ -0,0 +1,73 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_CONN_OPTS_H__
#define __NOPOLL_CONN_OPTS_H__
#include <nopoll.h>
BEGIN_C_DECLS
noPollConnOpts * nopoll_conn_opts_new (void);
void nopoll_conn_opts_set_ssl_protocol (noPollConnOpts * opts, noPollSslProtocol ssl_protocol);
nopoll_bool nopoll_conn_opts_set_ssl_certs (noPollConnOpts * opts,
const char * client_certificate,
const char * private_key,
const char * chain_certificate,
const char * ca_certificate);
void nopoll_conn_opts_ssl_peer_verify (noPollConnOpts * opts, nopoll_bool verify);
void nopoll_conn_opts_set_cookie (noPollConnOpts * opts, const char * cookie_content);
nopoll_bool nopoll_conn_opts_ref (noPollConnOpts * opts);
void nopoll_conn_opts_unref (noPollConnOpts * opts);
void nopoll_conn_opts_set_reuse (noPollConnOpts * opts, nopoll_bool reuse);
void nopoll_conn_opts_free (noPollConnOpts * opts);
/** internal API **/
void __nopoll_conn_opts_release_if_needed (noPollConnOpts * options);
END_C_DECLS
#endif

View File

@ -0,0 +1,106 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_CTX_H__
#define __NOPOLL_CTX_H__
#include <nopoll.h>
BEGIN_C_DECLS
noPollCtx * nopoll_ctx_new (void);
nopoll_bool nopoll_ctx_ref (noPollCtx * ctx);
void nopoll_ctx_unref (noPollCtx * ctx);
int nopoll_ctx_ref_count (noPollCtx * ctx);
nopoll_bool nopoll_ctx_register_conn (noPollCtx * ctx,
noPollConn * conn);
void nopoll_ctx_unregister_conn (noPollCtx * ctx,
noPollConn * conn);
int nopoll_ctx_conns (noPollCtx * ctx);
nopoll_bool nopoll_ctx_set_certificate (noPollCtx * ctx,
const char * serverName,
const char * certificateFile,
const char * privateKey,
const char * optionalChainFile);
nopoll_bool nopoll_ctx_find_certificate (noPollCtx * ctx,
const char * serverName,
const char ** certificateFile,
const char ** privateKey,
const char ** optionalChainFile);
void nopoll_ctx_set_on_accept (noPollCtx * ctx,
noPollActionHandler on_accept,
noPollPtr user_data);
void nopoll_ctx_set_on_open (noPollCtx * ctx,
noPollActionHandler on_open,
noPollPtr user_data);
void nopoll_ctx_set_on_ready (noPollCtx * ctx,
noPollActionHandler on_ready,
noPollPtr user_data);
void nopoll_ctx_set_on_msg (noPollCtx * ctx,
noPollOnMessageHandler on_msg,
noPollPtr user_data);
void nopoll_ctx_set_ssl_context_creator (noPollCtx * ctx,
noPollSslContextCreator context_creator,
noPollPtr user_data);
void nopoll_ctx_set_post_ssl_check (noPollCtx * ctx,
noPollSslPostCheck post_ssl_check,
noPollPtr user_data);
noPollConn * nopoll_ctx_foreach_conn (noPollCtx * ctx, noPollForeachConn foreach, noPollPtr user_data);
void nopoll_ctx_set_protocol_version (noPollCtx * ctx, int version);
void nopoll_ctx_free (noPollCtx * ctx);
END_C_DECLS
#endif

View File

@ -0,0 +1,469 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_DECL_H__
#define __NOPOLL_DECL_H__
/**
* \defgroup nopoll_decl_module Nopoll Declarations: Common Nopoll declarations, Types, macros, and support functions.
*/
/**
* \addtogroup nopoll_decl_module
* @{
*/
/* include platform specific configuration */
#include <nopoll_config.h>
/* include this at this place to load GNU extensions */
#if defined(__GNUC__)
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# define __NOPOLL_PRETTY_FUNCTION__ __PRETTY_FUNCTION__
# define __NOPOLL_LINE__ __LINE__
# define __NOPOLL_FILE__ __FILE__
#elif defined(_MSC_VER)
# define __NOPOLL_PRETTY_FUNCTION__ __FUNCDNAME__
# define __NOPOLL_LINE__ __LINE__
# define __NOPOLL_FILE__ __FILE__
#else
/* unknown compiler */
#define __NOPOLL_PRETTY_FUNCTION__ ""
#define __NOPOLL_LINE__ 0
#define __NOPOLL_FILE__ ""
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
/* only include unistd.h if unix platform is found or gnu gcc compiler
* is found */
#if defined(__GNUC__) || defined(NOPOLL_OS_UNIX)
# include <unistd.h>
#endif
//#include <sys/types.h>
//#include <sys/stat.h>
//#include <fcntl.h>
//#include <ctype.h>
#include "lwip/netdb.h"
#include "lwip/sockets.h"
/* Direct portable mapping definitions */
#if defined(NOPOLL_OS_UNIX)
/* Portable definitions while using noPoll Library */
#define NOPOLL_EINTR EINTR
/**
* @brief Portable definition for EWOULDBLOCK errno code.
*/
#define NOPOLL_EWOULDBLOCK EWOULDBLOCK
#define NOPOLL_EINPROGRESS EINPROGRESS
#define NOPOLL_ENOTCONN ENOTCONN
#define NOPOLL_EAGAIN EAGAIN
#define NOPOLL_SOCKET int
#define NOPOLL_INVALID_SOCKET -1
#define NOPOLL_SOCKET_ERROR -1
#define nopoll_close_socket(s) do {if ( s >= 0) {close (s);}} while (0)
#define nopoll_is_disconnected (errno == EPIPE)
#endif /* end defined(AXL_OS_UNIX) */
#if defined(NOPOLL_OS_WIN32)
/* additional includes for the windows platform */
/* _WIN32_WINNT note: If the application including the header defines
* the _WIN32_WINNT, it must include the bit defined by the value
* 0x400. */
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x400
#endif
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>
#include <time.h>
#ifdef _MSC_FULL_VER
#define strcasecmp(string1, string2) _stricmp(string1, string2)
#endif
#define NOPOLL_EINTR WSAEINTR
#define NOPOLL_EWOULDBLOCK WSAEWOULDBLOCK
#define NOPOLL_EINPROGRESS WSAEINPROGRESS
#define NOPOLL_ENOTCONN WSAENOTCONN
#define NOPOLL_EAGAIN WSAEWOULDBLOCK
#define SHUT_RDWR SD_BOTH
#define SHUT_WR SD_SEND
#define NOPOLL_SOCKET SOCKET
#define NOPOLL_INVALID_SOCKET INVALID_SOCKET
#define NOPOLL_SOCKET_ERROR SOCKET_ERROR
#define nopoll_close_socket(s) do {if ( s >= 0) {closesocket (s);}} while (0)
#define uint16_t u_short
#define nopoll_is_disconnected ((errno == WSAESHUTDOWN) || (errno == WSAECONNABORTED) || (errno == WSAECONNRESET))
/* a definition to avoid warnings */
#define strlen (int) strlen
/* no link support windows */
#define S_ISLNK(m) (0)
#endif /* end defined(AXL_OS_WINDOWS) */
#if defined(NOPOLL_OS_UNIX)
//#include <sys/types.h>
//#include <fcntl.h>
//#include "c_types.h"
//#include <lwip/netdb.h>
//#include <lwip/timers.h>
//#include "lwip/sockets.h"
//#include <netinet/in.h>
//#include <arpa/inet.h>
//#include <sys/select.h>
//#include <sys/time.h>
//#include <sys/resource.h>
//#include <unistd.h>
#endif
/* additional headers for poll support */
#if defined(NOPOLL_HAVE_POLL)
#include <sys/poll.h>
#endif
/* additional headers for linux epoll support */
#if defined(NOPOLL_HAVE_EPOLL)
#include <sys/epoll.h>
#endif
//#include <errno.h>
#if defined(NOPOLL_OS_WIN32)
/* errno redefinition for windows platform. this declaration must
* follow the previous include. */
#ifdef errno
#undef errno
#endif
#define errno (WSAGetLastError())
#endif
/**
* @brief Common definition to have false (\ref nopoll_false) value (which is defined to 0 integer value).
*/
#define nopoll_false ((int)0)
/**
* @brief Common definition to have true (\ref nopoll_true) value (which is defined to 1 integer value).
*/
#define nopoll_true ((int)1)
/**
* @brief Bool definition for the Nopoll toolkit. This type built on
* top of <b>int</b> is used along with \ref nopoll_false and \ref
* nopoll_true to model those API functions and attributes that
* returns or receive a boolean state.
*/
typedef int nopoll_bool;
/**
* @brief Pointer to any structure definition. It should be required
* to use this definition, however, some platforms doesn't support the
* <b>void *</b> making it necessary to use the <b>char *</b>
* definition as a general way to represent references.
*/
typedef void * noPollPtr;
/**
* @brief Execution context object used by the API to provide default
* settings.
*/
typedef struct _noPollCtx noPollCtx;
/**
* @brief Abstraction that represents a connection that maybe be a listener created by \ref nopoll_listener_new or because the connection was received as a consequence of that call, or because it is a client connection created by \ref nopoll_conn_new
*
* See noPoll API because there are other methods to create connections (not only previous mentioned functions).
*/
typedef struct _noPollConn noPollConn;
/**
* @brief Optional connection options to change default behaviour.
*/
typedef struct _noPollConnOpts noPollConnOpts;
/**
* @brief Abstraction that represents a selected IO wait mechanism.
*/
typedef struct _noPollIoEngine noPollIoEngine;
/**
* @brief Abstraction that represents a single websocket message
* received.
*/
typedef struct _noPollMsg noPollMsg;
/**
* @brief Abstraction that represents the status and data exchanged
* during the handshake.
*/
typedef struct _noPollHandshake noPollHandShake;
/**
* @brief Nopoll debug levels.
*
* While reporting log to the console, these levels are used to report
* the severity for such log.
*/
typedef enum {
/**
* @brief Debug level. Only used to report common
* circumstances that represent the proper functionality.
*/
NOPOLL_LEVEL_DEBUG,
/**
* @brief Warning level. Only used to report that an internal
* issue have happend that could be interesting while
* reporting error, but it could also mean common situations.
*/
NOPOLL_LEVEL_WARNING,
/**
* @brief Critical level. Only used to report critical
* situations where some that have happened shouldn't.
*
* This level should only be used while reporting critical
* situations.
*/
NOPOLL_LEVEL_CRITICAL}
noPollDebugLevel;
/**
* @brief Describes the connection role (how it was initiated).
*/
typedef enum {
/**
* @brief Unknown role, returned/used when the connection isn't defined.
*/
NOPOLL_ROLE_UNKNOWN,
/**
* @brief When the connection was created connecting to a web
* socket server (see \ref nopoll_conn_new).
*/
NOPOLL_ROLE_CLIENT,
/**
* @brief When the connection was accepted being a listener
* process.
*/
NOPOLL_ROLE_LISTENER,
/**
* @brief When the connection was created by \ref
* nopoll_listener_new to accept incoming connections.
*/
NOPOLL_ROLE_MAIN_LISTENER
} noPollRole;
/**
* @brief List of supported IO waiting mechanism available.
*/
typedef enum {
/**
* @brief Selects the default (best) IO mechanism found on the
* system.
*/
NOPOLL_IO_ENGINE_DEFAULT,
/**
* @brief Selects the select(2) based IO wait mechanism.
*/
NOPOLL_IO_ENGINE_SELECT,
/**
* @brief Selects the poll(2) based IO wait mechanism.
*/
NOPOLL_IO_ENGINE_POLL,
/**
* @brief Selects the epoll(2) based IO wait mechanism.
*/
NOPOLL_IO_ENGINE_EPOLL
} noPollIoEngineType;
/**
* @brief Support macro to allocate memory using nopoll_calloc function,
* making a casting and using the sizeof keyword.
*
* @param type The type to allocate
* @param count How many items to allocate.
*
* @return A newly allocated pointer.
*/
#define nopoll_new(type, count) (type *) nopoll_calloc (count, sizeof (type))
/**
* @brief Allows to check a condition and return if it is not meet.
*
* @param ctx The context where the operation will take place.
* @param expr The expresion to check.
*/
#define nopoll_return_if_fail(ctx, expr) \
if (!(expr)) {__nopoll_log (ctx, __function_name__, __file__, __line__, NOPOLL_LEVEL_CRITICAL, "Expresion '%s' have failed at %s (%s:%d)", #expr, __NOPOLL_PRETTY_FUNCTION__, __NOPOLL_FILE__, __NOPOLL_LINE__); return;}
/**
* @brief Allows to check a condition and return the given value if it
* is not meet.
*
* @param ctx The context where the operation will take place.
*
* @param expr The expresion to check.
*
* @param val The value to return if the expression is not meet.
*/
#define nopoll_return_val_if_fail(ctx, expr, val) \
if (!(expr)) { __nopoll_log (ctx, __function_name__, __file__, __line__, NOPOLL_LEVEL_CRITICAL, "Expresion '%s' have failed, returning: %s at %s (%s:%d)", #expr, #val, __NOPOLL_PRETTY_FUNCTION__, __NOPOLL_FILE__, __NOPOLL_LINE__); return val;}
/**
* @internal
*
* C++ support declarations borrowed from the libtool webpage. Thanks
* you guys for this information.
*
* BEGIN_C_DECLS should be used at the beginning of your declarations,
* so that C++ compilers don't mangle their names. Use END_C_DECLS at
* the end of C declarations.
*/
#undef BEGIN_C_DECLS
#undef END_C_DECLS
#ifdef __cplusplus
# define BEGIN_C_DECLS extern "C" {
# define END_C_DECLS }
#else
# define BEGIN_C_DECLS /* empty */
# define END_C_DECLS /* empty */
#endif
/**
* @brief Type of frames and opcodes supported by noPoll.
*/
typedef enum {
/**
* @brief Support to model unknown op code.
*/
NOPOLL_UNKNOWN_OP_CODE = -1,
/**
* @brief Denotes a continuation frame.
*/
NOPOLL_CONTINUATION_FRAME = 0,
/**
* @brief Denotes a text frame (utf-8 content) and the first
* frame of the message.
*/
NOPOLL_TEXT_FRAME = 1,
/**
* @brief Denotes a binary frame and the first frame of the
* message.
*/
NOPOLL_BINARY_FRAME = 2,
/**
* @brief Denotes a close frame request.
*/
NOPOLL_CLOSE_FRAME = 8,
/**
* @brief Denotes a ping frame (used to ring test the circuit
* and to keep alive the connection).
*/
NOPOLL_PING_FRAME = 9,
/**
* @brief Denotes a pong frame (reply to ping request).
*/
NOPOLL_PONG_FRAME = 10
} noPollOpCode;
/**
* @brief SSL/TLS protocol type to use for the client or listener
* connection.
*/
typedef enum {
/**
* @brief Allows to define SSLv23 as SSL protocol used by the
* client or server connection. A TLS/SSL connection
* established with these methods may understand SSLv3, TLSv1,
* TLSv1.1 and TLSv1.2 protocols (\ref NOPOLL_METHOD_SSLV3, \ref NOPOLL_METHOD_TLSV1, ...)
*/
NOPOLL_METHOD_SSLV23 = 2,
/**
* @brief Allows to define SSLv3 as SSL protocol used by the
* client or server connection. A connection/listener
* established with this method will only understand this
* method.
*/
NOPOLL_METHOD_SSLV3 = 3,
/**
* @brief Allows to define TLSv1 as SSL protocol used by the
* client or server connection. A connection/listener
* established with this method will only understand this
* method.
*/
NOPOLL_METHOD_TLSV1 = 4,
//#if defined(TLSv1_1_client_method)
/**
* @brief Allows to define TLSv1.1 as SSL protocol used by the
* client or server connection. A connection/listener
* established with this method will only understand this
* method.
*/
NOPOLL_METHOD_TLSV1_1 = 5
//#endif
} noPollSslProtocol ;
BEGIN_C_DECLS
#include "esp_libc.h"
noPollPtr nopoll_calloc (size_t count, size_t size);
noPollPtr nopoll_realloc (noPollPtr ref, size_t size);
void nopoll_free (noPollPtr ref);
END_C_DECLS
#endif
/* @} */

View File

@ -0,0 +1,329 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_HANDLERS_H__
#define __NOPOLL_HANDLERS_H__
/**
* \defgroup nopoll_handlers noPoll Handlers: Handler definitions used by the library to du async notifications
*/
/**
* \addtogroup nopoll_handlers
* @{
*/
/**
* @brief General async handler definition used to notify generic
* events associated to a connection.
*
* Currently this handler is used by:
* - \ref nopoll_ctx_set_on_accept
* - \ref nopoll_ctx_set_on_open
*
* @param ctx The context where the wait is happening.
*
* @param conn The connection where the data or something meaningful
* was detected.
*
* @param user_data Optional user data pointer passed in into the handler.
*
* @return The function returns a boolean value which is interpreted
* in an especific form according to the event.
*/
typedef nopoll_bool (*noPollActionHandler) (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data);
/**
* @brief Handler used to define the create function for an IO mechanism.
*
* @param ctx The context where the io mechanism will be created.
*/
typedef noPollPtr (*noPollIoMechCreate) (noPollCtx * ctx);
/**
* @brief Handler used to define the IO wait set destroy function for
* an IO mechanism.
*
* @param ctx The context where the io mechanism will be destroyed.
*
* @param io_object The io object to be destroyed as created by \ref
* noPollIoMechCreate handler.
*/
typedef void (*noPollIoMechDestroy) (noPollCtx * ctx, noPollPtr io_object);
/**
* @brief Handler used to define the IO wait set clear function for an
* IO mechanism.
*
* @param ctx The context where the io mechanism will be cleared.
*
* @param io_object The io object to be created as created by \ref
* noPollIoMechCreate handler.
*/
typedef void (*noPollIoMechClear) (noPollCtx * ctx, noPollPtr io_object);
/**
* @brief Handler used to define the IO wait function for an IO
* mechanism.
*
* @param ctx The context where the io mechanism was created.
*
* @param io_object The io object to be created as created by \ref
* noPollIoMechCreate handler where the wait will be implemented.
*/
typedef int (*noPollIoMechWait) (noPollCtx * ctx, noPollPtr io_object);
/**
* @brief Handler used to define the IO add to set function for an IO
* mechanism.
*
* @param ctx The context where the io mechanism was created.
*
* @param conn The noPollConn to be added to the working set.
*
* @param io_object The io object to be created as created by \ref
* noPollIoMechCreate handler where the wait will be implemented.
*/
typedef nopoll_bool (*noPollIoMechAddTo) (int fds,
noPollCtx * ctx,
noPollConn * conn,
noPollPtr io_object);
/**
* @brief Handler used to define the IO is set function for an IO
* mechanism.
*
* @param ctx The context where the io mechanism was created.
*
* @param conn The noPollConn to be added to the working set.
*
* @param io_object The io object to be created as created by \ref
* noPollIoMechCreate handler where the wait will be implemented.
*/
typedef nopoll_bool (*noPollIoMechIsSet) (noPollCtx * ctx,
int fds,
noPollPtr io_object);
/**
* @brief Handler used to define the foreach function that is used by
* \ref nopoll_ctx_foreach_conn
*
* @param ctx The context where the foreach operation is taking place.
*
* @param conn The connection notified
*
* @param user_data Optional user defined pointer received at \ref
* nopoll_ctx_foreach_conn.
*
* @return nopoll_true to stop the foreach process, otherwise
* nopoll_false to keep checking the next connection until all
* connections are notified.
*/
typedef nopoll_bool (*noPollForeachConn) (noPollCtx * ctx,
noPollConn * conn,
noPollPtr user_data);
/**
* @brief Handler definition used to describe read functions used by \ref noPollConn.
*
* @param conn The connection where the readOperation will take place.
*
* @param buffer The buffer where data read from socket will be placed.
*
* @param buffer_size The buffer size that is receiving the function.
*/
typedef int (*noPollRead) (noPollConn * conn,
char * buffer,
int buffer_size);
/**
* @brief Handler definition used to notify websocket messages
* received.
*
* This handler will be called when a websocket message is
* received. Keep in mind the reference received on this handler will
* be finished when the handler ends. If you need to have a reference
* to the message after handler execution, acquire a reference via
* \ref nopoll_msg_ref.
*
* @param ctx The context where the messagewas received.
*
* @param conn The connection where the message was received.
*
* @param msg The websocket message was received.
*
* @param user_data An optional user defined pointer.
*/
typedef void (*noPollOnMessageHandler) (noPollCtx * ctx,
noPollConn * conn,
noPollMsg * msg,
noPollPtr user_data);
/**
* @brief Handler definition used by \ref nopoll_conn_set_on_close.
*
* Handler definition for the function that is called when the
* connection is closed but just before shutting down the socket
* associated to the connection.
*
* @param ctx The context where the operation will take place.
*
* @param conn The connection where the operation will take place.
*
* @param user_data The reference that was configured to be passed in
* into the handler.
*/
typedef void (*noPollOnCloseHandler) (noPollCtx * ctx,
noPollConn * conn,
noPollPtr user_data);
/**
* @brief Mutex creation handler used by the library.
*
* @return A reference to the mutex created (already initialized).
*/
typedef noPollPtr (*noPollMutexCreate) (void);
/**
* @brief Mutex destroy handler used by the library.
*
* @param The mutex to destroy.
*/
typedef void (*noPollMutexDestroy) (noPollPtr mutex);
/**
* @brief Mutex lock handler used by the library.
*
* @param The mutex where to implement the lock operation.
*/
typedef void (*noPollMutexLock) (noPollPtr mutex);
/**
* @brief Mutex unlock handler used by the library.
*
* @param The mutex where to implement the unlock operation.
*/
typedef void (*noPollMutexUnlock) (noPollPtr mutex);
/**
* @brief Handler used by nopoll_log_set_handler to receive all log
* notifications produced by the library on this function.
*
* @param ctx The context where the operation is happening.
*
* @param level The log level
*
* @param log_msg The actual log message reported.
*
* @param user_data A reference to user defined pointer passed in into the function.
*/
typedef void (*noPollLogHandler) (noPollCtx * ctx, noPollDebugLevel level, const char * log_msg, noPollPtr user_data);
/**
* @brief An optional handler that allows user land code to define how
* is SSL_CTX (SSL context) created and which are the settings it
* should have before taking place SSL/TLS handshake.
*
* NOTE: that the function should return one context for every
* connection created. Do not reuse unless you know what you are
* doing.
*
* A very bare implementation for this context creation will be:
*
* \code
* SSL_CTX * my_ssl_ctx_creator (noPollCtx * ctx, noPollConn * conn, noPollConnOpts * opts, nopoll_bool is_client, noPollPtr user_data)
* {
* // very basic context creation using default settings provided by OpenSSL
* return SSL_CTX_new (is_client ? TLSv1_client_method () : TLSv1_server_method ());
* }
* \endcode
*
* @param ctx The context where the operation is taking place.
*
* @param conn The connection that is being requested for a new context (SSL_CTX). Use is_client to know if this is a connecting client or a listener connection.
*
* @param opts Optional reference to the connection object created for this connection.
*
* @param is_client nopoll_true to signal that this is a request for a context for a client connection. Otherwise, it is for a listener connection.
*
* @param user_data User defined pointer that received on this function as defined at \ref nopoll_ctx_set_ssl_context_creator.
*
* @return The function must return a valid SSL_CTX object (see OpenSSL documentation to know more about this) or NULL if it fails.
*/
typedef noPollPtr (*noPollSslContextCreator) (noPollCtx * ctx,
noPollConn * conn,
noPollConnOpts * opts,
nopoll_bool is_client,
noPollPtr user_data);
/**
* @brief Optional user defined handler that allows to execute SSL
* post checks code before proceed.
*
* This handler is configured at \ref nopoll_ctx_set_post_ssl_check
* and allows to implement custom actions while additional
* verifications about certificate received, validation based on
* certain attributes, etc.
*
* Note that when this handler is called, the SSL handshake has
* finished without error. In case of SSL handshake failure, this
* handler is not executed.
*
* @param ctx The context where the operation happens.
*
* @param conn The connection where the operation takes place and for which the post SSL check is being done.
*
* @param SSL_CTX The OpenSSL SSL_CTX object created for this connection.
*
* @param SSL The OpenSSL SSL object created for this connection.
*
* @param user_data User defined data that is received on this handler as configured at \ref nopoll_ctx_set_post_ssl_check
*/
typedef nopoll_bool (*noPollSslPostCheck) (noPollCtx * ctx,
noPollConn * conn,
noPollPtr SSL_CTX,
noPollPtr SSL,
noPollPtr user_data);
#endif
/* @} */

View File

@ -0,0 +1,52 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_IO_H__
#define __NOPOLL_IO_H__
#include <nopoll.h>
BEGIN_C_DECLS
noPollIoEngine * nopoll_io_get_engine (noPollCtx * ctx, noPollIoEngineType engine_type);
void nopoll_io_release_engine (noPollIoEngine * engine);
END_C_DECLS
#endif

View File

@ -0,0 +1,80 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_LISTENER_H__
#define __NOPOLL_LISTENER_H__
#include <nopoll.h>
BEGIN_C_DECLS
NOPOLL_SOCKET nopoll_listener_sock_listen (noPollCtx * ctx,
const char * host,
const char * port);
noPollConn * nopoll_listener_new (noPollCtx * ctx,
const char * host,
const char * port);
noPollConn * nopoll_listener_new_opts (noPollCtx * ctx,
noPollConnOpts * opts,
const char * host,
const char * port);
noPollConn * nopoll_listener_tls_new (noPollCtx * ctx,
const char * host,
const char * port);
noPollConn * nopoll_listener_tls_new_opts (noPollCtx * ctx,
noPollConnOpts * opts,
const char * host,
const char * port);
nopoll_bool nopoll_listener_set_certificate (noPollConn * listener,
const char * certificate,
const char * private_key,
const char * chain_file);
noPollConn * nopoll_listener_from_socket (noPollCtx * ctx,
NOPOLL_SOCKET session);
NOPOLL_SOCKET nopoll_listener_accept (NOPOLL_SOCKET server_socket);
END_C_DECLS
#endif

View File

@ -0,0 +1,113 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_LOG_H__
#define __NOPOLL_LOG_H__
#include <nopoll_decl.h>
#include <nopoll_handlers.h>
BEGIN_C_DECLS
/**
* \addtogroup nopoll_log_module
* @{
*/
nopoll_bool nopoll_log_is_enabled (noPollCtx * ctx);
nopoll_bool nopoll_log_color_is_enabled (noPollCtx * ctx);
void nopoll_log_enable (noPollCtx * ctx, nopoll_bool value);
void nopoll_log_color_enable (noPollCtx * ctx, nopoll_bool value);
void nopoll_log_set_handler (noPollCtx * ctx, noPollLogHandler handler, noPollPtr user_data);
/* include this at this place to load GNU extensions */
#if defined(__GNUC__)
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# define __function_name__ __PRETTY_FUNCTION__
# define __line__ __LINE__
# define __file__ __FILE__
#elif defined(_MSC_VER)
# define __function_name__ __FUNCDNAME__
# define __line__ __LINE__
# define __file__ __FILE__
#else
/* unknown compiler */
#define __function_name__ ""
#define __line__ 0
#define __file__ ""
#endif
#if defined(SHOW_DEBUG_LOG)
# define nopoll_log(ctx,level,message, ...) do{__nopoll_log(ctx, __function_name__, __file__, __line__, level, message, ##__VA_ARGS__);}while(0)
#else
# if defined(NOPOLL_OS_WIN32) && !( defined (__GNUC__) || _MSC_VER >= 1400)
/* default case where '...' is not supported but log is still
* disabled */
# define nopoll_log __nopoll_log
# else
# define nopoll_log(ctx, level, message, ...) /* nothing */
# endif
#endif
/**
* @internal The following definition allows to find printf like wrong
* argument passing to nopoll_log function. To activate the depuration
* just add the following to local nopoll_config.h file:
*
* #define SHOW_FORMAT_BUGS (1)
*/
#if defined(SHOW_FORMAT_BUGS)
# undef nopoll_log
# define nopoll_log(ctx,level,message, ...) do{printf (message, ##__VA_ARGS__);}while(0)
#endif
void __nopoll_log (noPollCtx * ctx, const char * function_name, const char * file, int line, noPollDebugLevel level, const char * message, ...);
/* @} */
END_C_DECLS
#endif

View File

@ -0,0 +1,52 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_LOOP_H__
#define __NOPOLL_LOOP_H__
#include <nopoll.h>
BEGIN_C_DECLS
int nopoll_loop_wait (noPollCtx * ctx, long timeout);
void nopoll_loop_stop (noPollCtx * ctx);
END_C_DECLS
#endif

View File

@ -0,0 +1,68 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_MSG_H__
#define __NOPOLL_MSG_H__
#include <nopoll.h>
BEGIN_C_DECLS
const unsigned char * nopoll_msg_get_payload (noPollMsg * msg);
int nopoll_msg_get_payload_size (noPollMsg * msg);
noPollMsg * nopoll_msg_new (void);
nopoll_bool nopoll_msg_ref (noPollMsg * msg);
int nopoll_msg_ref_count (noPollMsg * msg);
nopoll_bool nopoll_msg_is_final (noPollMsg * msg);
nopoll_bool nopoll_msg_is_fragment (noPollMsg * msg);
noPollOpCode nopoll_msg_opcode (noPollMsg * msg);
noPollMsg * nopoll_msg_join (noPollMsg * msg, noPollMsg * msg2);
void nopoll_msg_unref (noPollMsg * msg);
END_C_DECLS
#endif

View File

@ -0,0 +1,386 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_PRIVATE_H__
#define __NOPOLL_PRIVATE_H__
#include "openssl/ssl.h"
#include <nopoll_handlers.h>
typedef struct _noPollCertificate {
char * serverName;
char * certificateFile;
char * privateKey;
char * optionalChainFile;
} noPollCertificate;
struct _noPollCtx {
/**
* @internal Controls logs output..
*/
/* context reference counting */
int refs;
/* console log */
nopoll_bool not_executed;
nopoll_bool debug_enabled;
/* colored log */
nopoll_bool not_executed_color;
nopoll_bool debug_color_enabled;
nopoll_bool keep_looping;
/**
* @internal noPollConn connection timeout.
*/
long conn_connect_std_timeout;
/**
* @internal Default listener connection backlog
*/
int backlog;
/**
* @internal Currently selected io engine on this context.
*/
noPollIoEngine * io_engine;
/**
* @internal Connection array list and its length.
*/
int conn_id;
noPollConn ** conn_list;
int conn_length;
/**
* @internal Number of connections registered on this context.
*/
int conn_num;
/**
* @internal Reference to defined on accept handling.
*/
noPollActionHandler on_accept;
noPollPtr on_accept_data;
/**
* @internal Reference to defined on ready handling.
*/
noPollActionHandler on_ready;
noPollPtr on_ready_data;
/**
* @internal Reference to defined on open handling.
*/
noPollActionHandler on_open;
noPollPtr on_open_data;
/**
* @internal Reference to the defined on message handling.
*/
noPollOnMessageHandler on_msg;
noPollPtr on_msg_data;
/**
* @internal Basic fake support for protocol version, by
* default: 13, due to RFC6455 standard
*/
int protocol_version;
/**
* @internal Certificates added..
*/
noPollCertificate * certificates;
int certificates_length;
/* mutex */
noPollPtr ref_mutex;
/* log handling */
noPollLogHandler log_handler;
noPollPtr log_user_data;
/* context creator */
noPollSslContextCreator context_creator;
noPollPtr context_creator_data;
/* SSL postcheck */
noPollSslPostCheck post_ssl_check;
noPollPtr post_ssl_check_data;
};
struct _noPollConn {
/**
* @internal Connection id.
*/
int id;
/**
* @internal The context associated to this connection.
*/
noPollCtx * ctx;
/**
* @internal This is the actual socket handler associated to
* the noPollConn object.
*/
NOPOLL_SOCKET session;
/**
* @internal Flag to signal this connection has finished its
* handshake.
*/
nopoll_bool handshake_ok;
/**
* @internal Current connection receive function.
*/
noPollRead receive;
/**
* @internal Current connection receive function.
*/
noPollRead sends;
/**
* @internal The connection role.
*/
noPollRole role;
/**
* @internal Conection host ip location (connecting or listening).
*/
char * host;
/**
* @internal Connection port location (connecting or
* listening).
*/
char * port;
/**
* @internal Host name requested on the connection.
*/
char * host_name;
/**
* @internal Origin requested on the connection.
*/
char * origin;
/**
* @internal reference to the get url.
*/
char * get_url;
/**
* @internal Reference to protocols requested to be opened on
* this connection.
*/
char * protocols;
/* @internal reference to the protocol that was replied by the server */
char * accepted_protocol;
/* close status and reason */
int peer_close_status;
char * peer_close_reason;
/**
* @internal Reference to the defined on message handling.
*/
noPollOnMessageHandler on_msg;
noPollPtr on_msg_data;
/**
* @internal Reference to defined on ready handling.
*/
noPollActionHandler on_ready;
noPollPtr on_ready_data;
/**
* @internal Reference to the defined on close handling.
*/
noPollOnCloseHandler on_close;
noPollPtr on_close_data;
/* reference to the handshake */
noPollHandShake * handshake;
/* reference to a buffer with pending content */
char * pending_line;
/**
* @internal connection reference counting.
*/
int refs;
/**
* @internal References to pending content to be read
*/
noPollMsg * pending_msg;
long int pending_diff;
long int pending_desp;
/**
* @internal Flag to handle TLS support upon connection
* reception.
*/
nopoll_bool tls_on;
/**
* @internal Flag that indicates that the provided session
* must call to accept the TLS session before proceeding.
*/
nopoll_bool pending_ssl_accept;
/* SSL support */
SSL_CTX * ssl_ctx;
SSL * ssl;
/* certificates */
char * certificate;
char * private_key;
char * chain_certificate;
/* pending buffer */
char pending_buf[100];
int pending_buf_bytes;
/**
* @internal Support for an user defined pointer.
*/
noPollPtr hook;
/**
* @internal Mutex
*/
noPollPtr ref_mutex;
/**
* @internal Variable to track pending bytes from previous
* read that must be completed.
*/
noPollMsg * previous_msg;
/* allows to track if previous message was a fragment to flag
* next message, even having FIN enabled as a fragment. */
nopoll_bool previous_was_fragment;
char * pending_write;
int pending_write_bytes;
/**
* @internal Internal reference to the connection options.
*/
noPollConnOpts * opts;
/**
* @internal Reference to the listener in the case this is a
* connection that was created due to a listener running.
*/
noPollConn * listener;
};
struct _noPollIoEngine {
noPollPtr io_object;
noPollCtx * ctx;
noPollIoMechCreate create;
noPollIoMechDestroy destroy;
noPollIoMechClear clear;
noPollIoMechWait wait;
noPollIoMechAddTo addto;
noPollIoMechIsSet isset;
};
struct _noPollMsg {
nopoll_bool has_fin;
short op_code;
nopoll_bool is_masked;
noPollPtr payload;
long int payload_size;
int refs;
noPollPtr ref_mutex;
char mask[4];
int remain_bytes;
nopoll_bool is_fragment;
int unmask_desp;
};
struct _noPollHandshake {
/**
* @internal Reference to the to the GET url HTTP/1.1 header
* part.
*/
nopoll_bool upgrade_websocket;
nopoll_bool connection_upgrade;
nopoll_bool received_101;
char * websocket_key;
char * websocket_version;
char * websocket_accept;
char * expected_accept;
/* reference to cookie header */
char * cookie;
};
struct _noPollConnOpts {
/* If the connection options object should be reused across calls */
nopoll_bool reuse;
/* mutex */
noPollPtr mutex;
int refs;
/* What ssl protocol should be used */
noPollSslProtocol ssl_protocol;
/* SSL options */
char * certificate;
char * private_key;
char * chain_certificate;
char * ca_certificate;
nopoll_bool disable_ssl_verify;
/* cookie support */
char * cookie;
};
#endif

View File

@ -0,0 +1,66 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#ifndef __NOPOLL_WIN32_H__
#define __NOPOLL_WIN32_H__
#include <nopoll_ctx.h>
BEGIN_C_DECLS
int nopoll_win32_init (noPollCtx * ctx);
int nopoll_win32_nonblocking_enable (NOPOLL_SOCKET socket);
int nopoll_win32_blocking_enable (NOPOLL_SOCKET socket);
/* gettimeofday support on windows */
int nopoll_win32_gettimeofday (struct timeval *tv, noPollPtr notUsed);
BOOL APIENTRY DllMain (HINSTANCE hInst,
DWORD reason,
LPVOID reserved);
#if !defined(EINPROGRESS)
#define EINPROGRESS (WSAEINPROGRESS)
#endif
END_C_DECLS
#endif

View File

@ -0,0 +1,44 @@
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libnopoll.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,313 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_conn_opts.h>
#include <nopoll_private.h>
/**
* \defgroup nopoll_conn_opts noPoll Connection Options: API to change default connection options.
*/
/**
* \addtogroup nopoll_conn_opts
* @{
*/
/**
* @brief Create a new connection options object.
*
* @return A newly created connection options object. In general you don't have to worry about releasing this object because this is automatically done by functions using this object. However, if you call to \ref nopoll_conn_opts_set_reuse (opts, nopoll_true), then you'll have to use \ref nopoll_conn_opts_free to release the object after it is no longer used. The function may return NULL in case of memory allocation problems. Creating an object without setting anything will cause the library to provide same default behaviour as not providing it.
*/
noPollConnOpts * nopoll_conn_opts_new (void)
{
noPollConnOpts * result;
/* create configuration object */
result = nopoll_new (noPollConnOpts, 1);
if (! result)
return NULL;
result->reuse = nopoll_false; /* this is not needed, just to clearly state defaults */
result->ssl_protocol = NOPOLL_METHOD_TLSV1;
result->mutex = nopoll_mutex_create ();
result->refs = 1;
/* by default, disable ssl peer verification */
result->disable_ssl_verify = nopoll_true;
return result;
}
/**
* @brief Set ssl protocol method to be used on the API receiving this
* configuration object.
*
* @param opts The connection options object.
*
* @param ssl_protocol SSL protocol to use. See \ref noPollSslProtocol for more information.
*/
void nopoll_conn_opts_set_ssl_protocol (noPollConnOpts * opts, noPollSslProtocol ssl_protocol)
{
if (opts == NULL)
return;
opts->ssl_protocol = ssl_protocol;
return;
}
/**
* @brief Allows to certificate, private key and optional chain
* certificate and ca for on a particular options that can be used for
* a client and a listener connection.
*
* @param opts The connection options where these settings will be
* applied.
*
* @param certificate The certificate to use on the connection.
*
* @param private_key client_certificate private key.
*
* @param chain_certificate Optional chain certificate to use
*
* @param ca_certificate Optional CA certificate to use during the
* process.
*
* @return nopoll_true in the case all certificate files provided are
* reachable.
*/
nopoll_bool nopoll_conn_opts_set_ssl_certs (noPollConnOpts * opts,
const char * certificate,
const char * private_key,
const char * chain_certificate,
const char * ca_certificate)
{
if (opts == NULL)
return nopoll_false;
/* store certificate settings */
opts->certificate = nopoll_strdup (certificate);
opts->private_key = nopoll_strdup (private_key);
opts->chain_certificate = nopoll_strdup (chain_certificate);
opts->ca_certificate = nopoll_strdup (ca_certificate);
return nopoll_true;
}
/**
* @brief Allows to disable peer ssl certificate verification. This is
* not recommended for production enviroment. This affects in a
* different manner to a listener connection and a client connection.
*
* For a client connection, by default, peer verification is enabled
* and this function may help to disable it during development or
* other reasons.
*
* In the case of the servers (created by using \ref
* nopoll_listener_new for example) this is not required because by
* default peer verification is disabled by default.
*
* @param opts The connection option to configure.
*
* @param verify nopoll_true to disable verification
* otherwise, nopoll_false should be used. By default SSL verification
* is enabled.
*
*/
void nopoll_conn_opts_ssl_peer_verify (noPollConnOpts * opts, nopoll_bool verify)
{
if (opts == NULL)
return;
opts->disable_ssl_verify = ! verify;
return;
}
/**
* @brief Allows to set Cookie header content to be sent during the
* connection handshake. If configured and the remote side server is a
* noPoll peer, use \ref nopoll_conn_get_cookie to get this value.
*
* @param opts The connection option to configure.
*
* @param cookie_content Content for the cookie. If you pass NULL the
* cookie is unset.
*/
void nopoll_conn_opts_set_cookie (noPollConnOpts * opts, const char * cookie_content)
{
if (opts == NULL)
return;
if (cookie_content) {
/* configure cookie content to be sent */
opts->cookie = nopoll_strdup (cookie_content);
} else {
nopoll_free (opts->cookie);
opts->cookie = NULL;
} /* end if */
return;
}
/**
* @brief Allows to increase a reference to the connection options
* provided.
*
* @param opts The connection option reference over which a connection
* reference is needed.
*
* @return nopoll_true in the case the operation went ok, otherwise
* nopoll_false is returned.
*/
nopoll_bool nopoll_conn_opts_ref (noPollConnOpts * opts)
{
if (opts == NULL)
return nopoll_false;
/* lock the mutex */
nopoll_mutex_lock (opts->mutex);
if (opts->refs <= 0) {
/* unlock the mutex */
nopoll_mutex_unlock (opts->mutex);
return nopoll_false;
}
opts->refs++;
/* release here the mutex */
nopoll_mutex_unlock (opts->mutex);
return nopoll_true;
}
/**
* @brief Allows to unref a reference acquired by \ref nopoll_conn_opts_ref
*
* @param opts The connection opts to release.
*/
void nopoll_conn_opts_unref (noPollConnOpts * opts)
{
/* call free implementation */
nopoll_conn_opts_free (opts);
return;
}
/**
* @brief Set reuse-flag be used on the API receiving this
* configuration object. By setting nopoll_true will cause the API to
* not release the object when finished. Instead, the caller will be
* able to use this object in additional API calls but, after
* finishing, a call to \ref nopoll_conn_opts_set_reuse function is
* required.
*
* @param opts The connection options object.
*
* @param reuse nopoll_true to reuse the object across calls,
* otherwise nopoll_false to make the API function to release the
* object when done.
*/
void nopoll_conn_opts_set_reuse (noPollConnOpts * opts, nopoll_bool reuse)
{
if (opts == NULL)
return;
opts->reuse = reuse;
return;
}
void __nopoll_conn_opts_free_common (noPollConnOpts * opts)
{
if (opts == NULL)
return;
/* acquire here the mutex */
nopoll_mutex_lock (opts->mutex);
opts->refs--;
if (opts->refs != 0) {
/* release here the mutex */
nopoll_mutex_unlock (opts->mutex);
return;
}
/* release here the mutex */
nopoll_mutex_unlock (opts->mutex);
nopoll_free (opts->certificate);
nopoll_free (opts->private_key);
nopoll_free (opts->chain_certificate);
nopoll_free (opts->ca_certificate);
/* cookie */
nopoll_free (opts->cookie);
/* release mutex */
nopoll_mutex_destroy (opts->mutex);
nopoll_free (opts);
return;
}
/**
* @brief Allows to release a connection object reported by \ref nopoll_conn_opts_new
*
* IMPORTANT NOTE: do not use this function over a \ref noPollConnOpts if it is not flagged with \ref nopoll_conn_opts_set_reuse (opts, nopoll_true).
*
* Default behaviour provided by the API implies that every connection
* options object created by \ref nopoll_conn_opts_new is
* automatically released by the API consuming that object.
*/
void nopoll_conn_opts_free (noPollConnOpts * opts)
{
__nopoll_conn_opts_free_common (opts);
return;
} /* end if */
/**
* @internal API. Do not use it. It may change at any time without any
* previous indication.
*/
void __nopoll_conn_opts_release_if_needed (noPollConnOpts * options)
{
if (! options)
return;
if (options && options->reuse)
return;
__nopoll_conn_opts_free_common (options);
return;
}
/* @} */

View File

@ -0,0 +1,802 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_ctx.h>
#include <nopoll_private.h>
//#include <signal.h>
/**
* \defgroup nopoll_ctx noPoll Context: context handling functions used by the library
*/
/**
* \addtogroup nopoll_ctx
* @{
*/
void __nopoll_ctx_sigpipe_do_nothing (int _signal)
{
#if !defined(NOPOLL_OS_WIN32)
/* do nothing sigpipe handler to be able to manage EPIPE error
* returned by write ops. */
/* the following line is to ensure ancient glibc version that
* restores to the default handler once the signal handling is
* executed. */
// signal (SIGPIPE, __nopoll_ctx_sigpipe_do_nothing);
#endif
return;
}
/**
* @brief Creates an empty Nopoll context.
*/
noPollCtx * nopoll_ctx_new (void) {
noPollCtx * result = nopoll_new (noPollCtx, 1);
if (result == NULL)
return NULL;
#if defined(NOPOLL_OS_WIN32)
if (! nopoll_win32_init (result))
return NULL;
#endif
/* set initial reference */
result->conn_id = 1;
result->refs = 1;
result->conn_id = 1;
/* 20 seconds for connection timeout */
result->conn_connect_std_timeout = 20000000;
/* default log initialization */
result->not_executed = nopoll_true;
result->debug_enabled = nopoll_false;
/* colored log */
result->not_executed_color = nopoll_true;
result->debug_color_enabled = nopoll_false;
/* default back log */
result->backlog = 5;
/* current list length */
result->conn_length = 0;
#if !defined(NOPOLL_OS_WIN32)
/* install sigpipe handler */
// signal (SIGPIPE, __nopoll_ctx_sigpipe_do_nothing);
#endif
/* setup default protocol version */
result->protocol_version = 13;
/* create mutexes */
result->ref_mutex = nopoll_mutex_create ();
return result;
}
/**
* @brief Allows to acquire a reference to the provided context. This
* reference is released by calling to \ref nopoll_ctx_unref.
*
* @param ctx The context to acquire a reference.
*
* @return The function returns nopoll_true in the case the reference
* was acquired, otherwise nopoll_false is returned.
*/
nopoll_bool nopoll_ctx_ref (noPollCtx * ctx)
{
/* return false value */
nopoll_return_val_if_fail (ctx, ctx, nopoll_false);
/* acquire mutex here */
nopoll_mutex_lock (ctx->ref_mutex);
ctx->refs++;
/* release mutex here */
nopoll_mutex_unlock (ctx->ref_mutex);
return nopoll_true;
}
/**
* @brief allows to release a reference acquired to the provided
* noPoll context.
*
* @param ctx The noPoll context reference to release..
*/
void nopoll_ctx_unref (noPollCtx * ctx)
{
noPollCertificate * cert;
int iterator;
nopoll_return_if_fail (ctx, ctx);
/* acquire mutex here */
nopoll_mutex_lock (ctx->ref_mutex);
ctx->refs--;
if (ctx->refs != 0) {
/* release mutex here */
nopoll_mutex_unlock (ctx->ref_mutex);
return;
}
/* release mutex here */
nopoll_mutex_unlock (ctx->ref_mutex);
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Releasing no poll context %p (%d, conns: %d)", ctx, ctx->refs, ctx->conn_length);
iterator = 0;
while (iterator < ctx->certificates_length) {
/* get reference */
cert = &(ctx->certificates[iterator]);
/* release */
nopoll_free (cert->serverName);
nopoll_free (cert->certificateFile);
nopoll_free (cert->privateKey);
nopoll_free (cert->optionalChainFile);
/* next position */
iterator++;
} /* end while */
/* release mutex */
nopoll_mutex_destroy (ctx->ref_mutex);
/* release all certificates buckets */
nopoll_free (ctx->certificates);
/* release connection */
nopoll_free (ctx->conn_list);
ctx->conn_length = 0;
nopoll_free (ctx);
return;
}
/**
* @brief Allows to get current reference counting for the provided
* context.
*
* @param ctx The context the reference counting is being requested.
*
* @return The reference counting or -1 if it fails.
*/
int nopoll_ctx_ref_count (noPollCtx * ctx)
{
int result;
if (! ctx)
return -1;
/* lock */
nopoll_mutex_lock (ctx->ref_mutex);
result = ctx->refs;
/* unlock */
nopoll_mutex_unlock (ctx->ref_mutex);
return result;
}
/**
* @internal Function used to register the provided connection on the
* provided context.
*
* @param ctx The context where the connection will be registered.
*
* @param conn The connection to be registered.
*
* @return nopoll_true if the connection was registered, otherwise
* nopoll_false is returned.
*/
nopoll_bool nopoll_ctx_register_conn (noPollCtx * ctx,
noPollConn * conn)
{
int iterator;
nopoll_return_val_if_fail (ctx, ctx && conn, nopoll_false);
/* acquire mutex here */
nopoll_mutex_lock (ctx->ref_mutex);
/* get connection */
conn->id = ctx->conn_id;
ctx->conn_id ++;
/* register connection */
iterator = 0;
while (iterator < ctx->conn_length) {
/* register reference */
if (ctx->conn_list[iterator] == 0) {
ctx->conn_list[iterator] = conn;
/* update connection list number */
ctx->conn_num++;
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "registered connection id %d, role: %d", conn->id, conn->role);
/* release */
nopoll_mutex_unlock (ctx->ref_mutex);
/* acquire reference */
nopoll_ctx_ref (ctx);
/* acquire a reference to the conection */
nopoll_conn_ref (conn);
/* release mutex here */
return nopoll_true;
}
iterator++;
} /* end while */
/* if reached this place it means no more buckets are
* available, acquire more memory (increase 10 by 10) */
ctx->conn_length += 10;
ctx->conn_list = (noPollConn**) nopoll_realloc (ctx->conn_list, sizeof (noPollConn *) * (ctx->conn_length));
if (ctx->conn_list == NULL) {
/* release mutex */
nopoll_mutex_unlock (ctx->ref_mutex);
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "General connection registration error, memory acquisition failed..");
return nopoll_false;
} /* end if */
/* clear new positions */
iterator = (ctx->conn_length - 10);
while (iterator < ctx->conn_length) {
ctx->conn_list[iterator] = 0;
/* next position */
iterator++;
} /* end while */
/* release mutex here */
nopoll_mutex_unlock (ctx->ref_mutex);
/* ok, now register connection because we have memory */
return nopoll_ctx_register_conn (ctx, conn);
}
/**
* @internal Function used to register the provided connection on the
* provided context.
*
* @param ctx The context where the connection will be registered.
*
* @param conn The connection to be registered.
*/
void nopoll_ctx_unregister_conn (noPollCtx * ctx,
noPollConn * conn)
{
int iterator;
nopoll_return_if_fail (ctx, ctx && conn);
/* acquire mutex here */
nopoll_mutex_lock (ctx->ref_mutex);
/* find the connection and remove it from the array */
iterator = 0;
while (iterator < ctx->conn_length) {
/* check the connection reference */
if (ctx->conn_list && ctx->conn_list[iterator] && ctx->conn_list[iterator]->id == conn->id) {
/* remove reference */
ctx->conn_list[iterator] = NULL;
/* update connection list number */
ctx->conn_num--;
/* release */
nopoll_mutex_unlock (ctx->ref_mutex);
/* acquire a reference to the conection */
nopoll_conn_unref (conn);
break;
} /* end if */
iterator++;
} /* end while */
/* release mutex here */
nopoll_mutex_unlock (ctx->ref_mutex);
return;
}
/**
* @brief Allows to get number of connections currently registered.
*
* @param ctx The context where the operation is requested.
*
* @return Number of connections registered on this context or -1 if it fails.
*/
int nopoll_ctx_conns (noPollCtx * ctx)
{
nopoll_return_val_if_fail (ctx, ctx, -1);
return ctx->conn_num;
}
/**
* @brief Allows to find the certificate associated to the provided serverName.
*
* @param ctx The context where the operation will take place.
*
* @param serverName the servername to use as pattern to find the
* right certificate. If NULL is provided the first certificate not
* refering to any serverName will be returned.
*
* @param certificateFile If provided a reference and the function
* returns nopoll_true, it will contain the certificateFile found.
*
* @param privateKey If provided a reference and the function
* returns nopoll_true, it will contain the privateKey found.
*
* @param optionalChainFile If provided a reference and the function
* returns nopoll_true, it will contain the optionalChainFile found.
*
* @return nopoll_true in the case the certificate was found,
* otherwise nopoll_false is returned.
*/
nopoll_bool nopoll_ctx_find_certificate (noPollCtx * ctx,
const char * serverName,
const char ** certificateFile,
const char ** privateKey,
const char ** optionalChainFile)
{
noPollCertificate * cert;
int iterator = 0;
nopoll_return_val_if_fail (ctx, ctx, nopoll_false);
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Finding a certificate for serverName=%s", serverName ? serverName : "<not defined>");
while (iterator < ctx->certificates_length) {
/* get cert */
cert = &(ctx->certificates[iterator]);
if (cert) {
/* found a certificate */
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, " certificate stored associated to serverName=%s", cert->serverName ? cert->serverName : "<not defined>");
if ((serverName == NULL && cert->serverName == NULL) ||
(nopoll_cmp (serverName, cert->serverName))) {
if (certificateFile)
(*certificateFile) = cert->certificateFile;
if (privateKey)
(*privateKey) = cert->privateKey;
if (optionalChainFile)
(*optionalChainFile) = cert->optionalChainFile;
return nopoll_true;
} /* end if */
} /* end if */
/* next position */
iterator++;
}
/* check for default certificate when serverName isn't defined */
if (serverName == NULL) {
/* requested a certificate for an undefined serverName */
iterator = 0;
while (iterator < ctx->certificates_length) {
/* get cert */
cert = &(ctx->certificates[iterator]);
if (cert) {
/* found a certificate */
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, " serverName not defined, selecting first certificate from the list");
if (certificateFile)
(*certificateFile) = cert->certificateFile;
if (privateKey)
(*privateKey) = cert->privateKey;
if (optionalChainFile)
(*optionalChainFile) = cert->optionalChainFile;
return nopoll_true;
} /* end if */
} /* end if */
/* next position */
iterator++;
} /* end if */
return nopoll_false;
}
/**
* @brief Allows to install a certificate to be used in general by all
* listener connections working under the provided context.
*
* @param ctx The context where the certificate will be installed.
*
* @param serverName The optional server name to to limit the use of
* this certificate to the value provided here. Provide a NULL value
* to make the certificate provide to work under any server notified
* (Host: header) or via SNI (server name identification associated to
* the TLS transport).
*
* @param certificateFile The certificate file to be installed.
*
* @param privateKey The private key file to use used.
*
* @param optionalChainFile Optional chain file with additional
* material to complete the certificate definition.
*
* @return nopoll_true if the certificate was installed otherwise
* nopoll_false. The function returns nopoll_false when ctx, certificateFile or privateKey are NULL.
*/
nopoll_bool nopoll_ctx_set_certificate (noPollCtx * ctx,
const char * serverName,
const char * certificateFile,
const char * privateKey,
const char * optionalChainFile)
{
int length;
noPollCertificate * cert;
/* check values before proceed */
nopoll_return_val_if_fail (ctx, ctx && certificateFile && privateKey, nopoll_false);
/* check if the certificate is already installed */
if (nopoll_ctx_find_certificate (ctx, serverName, NULL, NULL, NULL))
return nopoll_true;
/* update certificate storage to hold all values */
ctx->certificates_length++;
length = ctx->certificates_length;
if (length == 1)
ctx->certificates = nopoll_new (noPollCertificate, 1);
else
ctx->certificates = (noPollCertificate *) nopoll_realloc (ctx->certificates, sizeof (noPollCertificate) * (length));
/* hold certificate */
cert = &(ctx->certificates[length - 1]);
cert->serverName = NULL;
if (serverName)
cert->serverName = nopoll_strdup (serverName);
cert->certificateFile = NULL;
if (certificateFile)
cert->certificateFile = nopoll_strdup (certificateFile);
cert->privateKey = NULL;
if (privateKey)
cert->privateKey = nopoll_strdup (privateKey);
cert->optionalChainFile = NULL;
if (optionalChainFile)
cert->optionalChainFile = nopoll_strdup (optionalChainFile);
return nopoll_true;
}
/**
* @brief Allows to configure the on open handler, the handler that is
* called when it is received an incoming websocket connection and all
* websocket client handshake data was received (but still not required).
*
* This handler differs from \ref nopoll_ctx_set_on_accept this
* handler is called after all client handshake data was received.
*
* Note the connection is still not fully working at this point
* because the handshake hasn't been sent to the remote peer yet. This
* means that attempting to send any content inside this handler (for
* example by using \ref nopoll_conn_send_text) will cause a protocol
* violation (because remote side is expecting a handshake reply but
* received something different).
*
* In the case you want to sent content right away after receiving a
* connection (on a listener), you can use \ref
* nopoll_ctx_set_on_ready "On Ready" handler which is called just
* after the connection has been fully accepted and handshake reply is
* fully written.
*
* @param ctx The context that will be configured.
*
* @param on_open The handler to be configured on this context.
*
* @param user_data User defined pointer to be passed to the on open
* handler
*/
void nopoll_ctx_set_on_open (noPollCtx * ctx,
noPollActionHandler on_open,
noPollPtr user_data)
{
nopoll_return_if_fail (ctx, ctx && on_open);
/* set the handler */
ctx->on_open = on_open;
if (ctx->on_open == NULL)
ctx->on_open_data = NULL;
else
ctx->on_open_data = user_data;
return;
}
/**
* @brief Allows to configure a handler that is called when a
* connection is received and it is ready to send and receive because
* all WebSocket handshake protocol finished OK.
*
* Unlike handlers configured at \ref nopoll_ctx_set_on_open and \ref
* nopoll_ctx_set_on_accept which get notified when the connection
* isn't still working (because WebSocket handshake wasn't finished
* yet), on read handlers configured here will get called just after
* the WebSocket handshake has taken place.
*
* @param ctx The context that will be configured.
*
* @param on_ready The handler to be called when a connection is fully
* ready to send and receive content because WebSocket handshake has
* finished. The function must return nopoll_true to accept the
* connection. By returning nopoll_false the handler is signalling to
* terminate the connection.
*
* @param user_data Optional user data pointer passed to the on ready
* handler.
*
*/
void nopoll_ctx_set_on_ready (noPollCtx * ctx,
noPollActionHandler on_ready,
noPollPtr user_data)
{
nopoll_return_if_fail (ctx, ctx && on_ready);
/* set the handler */
ctx->on_ready = on_ready;
if (ctx->on_ready == NULL)
ctx->on_ready_data = NULL;
else
ctx->on_ready_data = user_data;
return;
}
/**
* @brief Allows to configure the accept handler that will be called
* when a connection is received but before any handshake takes place.
*
* @param ctx The context that will be configured.
*
* @param on_accept The handler to be called when a connection is
* received. Here the handler must return nopoll_true to accept the
* connection, otherwise nopoll_false should be returned.
*
* @param user_data Optional user data pointer passed to the on accept
* handler.
*
*/
void nopoll_ctx_set_on_accept (noPollCtx * ctx,
noPollActionHandler on_accept,
noPollPtr user_data)
{
nopoll_return_if_fail (ctx, ctx && on_accept);
/* set the handler */
ctx->on_accept = on_accept;
if (ctx->on_accept == NULL)
ctx->on_accept_data = NULL;
else
ctx->on_accept_data = user_data;
return;
}
/**
* @brief Allows to set a general handler to get notifications about a
* message received over any connection that is running under the
* provided context (noPollCtx).
*
* @param ctx The context where the notification will happen
*
* @param on_msg The handler to be called when an incoming message is
* received.
*
* @param user_data User defined pointer that is passed in into the
* handler when called.
*
* Note that the handler configured here will be overriden by the handler configured by \ref nopoll_conn_set_on_msg
*
*/
void nopoll_ctx_set_on_msg (noPollCtx * ctx,
noPollOnMessageHandler on_msg,
noPollPtr user_data)
{
nopoll_return_if_fail (ctx, ctx);
/* set new handler */
ctx->on_msg = on_msg;
ctx->on_msg_data = user_data;
return;
}
/**
* @brief Allows to configure the handler that will be used to let
* user land code to define OpenSSL SSL_CTX object.
*
* By default, SSL_CTX (SSL Context) object is created by default
* settings that works for most of the cases. In the case you want to
* configure particular configurations that should be enabled on the
* provided SSL_CTX that is going to be used by the client ---while
* connecting--- or server ---while receiving a connection--- then use
* this function to setup your creator handler.
*
* See \ref noPollSslContextCreator for more information about this
* handler.
*
*/
void nopoll_ctx_set_ssl_context_creator (noPollCtx * ctx,
noPollSslContextCreator context_creator,
noPollPtr user_data)
{
if (ctx == NULL)
return;
/* set handlers as indicated by the caller */
ctx->context_creator = context_creator;
ctx->context_creator_data = user_data;
return;
}
/**
* @brief Allows to configure a function that will implement an post SSL/TLS check.
*
* See the following function to get more information: \ref noPollSslPostCheck
*
* @param ctx The context where the operation is taking place.
*
* @param post_ssl_check The handler that is going to be called
* everything a new connection with SSL is established by a client or
* received by a server. The handler is executed right after the SSL
* handshake finishes without error.
*
* @param user_data A reference to user defined pointer that will be
* passed in to the handler.
*/
void nopoll_ctx_set_post_ssl_check (noPollCtx * ctx,
noPollSslPostCheck post_ssl_check,
noPollPtr user_data)
{
if (ctx == NULL)
return;
/* set handlers as indicated by the caller */
ctx->post_ssl_check = post_ssl_check;
ctx->post_ssl_check_data = user_data;
return;
}
/**
* @brief Allows to iterate over all connections currently registered
* on the provided context, optionally stopping the foreach process,
* returning the connection reference selected if the foreach handler
* returns nopoll_true.
*
* @param ctx The nopoll context where the foreach operation will take
* place.
*
* @param foreach The foreach handler to be called for each connection
* registered.
*
* @param user_data An optional reference to a pointer that will be
* passed to the handler.
*
* @return Returns the connection selected (in the case the foreach
* function returns nopoll_false) or NULL in the case all foreach
* executions returned nopoll_true. Keep in mind the function also
* returns NULL if ctx or foreach parameter is NULL.
*
* See \ref noPollForeachConn for a signature example.
*/
noPollConn * nopoll_ctx_foreach_conn (noPollCtx * ctx,
noPollForeachConn foreach,
noPollPtr user_data)
{
noPollConn * result;
int iterator;
nopoll_return_val_if_fail (ctx, ctx && foreach, NULL);
/* acquire here the mutex to protect connection list */
nopoll_mutex_lock (ctx->ref_mutex);
/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Doing foreach over conn_length array (%p): %d", ctx, ctx->conn_length); */
/* find the connection and remove it from the array */
iterator = 0;
while (iterator < ctx->conn_length) {
/* check the connection reference */
if (ctx->conn_list[iterator]) {
/* call to notify connection */
if (foreach (ctx, ctx->conn_list[iterator], user_data)) {
/* get a reference to avoid races
* after releasing the mutex */
result = ctx->conn_list[iterator];
/* release */
nopoll_mutex_unlock (ctx->ref_mutex);
/* release here the mutex to protect connection list */
return result;
} /* end if */
} /* end if */
iterator++;
} /* end while */
/* release here the mutex to protect connection list */
nopoll_mutex_unlock (ctx->ref_mutex);
return NULL;
}
/**
* @brief Allows to change the protocol version that is send in all
* client connections created under the provided context and the
* protocol version accepted by listener created under this context
* too.
*
* This is a really basic (mostly fake) protocol version support
* because it only allows to change the version string sent (but
* nothing more for now). It is useful for testing purposes.
*
* @param ctx The noPoll context where the protocol version change
* will be applied.
*
* @param version The value representing the protocol version. By
* default this function isn't required to be called because it
* already has the right protocol value configured (13).
*/
void nopoll_ctx_set_protocol_version (noPollCtx * ctx, int version)
{
/* check input data */
nopoll_return_if_fail (ctx, ctx || version);
/* setup the new protocol version */
ctx->protocol_version = version;
return;
}
/* @} */

View File

@ -0,0 +1,94 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_decl.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR STORE_ATTR = __FILE__;
#endif
/**
* \addtogroup nopoll_decl_module
* @{
*/
/**
* @brief Calloc helper for nopoll library.
*
* @param count How many items to allocate.
* @param size Size of one item.
*
* @return A newly allocated pointer.
* @see nopoll_free
*/
noPollPtr nopoll_calloc(size_t count, size_t size)
{
return (void *)os_calloc (count, size);
}
/**
* @brief Realloc helper for nopoll library.
*
* @param ref the reference to reallocate.
* @param size Size of the new reference.
*
* @return A newly allocated pointer.
* @see nopoll_free
*/
noPollPtr nopoll_realloc(noPollPtr ref, size_t size)
{
return (void *)os_realloc (ref, size);
}
/**
* @brief Allows to deallocate memory referenced by <i>ref</i> but
* checking before that the reference is different from null.
*
* @param ref The reference to clear.
*/
void nopoll_free (noPollPtr ref)
{
os_free (ref);
return;
}
/**
* @}
*/

View File

@ -0,0 +1,233 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_io.h>
#include <nopoll_private.h>
typedef struct _noPollSelect {
noPollCtx * ctx;
fd_set set;
int length;
int max_fds;
} noPollSelect;
/**
* @internal nopoll implementation to create a compatible "select" IO
* call fd set reference.
*
* @return A newly allocated fd_set reference.
*/
noPollPtr nopoll_io_wait_select_create (noPollCtx * ctx)
{
noPollSelect * select = nopoll_new (noPollSelect, 1);
/* set default behaviour expected for the set */
select->ctx = ctx;
/* clear the set */
FD_ZERO (&(select->set));
return select;
}
/**
* @internal noPoll implementation to destroy the "select" IO call
* created by the default create.
*
* @param fd_group The fd group to be deallocated.
*/
void nopoll_io_wait_select_destroy (noPollCtx * ctx, noPollPtr fd_group)
{
fd_set * __fd_set = (fd_set *) fd_group;
/* release memory allocated */
nopoll_free (__fd_set);
/* nothing more to do */
return;
}
/**
* @internal noPoll implementation to clear the "select" IO call
* created by the default create.
*
* @param fd_group The fd group to be deallocated.
*/
void nopoll_io_wait_select_clear (noPollCtx * ctx, noPollPtr __fd_group)
{
noPollSelect * select = (noPollSelect *) __fd_group;
/* clear the fd set */
select->length = 0;
FD_ZERO (&(select->set));
/* nothing more to do */
return;
}
/**
* @internal Default internal implementation for the wait operation to
* change its status at least one socket description inside the fd set
* provided.
*
* @param __fd_group The fd set having all sockets to be watched.
* @param wait_to The operation requested.
*
* @return Number of connections that changed or -1 if something wailed
*/
int nopoll_io_wait_select_wait (noPollCtx * ctx, noPollPtr __fd_group)
{
int result = -1;
struct timeval tv;
noPollSelect * _select = (noPollSelect *) __fd_group;
/* init wait */
tv.tv_sec = 0;
tv.tv_usec = 500000;
result = select (_select->max_fds + 1, &(_select->set), NULL, NULL, &tv);
/* check result */
if ((result == NOPOLL_SOCKET_ERROR) && (errno == NOPOLL_EINTR))
return -1;
return result;
}
/**
* @internal noPoll select implementation for the "add to" on fd set
* operation.
*
* @param fds The socket descriptor to be added.
*
* @param fd_set The fd set where the socket descriptor will be added.
*/
nopoll_bool nopoll_io_wait_select_add_to (int fds,
noPollCtx * ctx,
noPollConn * conn,
noPollPtr __fd_set)
{
noPollSelect * select = (noPollSelect *) __fd_set;
if (fds < 0) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL,
"received a non valid socket (%d), unable to add to the set", fds);
return nopoll_false;
}
/* set the value */
FD_SET (fds, &(select->set));
/* update length */
select->length++;
/* update max fds */
if (fds > select->max_fds)
select->max_fds = fds;
return nopoll_true;
}
/**
* @internal
*
* @brief Default noPoll implementation for the "is set" on fd
* set operation.
*
* @param fds The socket descriptor to be checked to be active on the
* given fd group.
*
* @param fd_set The fd set where the socket descriptor will be checked.
*/
nopoll_bool nopoll_io_wait_select_is_set (noPollCtx * ctx,
int fds,
noPollPtr __fd_set)
{
noPollSelect * select = (noPollSelect *) __fd_set;
return FD_ISSET (fds, &(select->set));
}
/**
* @brief Creates an object that represents the best IO wait mechanism
* found on the current system.
*
* @param ctx The context where the engine will be created/associated.
*
* @param engine Use \ref NOPOLL_IO_ENGINE_DEFAULT or the engine you
* want to use.
*
* @return The selected IO wait mechanism or NULL if it fails.
*/
noPollIoEngine * nopoll_io_get_engine (noPollCtx * ctx, noPollIoEngineType engine_type)
{
noPollIoEngine * engine = nopoll_new (noPollIoEngine, 1);
if (engine == NULL)
return NULL;
/* configure default implementation */
engine->create = nopoll_io_wait_select_create;
engine->destroy = nopoll_io_wait_select_destroy;
engine->clear = nopoll_io_wait_select_clear;
engine->wait = nopoll_io_wait_select_wait;
engine->addto = nopoll_io_wait_select_add_to;
engine->isset = nopoll_io_wait_select_is_set;
/* call to create the object */
engine->ctx = ctx;
engine->io_object = engine->create (ctx);
/* return the engine that was created */
return engine;
}
/**
* @brief Release the io engine created by \ref nopoll_io_get_engine.
*
* @param engine The engine to be released.
*/
void nopoll_io_release_engine (noPollIoEngine * engine)
{
if (engine == NULL)
return;
engine->destroy (engine->ctx, engine->io_object);
nopoll_free (engine);
return;
}

View File

@ -0,0 +1,441 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_listener.h>
#include <nopoll_private.h>
/**
* \defgroup nopoll_listener noPoll Listener: functions required to create WebSocket listener connections.
*/
/**
* \addtogroup nopoll_listener
* @{
*/
/**
* @internal Creates a listener socket on the provided port.
*/
NOPOLL_SOCKET nopoll_listener_sock_listen (noPollCtx * ctx,
const char * host,
const char * port)
{
struct hostent * he;
struct in_addr * haddr;
struct sockaddr_in saddr;
struct sockaddr_in sin;
NOPOLL_SOCKET fd;
int tries;
#if defined(NOPOLL_OS_WIN32)
int sin_size = sizeof (sin);
#else
int unit = 1;
socklen_t sin_size = sizeof (sin);
#endif
uint16_t int_port;
int bind_res;
nopoll_return_val_if_fail (ctx, ctx, -2);
nopoll_return_val_if_fail (ctx, host, -2);
nopoll_return_val_if_fail (ctx, port || strlen (port) == 0, -2);
/* resolve hostname */
he = gethostbyname (host);
if (he == NULL) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "unable to get hostname by calling gethostbyname");
return -1;
} /* end if */
haddr = ((struct in_addr *) (he->h_addr_list)[0]);
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 2) {
/* do not allow creating sockets reusing stdin (0),
stdout (1), stderr (2) */
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "failed to create listener socket: %d (errno=%d)", fd, errno);
return -1;
} /* end if */
#if defined(NOPOLL_OS_WIN32)
/* Do not issue a reuse addr which causes on windows to reuse
* the same address:port for the same process. Under linux,
* reusing the address means that consecutive process can
* reuse the address without being blocked by a wait
* state. */
/* setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&unit, sizeof(BOOL)); */
#else
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &unit, sizeof (unit));
#endif
/* get integer port */
int_port = (uint16_t) atoi (port);
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(int_port);
memcpy(&saddr.sin_addr, haddr, sizeof(struct in_addr));
/* call to bind */
tries = 0;
while (1) {
bind_res = bind(fd, (struct sockaddr *)&saddr, sizeof (struct sockaddr_in));
if (bind_res == NOPOLL_SOCKET_ERROR) {
/* check if we can retry */
tries++;
if (tries < 25) {
nopoll_log (ctx, NOPOLL_LEVEL_WARNING,
"unable to bind address (port:%u already in use or insufficient permissions, errno=%d : %s), retrying=%d on socket: %d",
int_port, errno, strerror (errno), tries, fd);
nopoll_sleep (100000);
continue;
} /* end if */
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL,
"unable to bind address (port:%u already in use or insufficient permissions, errno=%d : %s). Closing socket: %d",
int_port, errno, strerror (errno), fd);
nopoll_close_socket (fd);
return -1;
} /* end if */
/* reached this point, bind was ok */
break;
} /* end while */
if (listen(fd, ctx->backlog) == NOPOLL_SOCKET_ERROR) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "an error have occur while executing listen");
return -1;
} /* end if */
/* notify listener */
if (getsockname (fd, (struct sockaddr *) &sin, &sin_size) < -1) {
return -1;
} /* end if */
/* report and return fd */
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "running listener at %s:%d (socket: %d)", inet_ntoa(sin.sin_addr), ntohs (sin.sin_port), fd);
return fd;
}
/**
* @brief Creates a new websocket server listener on the provided host
* name and port.
*
* @param ctx The context where the operation will take place.
*
* @param host The hostname or address interface to bind on.
*
* @param port The port where to listen, or NULL to use default port: 80.
*
* @return A reference to a \ref noPollConn object representing the
* listener or NULL if it fails.
*/
noPollConn * nopoll_listener_new (noPollCtx * ctx,
const char * host,
const char * port)
{
return nopoll_listener_new_opts (ctx, NULL, host, port);
}
/**
* @brief Creates a new websocket server listener on the provided host
* name and port.
*
* @param ctx The context where the operation will take place.
*
* @param opts Optional connection options to configure this listener.
*
* @param host The hostname or address interface to bind on.
*
* @param port The port where to listen, or NULL to use default port: 80.
*
* @return A reference to a \ref noPollConn object representing the
* listener or NULL if it fails.
*/
noPollConn * nopoll_listener_new_opts (noPollCtx * ctx,
noPollConnOpts * opts,
const char * host,
const char * port)
{
NOPOLL_SOCKET session;
noPollConn * listener;
nopoll_return_val_if_fail (ctx, ctx && host, NULL);
/* call to create the socket */
session = nopoll_listener_sock_listen (ctx, host, port);
if (session == NOPOLL_INVALID_SOCKET) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Failed to start listener error was: %d", errno);
return NULL;
} /* end if */
/* create noPollConn ection object */
listener = nopoll_new (noPollConn, 1);
listener->refs = 1;
listener->session = session;
listener->ctx = ctx;
listener->role = NOPOLL_ROLE_MAIN_LISTENER;
/* record host and port */
listener->host = nopoll_strdup (host);
listener->port = nopoll_strdup (port);
/* register connection into context */
nopoll_ctx_register_conn (ctx, listener);
/* configure default handlers */
listener->receive = nopoll_conn_default_receive;
listener->sends = nopoll_conn_default_send;
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Listener created, started: %s:%s (socket: %d)", listener->host, listener->port, listener->session);
return listener;
}
/**
* @brief Allows to create a new WebSocket listener but expecting the
* incoming connection to be under TLS supervision. The function works
* like \ref nopoll_listener_new (providing wss:// services).
*
* @param ctx The context where the operation will take place.
*
* @param host The hostname or address interface to bind on.
*
* @param port The port where to listen, or NULL to use default port: 80.
*
* @return A reference to a \ref noPollConn object representing the
* listener or NULL if it fails.
*/
noPollConn * nopoll_listener_tls_new (noPollCtx * ctx,
const char * host,
const char * port)
{
return nopoll_listener_tls_new_opts (ctx, NULL, host, port);
}
/**
* @brief Allows to create a new WebSocket listener but expecting the
* incoming connection to be under TLS supervision. The function works
* like \ref nopoll_listener_new (providing wss:// services).
*
* @param ctx The context where the operation will take place.
*
* @param opts The connection options to configure this particular
* listener.
*
* @param host The hostname or address interface to bind on.
*
* @param port The port where to listen, or NULL to use default port: 80.
*
* @return A reference to a \ref noPollConn object representing the
* listener or NULL if it fails.
*/
noPollConn * nopoll_listener_tls_new_opts (noPollCtx * ctx,
noPollConnOpts * opts,
const char * host,
const char * port)
{
noPollConn * listener;
/* call to get listener from base function */
listener = nopoll_listener_new (ctx, host, port);
if (! listener)
return listener;
/* setup TLS support */
listener->tls_on = nopoll_true;
listener->opts = opts;
return listener;
}
/**
* @brief Allows to configure the TLS certificate and key to be used
* on the provided connection.
*
* @param listener The listener that is going to be configured with the providing certificate and key.
*
* @param certificate The path to the public certificate file (PEM
* format) to be used for every TLS connection received under the
* provided listener.
*
* @param private_key The path to the key file (PEM format) to be used for
* every TLS connection received under the provided listener.
*
* @param chain_file The path to additional chain certificates (PEM
* format). You can safely pass here a NULL value.
*
* @return nopoll_true if the certificates were configured, otherwise
* nopoll_false is returned.
*/
nopoll_bool nopoll_listener_set_certificate (noPollConn * listener,
const char * certificate,
const char * private_key,
const char * chain_file)
{
// FILE * handle;
//
// if (! listener || ! certificate || ! private_key)
// return nopoll_false;
//
// /* check certificate file */
// handle = fopen (certificate, "r");
// if (! handle) {
// nopoll_log (listener->ctx, NOPOLL_LEVEL_CRITICAL, "Failed to open certificate file from %s", certificate);
// return nopoll_false;
// } /* end if */
// fclose (handle);
//
// /* check private file */
// handle = fopen (private_key, "r");
// if (! handle) {
// nopoll_log (listener->ctx, NOPOLL_LEVEL_CRITICAL, "Failed to open private key file from %s", private_key);
// return nopoll_false;
// } /* end if */
// fclose (handle);
//
// if (chain_file) {
// /* check private file */
// handle = fopen (chain_file, "r");
// if (! handle) {
// nopoll_log (listener->ctx, NOPOLL_LEVEL_CRITICAL, "Failed to open chain certificate file from %s", private_key);
// return nopoll_false;
// } /* end if */
// fclose (handle);
// } /* end if */
//
// /* copy certificates to be used */
// listener->certificate = nopoll_strdup (certificate);
// listener->private_key = nopoll_strdup (private_key);
// if (chain_file)
// listener->chain_certificate = nopoll_strdup (chain_file);
//
// nopoll_log (listener->ctx, NOPOLL_LEVEL_DEBUG, "Configured certificate: %s, key: %s, for conn id: %d",
// listener->certificate, listener->private_key, listener->id);
/* certificates configured */
return nopoll_true;
}
/**
* @brief Creates a websocket listener from the socket provided.
*
* @param ctx The context where the listener will be associated.
*
* @param session The session to associate to the listener.
*
* @return A reference to a listener connection object or NULL if it
* fails.
*/
noPollConn * nopoll_listener_from_socket (noPollCtx * ctx,
NOPOLL_SOCKET session)
{
noPollConn * listener;
struct sockaddr_in sin;
#if defined(NOPOLL_OS_WIN32)
/* windows flavors */
int sin_size = sizeof (sin);
#else
/* unix flavors */
socklen_t sin_size = sizeof (sin);
#endif
nopoll_return_val_if_fail (ctx, ctx && session > 0, NULL);
/* create noPollConn ection object */
listener = nopoll_new (noPollConn, 1);
listener->refs = 1;
listener->session = session;
listener->ctx = ctx;
listener->role = NOPOLL_ROLE_LISTENER;
/* get peer value */
memset (&sin, 0, sizeof (struct sockaddr_in));
if (getpeername (session, (struct sockaddr *) &sin, &sin_size) < -1) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "unable to get remote hostname and port");
return NULL;
} /* end if */
/* record host and port */
/* lock mutex here to protect inet_ntoa */
listener->host = nopoll_strdup (inet_ntoa (sin.sin_addr));
/* release mutex here to protect inet_ntoa */
listener->port = nopoll_strdup_printf ("%d", ntohs (sin.sin_port));
/* configure default handlers */
listener->receive = nopoll_conn_default_receive;
listener->sends = nopoll_conn_default_send;
/* register connection into context */
if (! nopoll_ctx_register_conn (ctx, listener)) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Failed to register connection into the context, unable to create connection");
nopoll_conn_ref (listener);
return NULL;
} /* end if */
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Listener created, started: %s:%s (socket: %d)", listener->host, listener->port, listener->session);
/* reduce reference counting here because ctx_register_conn
* already acquired a reference */
nopoll_conn_unref (listener);
return listener;
}
/**
* @internal Public function that performs a TCP listener accept.
*
* @param server_socket The listener socket where the accept()
* operation will be called.
*
* @return Returns a connected socket descriptor or -1 if it fails.
*/
NOPOLL_SOCKET nopoll_listener_accept (NOPOLL_SOCKET server_socket)
{
struct sockaddr_in inet_addr;
#if defined(NOPOLL_OS_WIN32)
int addrlen;
#else
socklen_t addrlen;
#endif
addrlen = sizeof(struct sockaddr_in);
/* accept the connection new connection */
return accept (server_socket, (struct sockaddr *)&inet_addr, &addrlen);
}
/* @} */

View File

@ -0,0 +1,245 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll.h>
#include <nopoll_private.h>
/**
* \defgroup nopoll_log noPoll Log: Console log reporting for noPoll library
*/
/**
* \addtogroup nopoll_log
* @{
*/
/**
* @brief Allows to check if the log reporting inside the system is
* enabled.
*
* @return nopoll_true if the log is enabled or nopoll_false
*/
nopoll_bool nopoll_log_is_enabled (noPollCtx * ctx)
{
if (ctx == NULL)
return nopoll_false;
/* return current value */
return ctx->debug_enabled;
}
/**
*
* @brief Allows to get current log configuration, to use colors.
*
* @return nopoll_true if the color log is enabled or nopoll_false
*/
nopoll_bool nopoll_log_color_is_enabled (noPollCtx * ctx)
{
if (ctx == NULL)
return nopoll_false;
/* return current value */
return ctx->debug_color_enabled;
}
/**
* @brief Allows to control how to activate the log reporting to the
* console from the nopoll core library.
*
* @param ctx The context where the operation will take place.
*
* @param value nopoll_true to enable log to console, otherwise nopoll_false is
* returned.
*/
void nopoll_log_enable (noPollCtx * ctx, nopoll_bool value)
{
if (ctx == NULL)
return;
/* activate debuging according to the variable */
ctx->debug_enabled = value;
return;
}
/**
* @brief Allows to control how to activate the colog log reporting to
* the console from the nopoll core library.
*
* @param ctx The context where the operation will take place.
*
* @param value nopoll_true to enable log to console, otherwise nopoll_false is
* returned.
*/
void nopoll_log_color_enable (noPollCtx * ctx, nopoll_bool value)
{
if (ctx == NULL)
return;
/* activate color debuging according to the variable */
ctx->debug_color_enabled = value;
return;
}
/**
* @brief Allows to define a log handler that will receive all logs
* produced under the provided content.
*
* @param ctx The context that is going to be configured.
*
* @param handler The handler to be called for each log to be
* notified. Passing in NULL is allowed to remove any previously
* configured handler.
*
* @param user_data User defined pointer to be passed in into the
* handler configured along with the log notified.
*/
void nopoll_log_set_handler (noPollCtx * ctx, noPollLogHandler handler, noPollPtr user_data)
{
nopoll_return_if_fail (ctx, ctx);
ctx->log_handler = handler;
ctx->log_user_data = user_data;
return;
}
/**
* @internal Allows to drop a log to the console.
*
* This function allow to drop a log to the console using the given
* domain, as an identification of which subsystem have reported the
* information, and report level. This report level is used to notify
* the consideration of the log reported.
*
* The function allows to provide a printf like interface to report
* messages. Here are some examples:
*
* \code
* // drop a log about current library initialization
* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "library properly initialized status=%d", status);
* \endcode
*
*
* @param ctx The context where the operation will take place.
*
* @param level The level that this message is classificed.
*
* @param message The message to report. The message to report must be
* not NULL.
*/
void __nopoll_log (noPollCtx * ctx, const char * function_name, const char * file, int line, noPollDebugLevel level, const char * message, ...)
{
#ifdef SHOW_DEBUG_LOG
va_list args;
char * log_msg;
char * log_msg2;
if (ctx && ctx->log_handler) {
/* print the message */
va_start (args, message);
log_msg = nopoll_strdup_printfv (message, args);
va_end (args);
log_msg2 = log_msg;
log_msg = nopoll_strdup_printf ("%s:%d %s ", file, line, log_msg);
nopoll_free (log_msg2);
ctx->log_handler (ctx, level, log_msg, ctx->log_user_data);
nopoll_free (log_msg);
return;
}
/* check if the log is enabled */
if (! nopoll_log_is_enabled (ctx))
return;
// /* printout the process pid */
// if (nopoll_log_color_is_enabled (ctx))
// printf ("\e[1;36m(proc %d)\e[0m: ", getpid ());
// else
// printf ("(proc %d): ", getpid ());
/* drop a log according to the level */
if (nopoll_log_color_is_enabled (ctx)) {
switch (level) {
case NOPOLL_LEVEL_DEBUG:
printf ("(\e[1;32mdebug\e[0m) ");
break;
case NOPOLL_LEVEL_WARNING:
printf ("(\e[1;33mwarning\e[0m) ");
break;
case NOPOLL_LEVEL_CRITICAL:
printf ("(\e[1;31mcritical\e[0m) ");
break;
}
} else {
switch (level) {
case NOPOLL_LEVEL_DEBUG:
printf ("(debug)");
break;
case NOPOLL_LEVEL_WARNING:
printf ("(warning)");
break;
case NOPOLL_LEVEL_CRITICAL:
printf ("(critical) ");
break;
}
}
/* drop a log according to the domain */
printf ("%s:%d ", file, line);
/* print the message */
va_start (args, message);
// vprintf (message, args);
va_end (args);
printf ("\n");
/* ensure that the log is droped to the console */
// fflush (stdout);
#endif
/* return */
return;
}
/* @} */

View File

@ -0,0 +1,269 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_loop.h>
#include <nopoll_private.h>
/**
* \defgroup nopoll_loop noPoll Loop: basic support to create a watching loop for WebSocket listeners
*/
/**
* \addtogroup nopoll_loop
* @{
*/
/**
* @internal Function used by nopoll_loop_wait to register all
* connections into the io waiting object.
*/
nopoll_bool nopoll_loop_register (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data)
{
/* do not add connections that aren't working */
if (! nopoll_conn_is_ok (conn)) {
/* remove this connection from registry */
nopoll_ctx_unregister_conn (ctx, conn);
return nopoll_false; /* keep foreach, don't stop */
}
/* register the connection socket */
/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Adding socket id: %d", conn->session);*/
if (! ctx->io_engine->addto (conn->session, ctx, conn, ctx->io_engine->io_object)) {
/* remove this connection from registry */
nopoll_ctx_unregister_conn (ctx, conn);
nopoll_log (ctx, NOPOLL_LEVEL_WARNING, "Failed to add socket %d to the watching set", conn->session);
}
return nopoll_false; /* keep foreach, don't stop */
}
/**
* @internal Function used to handle incoming data from from the
* connection and to notify this data on the connection.
*/
void nopoll_loop_process_data (noPollCtx * ctx, noPollConn * conn)
{
noPollMsg * msg;
/* call to get messages from the connection */
msg = nopoll_conn_get_msg (conn);
if (msg == NULL)
return;
/* found message, notify it */
if (conn->on_msg)
conn->on_msg (ctx, conn, msg, conn->on_msg_data);
else if (ctx->on_msg)
ctx->on_msg (ctx, conn, msg, ctx->on_msg_data);
/* release message */
nopoll_msg_unref (msg);
return;
}
/**
* @internal Function used to detected which connections has something
* interesting to be notified.
*
*/
nopoll_bool nopoll_loop_process (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data)
{
int * conn_changed = (int *) user_data;
/* check if the connection have something to notify */
if (ctx->io_engine->isset (ctx, conn->session, ctx->io_engine->io_object)) {
/* call to notify action according to role */
switch (conn->role) {
case NOPOLL_ROLE_CLIENT:
case NOPOLL_ROLE_LISTENER:
/* received data, notify */
nopoll_loop_process_data (ctx, conn);
break;
case NOPOLL_ROLE_MAIN_LISTENER:
/* call to handle */
nopoll_conn_accept (ctx, conn);
break;
default:
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Found connection with unknown role, closing and dropping");
nopoll_conn_shutdown (conn);
break;
}
/* reduce connection changed */
(*conn_changed)--;
} /* end if */
return (*conn_changed) == 0;
}
/**
* @internal Function used to init internal io wait mechanism...
*
* @param ctx The noPoll context to be initialized if it wasn't
*/
void nopoll_loop_init (noPollCtx * ctx)
{
if (ctx == NULL)
return;
/* grab the mutex for the following check */
if (ctx->io_engine == NULL) {
ctx->io_engine = nopoll_io_get_engine (ctx, NOPOLL_IO_ENGINE_DEFAULT);
if (ctx->io_engine == NULL) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Failed to create IO wait engine, unable to implement wait call");
return;
}
} /* end if */
/* release the mutex */
return;
}
/**
* @brief Flag to stop the current loop implemented (if any) on the provided context.
*
* @param ctx The context where the loop is being done, and wanted to
* be stopped.
*
*/
void nopoll_loop_stop (noPollCtx * ctx)
{
if (! ctx)
return;
ctx->keep_looping = nopoll_false;
return;
} /* end if */
/**
* @brief Allows to implement a wait over all connections registered
* under the provided context during the provided timeout until
* something is detected meaningful to the user, calling to the action
* handler defined, optionally receving the user data pointer.
*
* @param ctx The context object where the wait will be implemented.
*
* @param timeout The timeout to wait for changes. If no changes
* happens, the function returns. The function will block the caller
* until a call to \ref nopoll_loop_stop is done in the case timeout
* passed is 0.
*
* @return The function returns 0 when finished or -2 in the case ctx
* is NULL or timeout is negative.
*/
int nopoll_loop_wait (noPollCtx * ctx, long timeout)
{
struct timeval start;
struct timeval stop;
struct timeval diff;
long ellapsed;
int wait_status;
nopoll_return_val_if_fail (ctx, ctx, -2);
nopoll_return_val_if_fail (ctx, timeout >= 0, -2);
/* call to init io engine */
nopoll_loop_init (ctx);
/* get as reference current time */
if (timeout > 0)
#if defined(NOPOLL_OS_WIN32)
nopoll_win32_gettimeofday (&start, NULL);
#else
gettimeofday (&start, NULL);
#endif
/* set to keep looping everything this function is called */
ctx->keep_looping = nopoll_true;
while (ctx->keep_looping) {
/* ok, now implement wait operation */
ctx->io_engine->clear (ctx, ctx->io_engine->io_object);
/* add all connections */
/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Adding connections to watch: %d", ctx->conn_num); */
nopoll_ctx_foreach_conn (ctx, nopoll_loop_register, NULL);
/* if (errno == EBADF) { */
/* detected some descriptor not properly
* working, try to check them */
/* nopoll_ctx_foreach_conn (ctx, nopoll_loop_clean_descriptors, NULL); */
/* nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Found some descriptor is not valid (errno==%d)", errno);
continue; */
/* } */ /* end if */
/* implement wait operation */
/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Waiting for changes into %d connections", ctx->conn_num); */
wait_status = ctx->io_engine->wait (ctx, ctx->io_engine->io_object);
/* nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "Waiting finished with result %d", wait_status); */
if (wait_status == -1) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Received error from wait operation, error code was: %d", errno);
break;
} /* end if */
/* check how many connections changed and restart */
if (wait_status > 0) {
/* check and call for connections with something
* interesting */
nopoll_ctx_foreach_conn (ctx, nopoll_loop_process, &wait_status);
}
/* check to stop wait operation */
if (timeout > 0) {
#if defined(NOPOLL_OS_WIN32)
nopoll_win32_gettimeofday (&stop, NULL);
#else
gettimeofday (&stop, NULL);
#endif
nopoll_timeval_substract (&stop, &start, &diff);
ellapsed = (diff.tv_sec * 1000000) + diff.tv_usec;
if (ellapsed > timeout)
break;
} /* end if */
} /* end while */
/* release engine */
nopoll_io_release_engine (ctx->io_engine);
ctx->io_engine = NULL;
return 0;
}
/* @} */

View File

@ -0,0 +1,320 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll_msg.h>
#include <nopoll_private.h>
/**
* \defgroup nopoll_msg noPoll Message: functions for handling and using noPoll messages (websocket messages)
*/
/**
* \addtogroup nopoll_msg
* @{
*/
/**
* @internal function that creates an empty message holder.
* @return A newly created reference or NULL if it fails.
*/
noPollMsg * nopoll_msg_new (void)
{
noPollMsg * msg = nopoll_new (noPollMsg, 1);
if (msg == NULL)
return NULL;
msg->refs = 1;
msg->ref_mutex = nopoll_mutex_create ();
return msg;
}
/**
* @brief Allows to get a reference to the payload content inside the
* provided websocket message.
*
* @param msg The websocket message to get the payload from.
*
* @return A reference to the payload or NULL if it fails. See \ref
* nopoll_msg_get_payload_size to get payload size.
*/
const unsigned char * nopoll_msg_get_payload (noPollMsg * msg)
{
if (msg == NULL)
return NULL;
return msg->payload;
}
/**
* @brief Allows to get the payload byte length stored on the provided
* message.
*
* @param msg The websocket message to get the payload from.
*
* @return The payload size or -1 if it fails (only when msg is NULL).
*/
int nopoll_msg_get_payload_size (noPollMsg * msg)
{
if (msg == NULL)
return -1;
return msg->payload_size;
}
/**
* @brief Allows to acquire a reference to the provided websocket
* message.
*
* @param msg The websocket message to acquire a reference.
*
* @return nopoll_true if the reference was acquired, otherwise
* nopoll_false is returned.
*/
nopoll_bool nopoll_msg_ref (noPollMsg * msg)
{
/* check recieved reference */
if (msg == NULL)
return nopoll_false;
/* acquire mutex here */
nopoll_mutex_lock (msg->ref_mutex);
msg->refs++;
/* release mutex here */
nopoll_mutex_unlock (msg->ref_mutex);
return nopoll_true;
}
/**
* @brief Allows to get current reference counting for the provided
* message.
*
* @param msg The message for which we are requesting for the
* reference counting.
*
* @return Reference counting or -1 if it fails (returned when msg
* reference received is NULL).
*/
int nopoll_msg_ref_count (noPollMsg * msg)
{
int result;
/* check recieved reference */
if (msg == NULL)
return -1;
/* acquire mutex here */
nopoll_mutex_lock (msg->ref_mutex);
result = msg->refs;
/* release mutex here */
nopoll_mutex_unlock (msg->ref_mutex);
return result;
}
/**
* @brief Allows to get if the provided message reference has FIN flag
* on (or off) to indicate if it is a final frame.
*
* When a series of messages are received and they conform together a
* single message, the last message is flagged with FIN = 1 while the
* rest before go with FIN = 0.
*
* For example, if a user level application is splitted into 4 frame
* fragments, then the WebSocket peer will receive 3 fragments with
* FIN = 0 and the last fragment with FIN = 1.
*
* You can use \ref nopoll_msg_is_fragment to know if a particular
* message was produced due to a fragmentation found at the network
* level. This happens when the entire frame wasn't sent or it
* couldn't be read entirely. In the example before, the four frames
* will be also flagged as fragments too.
*
* @param msg The message that is being checked for FIN flag.
*
* @return nopoll_true if the message is a final one, otherwise
* nopoll_false is returned. The function returns nopoll_false when
* message reference received is NULL.
*
*/
nopoll_bool nopoll_msg_is_final (noPollMsg * msg)
{
if (msg == NULL)
return nopoll_false;
return msg->has_fin;
}
/**
* @brief Allows to check if the message represents a frame fragment.
*
* The function allows to check if the provided noPollMsg is a
* fragment from a bigger frame or message that was splitted as a
* consequence of not being able to read the entire frame or because
* it wasn't sent complete from the other side. See \ref
* nopoll_msg_is_final for more information.
*
* The function also returns that the message is a fragment when the frame has FIN = 0.
*
* @param msg The message checked to be a fragment or not.
*
* @return nopoll_true if the message is a fragment, otherwise
* nopoll_false is returned.
*/
nopoll_bool nopoll_msg_is_fragment (noPollMsg * msg)
{
if (msg == NULL)
return nopoll_false;
return msg->is_fragment || msg->has_fin == 0;
}
/**
* @brief Get message OpCode to get the type of message that was
* received.
*
* @param msg The message that is being checked for its OpCode
*
* @return The op code or -1 in the case NULL reference is received.
*/
noPollOpCode nopoll_msg_opcode (noPollMsg * msg)
{
if (msg == NULL)
return NOPOLL_UNKNOWN_OP_CODE;
return (noPollOpCode) msg->op_code;
}
/**
* @brief Allows to join the provided noPollMsg references to create a
* newly allocated message (or reusing same reference but increasing reference
* counting) that contains both content.
*
* @param msg The message to be join to the next message. Headers from
* this message will be used as reference for the headers to be
* used. In the case this is NULL, the second argument will be used as
* argument and reference counting will be updated.
*
* @param msg2 The message to be join as a second part for the first
* argument.
*
* Here are some examples showing how the function works. The notation
* along the argument indicates the reference counting at the end of
* the function.
*
* msgA (2) = nopoll_msg_join (msgA (1), NULL);
* msgB (2) = nopoll_msg_join (NULL, msgB (1));
* msgC (1) = nopoll_msg_join (msgA (1), msgB (1));
* NULL = nopoll_msg_join (NULL, NULL);
*
* @return The function returns the newly allocated or reused
* reference with increased reference counting or NULL if it fails.
*/
noPollMsg * nopoll_msg_join (noPollMsg * msg, noPollMsg * msg2)
{
noPollMsg * result;
/* check for basic cases */
if (msg == NULL && msg2 == NULL)
return NULL;
if (msg == NULL && msg2) {
nopoll_msg_ref (msg2);
return msg2;
} /* ned if */
if (msg && msg2 == NULL) {
nopoll_msg_ref (msg);
return msg;
} /* end if */
/* now, join content */
result = nopoll_msg_new ();
result->has_fin = msg->has_fin;
result->op_code = msg->op_code;
result->is_masked = msg->is_masked;
if (result->is_masked)
memcpy (result->mask, msg->mask, 4);
/* copy payload size and content */
result->payload_size = msg->payload_size + msg2->payload_size;
result->payload = nopoll_new (char, result->payload_size + 1);
/* copy content from first message */
memcpy (result->payload, msg->payload, msg->payload_size);
/* copy content from second message */
memcpy (((unsigned char *) result->payload) + msg->payload_size , msg2->payload, msg2->payload_size);
/* return joined message */
return result;
}
/**
* @brief Allows to release the reference acquired, finished the
* object if all references are terminated.
*
* @param msg The websocket message to be finished.
*/
void nopoll_msg_unref (noPollMsg * msg)
{
if (msg == NULL)
return;
/* acquire mutex here */
nopoll_mutex_lock (msg->ref_mutex);
msg->refs--;
if (msg->refs != 0) {
/* release mutex here */
nopoll_mutex_unlock (msg->ref_mutex);
return;
}
/* release mutex */
nopoll_mutex_unlock (msg->ref_mutex);
nopoll_mutex_destroy (msg->ref_mutex);
/* free websocket message */
nopoll_free (msg->payload);
nopoll_free (msg);
/* release mutex here */
return;
}
/* @} */

View File

@ -0,0 +1,136 @@
/*
* LibNoPoll: A websocket library
* Copyright (C) 2013 Advanced Software Production Line, S.L.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*
* You may find a copy of the license under this software is released
* at COPYING file. This is LGPL software: you are welcome to develop
* proprietary applications using this library without any royalty or
* fee but returning back any change, improvement or addition in the
* form of source code, project image, documentation patches, etc.
*
* For commercial support on build Websocket enabled solutions
* contact us:
*
* Postal address:
* Advanced Software Production Line, S.L.
* Edificio Alius A, Oficina 102,
* C/ Antonio Suarez Nº 10,
* Alcalá de Henares 28802 Madrid
* Spain
*
* Email address:
* info@aspl.es - http://www.aspl.es/nopoll
*/
#include <nopoll.h>
#define LOG_DOMAIN "nopoll-win32"
#if defined(NOPOLL_OS_WIN32)
nopoll_bool __nopoll_win32_was_init = nopoll_false;
int nopoll_win32_init (noPollCtx * ctx)
{
WORD wVersionRequested;
WSADATA wsaData;
int error;
if (__nopoll_win32_was_init)
return nopoll_true;
wVersionRequested = MAKEWORD( 2, 2 );
error = WSAStartup( wVersionRequested, &wsaData );
if (error != NO_ERROR) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "unable to init winsock api, exiting..");
return nopoll_false;
}
nopoll_log (ctx, NOPOLL_LEVEL_DEBUG, "winsock initialization ok");
/* flag the library as initialized */
__nopoll_win32_was_init = nopoll_true;
return nopoll_true;
}
BOOL APIENTRY DllMain (HINSTANCE hInst,
DWORD reason,
LPVOID reserved)
{
/* always returns true because nopoll init is done through
* nopoll_init */
return nopoll_true;
}
int __nopoll_win32_blocking_socket_set (NOPOLL_SOCKET socket,
int status)
{
unsigned long enable = status;
return (ioctlsocket (socket, FIONBIO, &enable) == 0);
}
int nopoll_win32_nonblocking_enable (NOPOLL_SOCKET socket)
{
return __nopoll_win32_blocking_socket_set (socket, 1);
}
int nopoll_win32_blocking_enable (NOPOLL_SOCKET socket)
{
return __nopoll_win32_blocking_socket_set (socket, 0);
}
#if ! defined(HAVE_GETTIMEOFDAY)
/**
* @brief The function obtains the current time, expressed as seconds
* and microseconds since the Epoch, and store it in the timeval
* structure pointed to by tv. As posix says gettimeoday should return
* zero and should not reserve any value for error, this function
* returns zero.
*
* The timeval struct have the following members:
*
* \code
* struct timeval {
* long tv_sec;
* long tv_usec;
* } timeval;
* \endcode
*
* @param tv Timeval struct.
* @param notUsed Not defined.
*
* @return The function allways return 0.
*/
int nopoll_win32_gettimeofday(struct timeval *tv, noPollPtr notUsed)
{
union {
long long ns100;
FILETIME fileTime;
} now;
GetSystemTimeAsFileTime (&now.fileTime);
tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL);
tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL);
return (0);
} /* end gettimeofday */
#endif /* end ! defined(HAVE_GETTIMEOFDAY) */
#endif