1 /* 2 * Copyright (c) 2014 - 2019 Oleh Kulykov <info@resident.name> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23 24 #ifndef __LIBRWS_H__ 25 #define __LIBRWS_H__ 1 26 27 #include <stdio.h> 28 #include <stdbool.h> 29 #ifndef _AMLOGIC_ 30 #include "ulog/ulog.h" 31 #else 32 #include <printf.h> 33 #endif 34 #define RWS_VERSION_MAJOR 1 35 #define RWS_VERSION_MINOR 2 36 #define RWS_VERSION_PATCH 4 37 38 #define WEBSOC_TAG "websoc" 39 #if defined(WEBSOCKET_DEBUG) 40 #define DBG(format, arg...) LOGD(WEBSOC_TAG, format, ##arg) 41 #define WRN(format,arg...) LOGW(WEBSOC_TAG, format, ##arg) 42 #define ERR(format,arg...) LOGE(WEBSOC_TAG, format, ##arg) 43 #else 44 #define DBG(format,arg...) LOGD(WEBSOC_TAG, format, ##arg) 45 #define WRN(format,arg...) LOGW(WEBSOC_TAG, format, ##arg) 46 #define ERR(format,arg...) LOGE(WEBSOC_TAG, format, ##arg) 47 #endif 48 49 // check windows 50 #if defined(WIN32) || defined(_WIN32) || defined(WIN32_LEAN_AND_MEAN) || defined(_WIN64) || defined(WIN64) 51 #define RWS_OS_WINDOWS 1 52 #endif 53 54 55 // extern 56 #if defined(__cplusplus) || defined(_cplusplus) 57 #define RWS_EXTERN extern "C" 58 #else 59 #define RWS_EXTERN extern 60 #endif 61 62 63 // attribute 64 #if defined(__GNUC__) 65 #if (__GNUC__ >= 4) 66 #if defined(__cplusplus) || defined(_cplusplus) 67 #define RWS_ATTRIB __attribute__((visibility("default"))) 68 #else 69 #define RWS_ATTRIB __attribute__((visibility("default"))) 70 #endif 71 #endif 72 #endif 73 74 75 // check attrib and define empty if not defined 76 #if !defined(RWS_ATTRIB) 77 #define RWS_ATTRIB 78 #endif 79 80 81 // dll api 82 #if defined(RWS_OS_WINDOWS) 83 #if defined(RWS_BUILD) 84 #define RWS_DYLIB_API __declspec(dllexport) 85 #else 86 #define RWS_DYLIB_API __declspec(dllimport) 87 #endif 88 #endif 89 90 91 // check dll api and define empty if not defined 92 #if !defined(RWS_DYLIB_API) 93 #define RWS_DYLIB_API 94 #endif 95 96 97 // combined lib api 98 #define RWS_API(return_type) RWS_EXTERN RWS_ATTRIB RWS_DYLIB_API return_type 99 100 101 // types 102 103 /** 104 @brief Boolean type as unsigned byte type. 105 */ 106 typedef unsigned char rws_bool; 107 #define rws_true 1 108 #define rws_false 0 109 110 #define RWS_WAIT_FOREVER 0xffffffffu 111 112 /** 113 @brief Type of all public objects. 114 */ 115 typedef void* rws_handle; 116 117 118 /** 119 @brief Socket handle. 120 */ 121 typedef struct rws_socket_struct * rws_socket; 122 123 124 /** 125 @brief Error object handle. 126 */ 127 typedef struct rws_error_struct * rws_error; 128 129 130 /** 131 @brief Mutex object handle. 132 */ 133 typedef rws_handle rws_mutex; 134 135 /** 136 @brief Mutex object handle. 137 */ 138 typedef rws_handle rws_sem; 139 140 /** 141 @brief Thread object handle. 142 */ 143 typedef struct rws_thread_struct * rws_thread; 144 145 146 /** 147 @brief Callback type of thread function. 148 @param user_object User object provided during thread creation. 149 */ 150 typedef void (*rws_thread_funct)(void * user_object); 151 152 153 /** 154 @brief Callback type of socket object. 155 @param socket Socket object. 156 */ 157 typedef void (*rws_on_socket)(rws_socket socket); 158 159 160 /** 161 @brief Callback type on socket receive text frame. 162 @param socket Socket object. 163 @param text Pointer to reseived text. 164 @param length Received text lenght without null terminated char. 165 */ 166 typedef void (*rws_on_socket_recvd_text)(rws_socket socket, const char * text, const unsigned int length, bool is_finished); 167 168 169 /** 170 @brief Callback type on socket receive binary frame. 171 @param socket Socket object. 172 @param data Received binary data. 173 @param length Received binary data lenght. 174 */ 175 typedef void (*rws_on_socket_recvd_bin)(rws_socket socket, const void * data, const unsigned int length, bool is_finished); 176 177 178 /** 179 @brief Callback type on socket receive pong. 180 @param socket Socket object. 181 */ 182 typedef void (*rws_on_socket_recvd_pong)(rws_socket socket); 183 184 185 /** 186 @brief Callback type on socket send ping. 187 @param socket Socket object. 188 */ 189 typedef void (*rws_on_socket_send_ping)(rws_socket socket); 190 191 // socket 192 193 /** 194 @brief Create new socket. 195 @return Socket handler or NULL on error. 196 */ 197 RWS_API(rws_socket) rws_socket_create(void); 198 199 200 /** 201 @brief Set socket connect URL. 202 @param socket Socket object. 203 @param scheme Connect URL scheme, "http" or "ws" 204 @param scheme Connect URL host, "echo.websocket.org" 205 @param scheme Connect URL port. 206 @param scheme Connect URL path started with '/' character, "/" - for empty, "/path" 207 @code 208 rws_socket_set_url(socket, "http", "echo.websocket.org", 80, "/"); 209 rws_socket_set_url(socket, "ws", "echo.websocket.org", 80, "/"); 210 @endcode 211 */ 212 RWS_API(void) rws_socket_set_url(rws_socket socket, 213 const char * scheme, 214 const char * host, 215 const int port, 216 const char * path); 217 218 /** 219 @brief Set socket connect URL scheme string. 220 @param socket Socket object. 221 @param scheme Connect URL scheme, "http" or "ws" 222 @code 223 rws_socket_set_scheme(socket, "http"); 224 rws_socket_set_scheme(socket, "ws"); 225 @endcode 226 */ 227 RWS_API(void) rws_socket_set_scheme(rws_socket socket, const char * scheme); 228 229 230 /** 231 @brief Get socket connect URL scheme string. 232 @param socket Socket object. 233 @return Connect URL cheme or null. 234 */ 235 RWS_API(const char *) rws_socket_get_scheme(rws_socket socket); 236 237 238 /** 239 @brief Set socket connect URL scheme string. 240 @param socket Socket object. 241 @param scheme Connect URL host, "echo.websocket.org" 242 @code 243 rws_socket_set_host(socket, "echo.websocket.org"); 244 @endcode 245 */ 246 RWS_API(void) rws_socket_set_host(rws_socket socket, const char * host); 247 248 249 /** 250 @brief Get socket connect URL host string. 251 @param socket Socket object. 252 @return Connect URL host or null. 253 */ 254 RWS_API(const char *) rws_socket_get_host(rws_socket socket); 255 256 257 /** 258 @brief Set socket connect URL port. 259 @param socket Socket object. 260 @param scheme Connect URL port. 261 @code 262 rws_socket_set_port(socket, 80); 263 @endcode 264 */ 265 RWS_API(void) rws_socket_set_port(rws_socket socket, const int port); 266 267 268 /** 269 @brief Get socket connect URL port. 270 @param socket Socket object. 271 @return Connect URL port or 0. 272 */ 273 RWS_API(int) rws_socket_get_port(rws_socket socket); 274 275 276 /** 277 @brief Set socket connect URL path string. 278 @param socket Socket object. 279 @param scheme Connect URL path started with '/' character, "/" - for empty, "/path" 280 @code 281 rws_socket_set_path(socket, "/"); // empty path 282 rws_socket_set_path(socket, "/path"); // some path 283 @endcode 284 */ 285 RWS_API(void) rws_socket_set_path(rws_socket socket, const char * path); 286 287 288 /** 289 @brief Get socket connect URL path string. 290 @param socket Socket object. 291 @return Connect URL path or null. 292 */ 293 RWS_API(const char *) rws_socket_get_path(rws_socket socket); 294 295 296 /** 297 @brief Set socket connect Sec-WebSocket-Protocol field. 298 @param socket Socket object. 299 @param Sec-WebSocket-Protocol. 300 @code 301 rws_socket_set_protocol(socket, "echo-protocol") 302 rws_socket_set_protocol(socket, "chat, superchat") 303 @endcode 304 */ 305 RWS_API(void) rws_socket_set_protocol(rws_socket socket, const char * protocol); 306 307 #ifdef WEBSOCKET_SSL_ENABLE 308 /** 309 @brief Set server certificate for ssl connection. 310 @param socket Socket object. 311 @param server_cert Server certificate. 312 @param server_cert_len The length of the server certificate caculated by sizeof 313 */ 314 RWS_API(void) rws_socket_set_server_cert(rws_socket socket, const char *server_cert, int server_cert_len); 315 #endif 316 317 318 /** 319 @brief Get socket last error object handle. 320 @param socket Socket object. 321 @return Last error object handle or null if no error. 322 */ 323 RWS_API(rws_error) rws_socket_get_error(rws_socket socket); 324 325 326 /** 327 @brief Start connection. 328 @detailed This method can generate error object. 329 @param socket Socket object. 330 @return rws_true - all params exists and connection started, otherwice rws_false. 331 */ 332 RWS_API(rws_bool) rws_socket_connect(rws_socket socket); 333 334 335 /** 336 @brief Disconnect socket. 337 @detailed Cleanup prev. send messages and start disconnection sequence. 338 SHOULD forget about this socket handle and don't use it anymore. 339 @warning Don't use this socket object handler after this command. 340 @param socket Socket object. 341 */ 342 RWS_API(void) rws_socket_disconnect_and_release(rws_socket socket); 343 344 345 /** 346 @brief Check is socket has connection to host and handshake(sucessfully done). 347 @detailed Thread safe getter. 348 @param socket Socket object. 349 @return trw_true - connected to host and handshacked, otherwice rws_false. 350 */ 351 RWS_API(rws_bool) rws_socket_is_connected(rws_socket socket); 352 353 354 /** 355 @brief Send text to connect socket. 356 @detailed Thread safe method. 357 @param socket Socket object. 358 @param text Text string for sending. 359 @return rws_true - socket and text exists and placed to send queue, otherwice rws_false. 360 */ 361 RWS_API(rws_bool) rws_socket_send_text(rws_socket socket, const char * text); 362 363 364 /** 365 @brief Set socket user defined object pointer for identificating socket object. 366 @param socket Socket object. 367 @param user_object Void pointer to user object. 368 */ 369 RWS_API(void) rws_socket_set_user_object(rws_socket socket, void * user_object); 370 371 372 /** 373 @brief Get socket user defined object. 374 @param socket Socket object. 375 @return User defined object pointer or null. 376 */ 377 RWS_API(void *) rws_socket_get_user_object(rws_socket socket); 378 379 380 RWS_API(void) rws_socket_set_on_connected(rws_socket socket, rws_on_socket callback); 381 382 383 RWS_API(void) rws_socket_set_on_disconnected(rws_socket socket, rws_on_socket callback); 384 385 386 RWS_API(void) rws_socket_set_on_received_text(rws_socket socket, rws_on_socket_recvd_text callback); 387 388 389 RWS_API(void) rws_socket_set_on_received_bin(rws_socket socket, rws_on_socket_recvd_bin callback); 390 391 /** 392 @brief Get socket user defined object. 393 @param socket Socket object. 394 */ 395 RWS_API(void) rws_socket_set_on_received_pong(rws_socket socket, rws_on_socket_recvd_pong callback); 396 397 398 /** 399 @brief Get socket user defined object. 400 @param socket Socket object. 401 */ 402 RWS_API(void) rws_socket_set_on_send_ping(rws_socket socket, rws_on_socket_send_ping callback); 403 404 405 /** 406 @brief Send bin header to connect socket. 407 @detailed Thread safe method. 408 @param socket Socket object. 409 @param bin header string for sending. 410 @param len length of header, 8 bytes. 411 @return rws_true - socket and bin header exists and placed to send queue, otherwice rws_false 412 */ 413 RWS_API(rws_bool) rws_socket_send_bin_start(rws_socket socket, const char *bin, size_t len); 414 415 /** 416 @brief Send bin content to connect socket. 417 @detailed Thread safe method. 418 @param socket Socket object. 419 @param binary content for sending. 420 @param len length of binary content. 421 @return rws_true - socket and bin content exists and placed to send queue, otherwice rws_false. 422 */ 423 RWS_API(rws_bool) rws_socket_send_bin_continue(rws_socket socket, const char *bin, size_t len); 424 425 426 /** 427 @brief Send final bin to connect socket. 428 @detailed Thread safe method. 429 @param socket Socket object. 430 @param final bin string for sending. 431 @param len length of final, 6 bytes. 432 @return rws_true - socket and final bin exists and placed to send queue, otherwice rws_false 433 */ 434 RWS_API(rws_bool) rws_socket_send_bin_finish(rws_socket socket, const char * bin, size_t len); 435 436 437 /** 438 @brief Send ping async to connect socket. 439 @detailed Thread safe method. 440 @param socket Socket object. 441 @return rws_true - send ping success, otherwice rws_false 442 */ 443 RWS_API(rws_bool) rws_socket_send_ping(rws_socket socket); 444 445 // error 446 typedef enum _rws_error_code { 447 rws_error_code_none = 0, 448 449 rws_error_code_missed_parameter, 450 451 rws_error_code_send_handshake, 452 rws_error_code_parse_handshake, 453 rws_error_code_read_write_socket, 454 rws_error_code_connect_to_host, 455 456 /** 457 @brief Connection was closed by endpoint. 458 Reasons: an endpoint shutting down, an endpoint having received a frame too large, or an 459 endpoint having received a frame that does not conform to the format expected by the endpoint. 460 */ 461 rws_error_code_connection_closed, 462 463 464 } rws_error_code; 465 466 467 /** 468 @return 0 - if error is empty or no error, otherwice error code. 469 */ 470 RWS_API(int) rws_error_get_code(rws_error error); 471 472 473 /** 474 @return 0 - if error is empty or no error, otherwice HTTP error. 475 */ 476 RWS_API(int) rws_error_get_http_error(rws_error error); 477 478 479 /** 480 @brief Get description of the error object. 481 */ 482 RWS_API(const char *) rws_error_get_description(rws_error error); 483 484 485 // mutex 486 487 /** 488 @brief Creates recursive mutex object. 489 */ 490 RWS_API(rws_mutex) rws_mutex_create_recursive(void); 491 492 493 /** 494 @brief Lock mutex object. 495 */ 496 RWS_API(void) rws_mutex_lock(rws_mutex mutex); 497 498 499 /** 500 @brief Unlock mutex object. 501 */ 502 RWS_API(void) rws_mutex_unlock(rws_mutex mutex); 503 504 505 506 /** 507 @brief Unlock mutex object. 508 */ 509 RWS_API(void) rws_mutex_delete(rws_mutex mutex); 510 511 // semphore 512 513 /** 514 @brief Creates semhpore object. 515 */ 516 RWS_API(rws_sem) rws_sem_create(void); 517 518 519 /** 520 @brief Release a semhpore 521 */ 522 RWS_API(void) rws_sem_signal(rws_sem sem); 523 524 525 /** 526 @brief Wait for a semhpore 527 */ 528 RWS_API(int) rws_sem_wait(rws_sem sem, unsigned int timeout); 529 530 531 /** 532 @brief Free semhpore object. 533 */ 534 RWS_API(void) rws_sem_delete(rws_sem sem); 535 536 537 // thread 538 539 /** 540 @brief Create thread object that start immidiatelly. 541 */ 542 RWS_API(rws_thread) rws_thread_create(rws_thread_funct thread_function, void * user_object); 543 544 545 /** 546 @brief Pause current thread for a number of milliseconds. 547 */ 548 RWS_API(void) rws_thread_sleep(const unsigned int millisec); 549 550 #endif 551