1 // Copyright (c) 2014 Cesanta Software Limited 2 // All rights reserved 3 // 4 // This software is dual-licensed: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License version 2 as 6 // published by the Free Software Foundation. For the terms of this 7 // license, see <http://www.gnu.org/licenses/>. 8 // 9 // You are free to use this software under the terms of the GNU General 10 // Public License, but WITHOUT ANY WARRANTY; without even the implied 11 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 // See the GNU General Public License for more details. 13 // 14 // Alternatively, you can license this software under a commercial 15 // license, as set out in <http://cesanta.com/>. 16 // 17 // $Date: 2014-09-28 05:04:41 UTC $ 18 19 #ifndef NS_SKELETON_HEADER_INCLUDED 20 #define NS_SKELETON_HEADER_INCLUDED 21 22 #define NS_SKELETON_VERSION "2.1.0" 23 24 #undef UNICODE // Use ANSI WinAPI functions 25 #undef _UNICODE // Use multibyte encoding on Windows 26 #define _MBCS // Use multibyte encoding on Windows 27 #define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows 28 #define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+ 29 #undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h 30 #define _XOPEN_SOURCE 600 // For flockfile() on Linux 31 #define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++ 32 #define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX 33 #ifndef _LARGEFILE_SOURCE 34 #define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions 35 #endif 36 #define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets 37 38 #ifdef _MSC_VER 39 #pragma warning (disable : 4127) // FD_SET() emits warning, disable it 40 #pragma warning (disable : 4204) // missing c99 support 41 #endif 42 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <assert.h> 46 #include <ctype.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <stdarg.h> 50 #include <stddef.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <time.h> 55 #include <signal.h> 56 57 #ifdef _WIN32 58 #ifdef _MSC_VER 59 #pragma comment(lib, "ws2_32.lib") // Linking with winsock library 60 #endif 61 #include <windows.h> 62 #include <process.h> 63 #ifndef EINPROGRESS 64 #define EINPROGRESS WSAEINPROGRESS 65 #endif 66 #ifndef EWOULDBLOCK 67 #define EWOULDBLOCK WSAEWOULDBLOCK 68 #endif 69 #ifndef __func__ 70 #define STRX(x) #x 71 #define STR(x) STRX(x) 72 #define __func__ __FILE__ ":" STR(__LINE__) 73 #endif 74 #ifndef va_copy 75 #define va_copy(x,y) x = y 76 #endif // MINGW #defines va_copy 77 #define snprintf _snprintf 78 #define vsnprintf _vsnprintf 79 #define sleep(x) Sleep((x) * 1000) 80 #define to64(x) _atoi64(x) 81 typedef int socklen_t; 82 typedef unsigned char uint8_t; 83 typedef unsigned int uint32_t; 84 typedef unsigned short uint16_t; 85 typedef unsigned __int64 uint64_t; 86 typedef __int64 int64_t; 87 typedef SOCKET sock_t; 88 typedef struct _stati64 ns_stat_t; 89 #ifndef S_ISDIR 90 #define S_ISDIR(x) ((x) & _S_IFDIR) 91 #endif 92 #else 93 #include <errno.h> 94 #include <fcntl.h> 95 #include <netdb.h> 96 #include <pthread.h> 97 #include <stdarg.h> 98 #include <unistd.h> 99 #include <arpa/inet.h> // For inet_pton() when NS_ENABLE_IPV6 is defined 100 #include <netinet/in.h> 101 #include <sys/socket.h> 102 #include <sys/select.h> 103 #define closesocket(x) close(x) 104 #define __cdecl 105 #define INVALID_SOCKET (-1) 106 #define to64(x) strtoll(x, NULL, 10) 107 typedef int sock_t; 108 typedef struct stat ns_stat_t; 109 #endif 110 111 #ifdef NS_ENABLE_DEBUG 112 #define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ 113 fflush(stdout); } while(0) 114 #else 115 #define DBG(x) 116 #endif 117 118 #ifndef ARRAY_SIZE 119 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 120 #endif 121 122 #ifdef NS_ENABLE_SSL 123 #ifdef __APPLE__ 124 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 125 #endif 126 #include <openssl/ssl.h> 127 #else 128 typedef void *SSL; 129 typedef void *SSL_CTX; 130 #endif 131 132 #ifdef __cplusplus 133 extern "C" { 134 #endif // __cplusplus 135 136 union socket_address { 137 struct sockaddr sa; 138 struct sockaddr_in sin; 139 #ifdef NS_ENABLE_IPV6 140 struct sockaddr_in6 sin6; 141 #else 142 struct sockaddr sin6; 143 #endif 144 }; 145 146 // Describes chunk of memory 147 struct ns_str { 148 const char *p; 149 size_t len; 150 }; 151 152 // IO buffers interface 153 struct iobuf { 154 char *buf; 155 size_t len; 156 size_t size; 157 }; 158 159 void iobuf_init(struct iobuf *, size_t initial_size); 160 void iobuf_free(struct iobuf *); 161 size_t iobuf_append(struct iobuf *, const void *data, size_t data_size); 162 void iobuf_remove(struct iobuf *, size_t data_size); 163 void iobuf_resize(struct iobuf *, size_t new_size); 164 165 // Callback function (event handler) prototype, must be defined by user. 166 // Net skeleton will call event handler, passing events defined above. 167 struct ns_connection; 168 typedef void (*ns_callback_t)(struct ns_connection *, int event_num, void *evp); 169 170 // Events. Meaning of event parameter (evp) is given in the comment. 171 #define NS_POLL 0 // Sent to each connection on each call to ns_mgr_poll() 172 #define NS_ACCEPT 1 // New connection accept()-ed. union socket_address *addr 173 #define NS_CONNECT 2 // connect() succeeded or failed. int *success_status 174 #define NS_RECV 3 // Data has benn received. int *num_bytes 175 #define NS_SEND 4 // Data has been written to a socket. int *num_bytes 176 #define NS_CLOSE 5 // Connection is closed. NULL 177 178 179 struct ns_mgr { 180 struct ns_connection *active_connections; 181 const char *hexdump_file; // Debug hexdump file path 182 sock_t ctl[2]; // Socketpair for mg_wakeup() 183 void *user_data; // User data 184 }; 185 186 187 struct ns_connection { 188 struct ns_connection *next, *prev; // ns_mgr::active_connections linkage 189 struct ns_connection *listener; // Set only for accept()-ed connections 190 struct ns_mgr *mgr; 191 192 sock_t sock; // Socket 193 union socket_address sa; // Peer address 194 struct iobuf recv_iobuf; // Received data 195 struct iobuf send_iobuf; // Data scheduled for sending 196 SSL *ssl; 197 SSL_CTX *ssl_ctx; 198 void *user_data; // User-specific data 199 void *proto_data; // Application protocol-specific data 200 time_t last_io_time; // Timestamp of the last socket IO 201 ns_callback_t callback; // Event handler function 202 203 unsigned int flags; 204 #define NSF_FINISHED_SENDING_DATA (1 << 0) 205 #define NSF_BUFFER_BUT_DONT_SEND (1 << 1) 206 #define NSF_SSL_HANDSHAKE_DONE (1 << 2) 207 #define NSF_CONNECTING (1 << 3) 208 #define NSF_CLOSE_IMMEDIATELY (1 << 4) 209 #define NSF_WANT_READ (1 << 5) 210 #define NSF_WANT_WRITE (1 << 6) 211 #define NSF_LISTENING (1 << 7) 212 #define NSF_UDP (1 << 8) 213 214 #define NSF_USER_1 (1 << 20) 215 #define NSF_USER_2 (1 << 21) 216 #define NSF_USER_3 (1 << 22) 217 #define NSF_USER_4 (1 << 23) 218 #define NSF_USER_5 (1 << 24) 219 #define NSF_USER_6 (1 << 25) 220 }; 221 222 void ns_mgr_init(struct ns_mgr *, void *user_data); 223 void ns_mgr_free(struct ns_mgr *); 224 time_t ns_mgr_poll(struct ns_mgr *, int milli); 225 void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t); 226 227 struct ns_connection *ns_next(struct ns_mgr *, struct ns_connection *); 228 struct ns_connection *ns_add_sock(struct ns_mgr *, sock_t, 229 ns_callback_t, void *); 230 struct ns_connection *ns_bind(struct ns_mgr *, const char *, 231 ns_callback_t, void *); 232 struct ns_connection *ns_connect(struct ns_mgr *, const char *, 233 ns_callback_t, void *); 234 235 int ns_send(struct ns_connection *, const void *buf, int len); 236 int ns_printf(struct ns_connection *, const char *fmt, ...); 237 int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap); 238 239 // Utility functions 240 void *ns_start_thread(void *(*f)(void *), void *p); 241 int ns_socketpair(sock_t [2]); 242 int ns_socketpair2(sock_t [2], int sock_type); // SOCK_STREAM or SOCK_DGRAM 243 void ns_set_close_on_exec(sock_t); 244 void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags); 245 int ns_hexdump(const void *buf, int len, char *dst, int dst_len); 246 int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap); 247 int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len); 248 249 #ifdef __cplusplus 250 } 251 #endif // __cplusplus 252 253 #endif // NS_SKELETON_HEADER_INCLUDED 254