// Copyright (c) 2014 Cesanta Software Limited // All rights reserved // // This software is dual-licensed: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. For the terms of this // license, see . // // You are free to use this software under the terms of the GNU General // Public License, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // Alternatively, you can license this software under a commercial // license, as set out in . // // $Date: 2014-09-09 17:09:33 UTC $ #ifndef NS_SKELETON_HEADER_INCLUDED #define NS_SKELETON_HEADER_INCLUDED #define NS_SKELETON_VERSION "2.0.0" #undef UNICODE // Use ANSI WinAPI functions #undef _UNICODE // Use multibyte encoding on Windows #define _MBCS // Use multibyte encoding on Windows #define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows #define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+ #undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h #define _XOPEN_SOURCE 600 // For flockfile() on Linux #define __STDC_FORMAT_MACROS // wants this for C++ #define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX #ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions #endif #define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets #ifdef _MSC_VER #pragma warning (disable : 4127) // FD_SET() emits warning, disable it #pragma warning (disable : 4204) // missing c99 support #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #ifdef _MSC_VER #pragma comment(lib, "ws2_32.lib") // Linking with winsock library #endif #include #include #ifndef EINPROGRESS #define EINPROGRESS WSAEINPROGRESS #endif #ifndef EWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK #endif #ifndef __func__ #define STRX(x) #x #define STR(x) STRX(x) #define __func__ __FILE__ ":" STR(__LINE__) #endif #ifndef va_copy #define va_copy(x,y) x = y #endif // MINGW #defines va_copy #define snprintf _snprintf #define vsnprintf _vsnprintf #define sleep(x) Sleep((x) * 1000) #define to64(x) _atoi64(x) typedef int socklen_t; typedef unsigned char uint8_t; typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned __int64 uint64_t; typedef __int64 int64_t; typedef SOCKET sock_t; #ifndef S_ISDIR #define S_ISDIR(x) ((x) & _S_IFDIR) #endif #else #include #include #include #include #include #include #include // For inet_pton() when NS_ENABLE_IPV6 is defined #include #include #include #define closesocket(x) close(x) #define __cdecl #define INVALID_SOCKET (-1) #define to64(x) strtoll(x, NULL, 10) typedef int sock_t; #endif #ifdef NS_ENABLE_DEBUG #define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ fflush(stdout); } while(0) #else #define DBG(x) #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) #endif #ifdef NS_ENABLE_SSL #ifdef __APPLE__ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif #include #else typedef void *SSL; typedef void *SSL_CTX; #endif #ifdef __cplusplus extern "C" { #endif // __cplusplus union socket_address { struct sockaddr sa; struct sockaddr_in sin; #ifdef NS_ENABLE_IPV6 struct sockaddr_in6 sin6; #else struct sockaddr sin6; #endif }; // IO buffers interface struct iobuf { char *buf; size_t len; size_t size; }; void iobuf_init(struct iobuf *, size_t initial_size); void iobuf_free(struct iobuf *); size_t iobuf_append(struct iobuf *, const void *data, size_t data_size); void iobuf_remove(struct iobuf *, size_t data_size); // Net skeleton interface // Events. Meaning of event parameter (evp) is given in the comment. enum ns_event { NS_POLL, // Sent to each connection on each call to ns_mgr_poll() NS_ACCEPT, // New connection accept()-ed. union socket_address *remote_addr NS_CONNECT, // connect() succeeded or failed. int *success_status NS_RECV, // Data has benn received. int *num_bytes NS_SEND, // Data has been written to a socket. int *num_bytes NS_CLOSE // Connection is closed. NULL }; // Callback function (event handler) prototype, must be defined by user. // Net skeleton will call event handler, passing events defined above. struct ns_connection; typedef void (*ns_callback_t)(struct ns_connection *, enum ns_event, void *evp); struct ns_mgr { struct ns_connection *active_connections; ns_callback_t callback; // Event handler function const char *hexdump_file; // Debug hexdump file path sock_t ctl[2]; // Socketpair for mg_wakeup() void *user_data; // User data }; struct ns_connection { struct ns_connection *next, *prev; // ns_mgr::active_connections linkage struct ns_connection *listener; // Set only for accept()-ed connections struct ns_mgr *mgr; sock_t sock; union socket_address sa; struct iobuf recv_iobuf; struct iobuf send_iobuf; SSL *ssl; SSL_CTX *ssl_ctx; void *connection_data; time_t last_io_time; unsigned int flags; #define NSF_FINISHED_SENDING_DATA (1 << 0) #define NSF_BUFFER_BUT_DONT_SEND (1 << 1) #define NSF_SSL_HANDSHAKE_DONE (1 << 2) #define NSF_CONNECTING (1 << 3) #define NSF_CLOSE_IMMEDIATELY (1 << 4) #define NSF_WANT_READ (1 << 5) #define NSF_WANT_WRITE (1 << 6) #define NSF_LISTENING (1 << 7) #define NSF_UDP (1 << 8) #define NSF_USER_1 (1 << 20) #define NSF_USER_2 (1 << 21) #define NSF_USER_3 (1 << 22) #define NSF_USER_4 (1 << 23) #define NSF_USER_5 (1 << 24) #define NSF_USER_6 (1 << 25) }; void ns_mgr_init(struct ns_mgr *, void *data, ns_callback_t); void ns_mgr_free(struct ns_mgr *); int ns_mgr_poll(struct ns_mgr *, int milli); void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t); struct ns_connection *ns_next(struct ns_mgr *, struct ns_connection *); struct ns_connection *ns_add_sock(struct ns_mgr *, sock_t sock, void *p); struct ns_connection *ns_bind(struct ns_mgr *, const char *addr, void *p); struct ns_connection *ns_connect(struct ns_mgr *, const char *addr, void *p); int ns_send(struct ns_connection *, const void *buf, int len); int ns_printf(struct ns_connection *, const char *fmt, ...); int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap); // Utility functions void *ns_start_thread(void *(*f)(void *), void *p); int ns_socketpair(sock_t [2]); int ns_socketpair2(sock_t [2], int sock_type); // SOCK_STREAM or SOCK_DGRAM void ns_set_close_on_exec(sock_t); void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags); int ns_hexdump(const void *buf, int len, char *dst, int dst_len); int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap); int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); #ifdef __cplusplus } #endif // __cplusplus #endif // NS_SKELETON_HEADER_INCLUDED