From b489c37e9e7d96495fab7527aff02c6b1886393f Mon Sep 17 00:00:00 2001 From: Evgeniy Date: Mon, 21 Jan 2019 23:33:04 +0300 Subject: [PATCH] Merge branch 'feature/websocket' of https://github.com/xrdavies/xdag-1 into xrdavies-feature/websocket # Conflicts: # mac/xdag.xcodeproj/project.pbxproj --- automake/Makefile.am | 26 +- client/Makefile | 25 +- client/block.c | 67 ++ client/init.c | 4 + client/utils/base64.c | 122 +++ client/utils/base64.h | 31 + client/utils/uuid.c | 100 +++ client/utils/uuid.h | 24 + client/websocket/websocket.c | 696 +++++++++++++++++ client/websocket/websocket.h | 29 + client/websocket/wslay/config.h | 145 ++++ client/websocket/wslay/wslay.h | 772 +++++++++++++++++++ client/websocket/wslay/wslay_event.c | 1027 ++++++++++++++++++++++++++ client/websocket/wslay/wslay_event.h | 142 ++++ client/websocket/wslay/wslay_frame.c | 340 +++++++++ client/websocket/wslay/wslay_frame.h | 76 ++ client/websocket/wslay/wslay_net.c | 36 + client/websocket/wslay/wslay_net.h | 54 ++ client/websocket/wslay/wslay_queue.c | 117 +++ client/websocket/wslay/wslay_queue.h | 53 ++ client/websocket/wslay/wslay_stack.c | 86 +++ client/websocket/wslay/wslay_stack.h | 50 ++ client/websocket/wslay/wslayver.h | 31 + mac/xdag.xcodeproj/project.pbxproj | 862 +++++++++++---------- 24 files changed, 4510 insertions(+), 405 deletions(-) create mode 100644 client/utils/base64.c create mode 100644 client/utils/base64.h create mode 100644 client/utils/uuid.c create mode 100644 client/utils/uuid.h create mode 100644 client/websocket/websocket.c create mode 100644 client/websocket/websocket.h create mode 100644 client/websocket/wslay/config.h create mode 100755 client/websocket/wslay/wslay.h create mode 100755 client/websocket/wslay/wslay_event.c create mode 100755 client/websocket/wslay/wslay_event.h create mode 100755 client/websocket/wslay/wslay_frame.c create mode 100755 client/websocket/wslay/wslay_frame.h create mode 100755 client/websocket/wslay/wslay_net.c create mode 100755 client/websocket/wslay/wslay_net.h create mode 100755 client/websocket/wslay/wslay_queue.c create mode 100755 client/websocket/wslay/wslay_queue.h create mode 100755 client/websocket/wslay/wslay_stack.c create mode 100755 client/websocket/wslay/wslay_stack.h create mode 100644 client/websocket/wslay/wslayver.h diff --git a/automake/Makefile.am b/automake/Makefile.am index 4ab9403d..b5723d16 100644 --- a/automake/Makefile.am +++ b/automake/Makefile.am @@ -13,7 +13,7 @@ http = $(SRCROOT)/client/http moving_statistics = $(SRCROOT)/client/utils/moving_statistics algorithms = $(SRCROOT)/client/algorithms secp256k1 = $(SRCROOT)/secp256k1 - +websocket = $(SRCROOT)/client/websocket sources = \ $(algorithms)/sha256-mb-x86_64$(HOST_SUFFIX).s \ @@ -60,8 +60,13 @@ sources = \ $(jsonrpc)/rpc_commands.c \ $(http)/url.c \ $(http)/http.c \ - $(secp256k1)/src/secp256k1.c - + $(secp256k1)/src/secp256k1.c \ + $(websocket)/websocket.c \ + $(websocket)/wslay/wslay_event.c \ + $(websocket)/wslay/wslay_frame.c \ + $(websocket)/wslay/wslay_net.c \ + $(websocket)/wslay/wslay_queue.c \ + $(websocket)/wslay/wslay_stack.c \ headers = \ $(client)/address.h \ @@ -110,7 +115,16 @@ headers = \ $(jsonrpc)/rpc_wrapper.h \ $(jsonrpc)/rpc_commands.h \ $(http)/url.h \ - $(http)/http.h + $(http)/http.h \ + $(websocket)/websocket.h \ + $(websocket)/wslay/config.h \ + $(websocket)/wslay/wslay.h \ + $(websocket)/wslay/wslayver.h \ + $(websocket)/wslay/wslay_event.h \ + $(websocket)/wslay/wslay_frame.h \ + $(websocket)/wslay/wslay_net.h \ + $(websocket)/wslay/wslay_queue.h \ + $(websocket)/wslay/wslay_stack.h #program bin_PROGRAMS = xdag @@ -133,7 +147,9 @@ _INCLUDES = \ -I$(jsonrpc) \ -I$(http) \ -I$(secp256k1)/src \ - -I$(secp256k1)/ + -I$(secp256k1)/ \ + -I$(websocket)/wslay \ + -I$(websocket)/ \ xdag_SOURCES = $(sources) diff --git a/client/Makefile b/client/Makefile index 9926c361..aeb72971 100644 --- a/client/Makefile +++ b/client/Makefile @@ -9,6 +9,8 @@ moving_statistics = ./utils/moving_statistics algorithms = ./algorithms json-rpc = ./json-rpc secp256k1 = ../secp256k1 +http = ./http +websocket = ./websocket OS := $(shell uname) use_openssl_ec := $(shell if grep --quiet -e 'define USE_OPTIMIZED_EC 1' -e 'define USE_OPTIMIZED_EC 2' crypt.h; then echo false; else echo true; fi) lgmp_installed := $(shell if cc -lgmp 2>&1 | grep --quiet main; then echo true; else echo false; fi) @@ -68,8 +70,14 @@ sources = \ $(json-rpc)/rpc_service.c \ $(json-rpc)/rpc_wrapper.c \ $(json-rpc)/rpc_commands.c \ - ./http/url.c \ - ./http/http.c \ + $(websocket)/websocket.c \ + $(websocket)/wslay/wslay_event.c \ + $(websocket)/wslay/wslay_frame.c \ + $(websocket)/wslay/wslay_net.c \ + $(websocket)/wslay/wslay_queue.c \ + $(websocket)/wslay/wslay_stack.c \ + $(http)/url.c \ + $(http)/http.c headers = \ @@ -125,8 +133,17 @@ headers = \ $(json-rpc)/rpc_service.h \ $(json-rpc)/rpc_wrapper.h \ $(json-rpc)/rpc_commands.h \ - ./http/url.h \ - ./http/http.h \ + $(websocket)/websocket.h \ + $(websocket)/wslay/config.h \ + $(websocket)/wslay/wslay.h \ + $(websocket)/wslay/wslayver.h \ + $(websocket)/wslay/wslay_event.h \ + $(websocket)/wslay/wslay_frame.h \ + $(websocket)/wslay/wslay_net.h \ + $(websocket)/wslay/wslay_queue.h \ + $(websocket)/wslay/wslay_stack.h \ + $(http)/url.h \ + $(http)/http.h \ diff --git a/client/block.c b/client/block.c index 50d4bcb6..6082976e 100644 --- a/client/block.c +++ b/client/block.c @@ -29,6 +29,7 @@ #include "math.h" #include "utils/atomic.h" #include "utils/random.h" +#include "websocket/websocket.h" #define MAX_WAITING_MAIN 1 #define MAIN_START_AMOUNT (1ll << 42) @@ -120,6 +121,7 @@ static uint32_t cache_bounded_counter = 0; static struct orphan_block *g_orphan_first[ORPHAN_HASH_SIZE], *g_orphan_last[ORPHAN_HASH_SIZE]; //functions +void append_block_info(struct block_internal *bi); void cache_retarget(int32_t, int32_t); void cache_add(struct xdag_block*, xdag_hash_t); int32_t check_signature_out_cached(struct block_internal*, struct xdag_public_key*, const int, int32_t*, int32_t*); @@ -247,6 +249,7 @@ static uint64_t apply_block(struct block_internal *bi) accept_amount(bi, sum_in - sum_out); bi->flags |= BI_APPLIED; + append_block_info(bi); //TODO: figure out how to detect when the block is rejected. return bi->fee; } @@ -1540,6 +1543,70 @@ const char* xdag_get_block_state_info(uint8_t flags) return "Pending"; } +void append_block_info(struct block_internal *bi) +{ + // if websocket service is not running return directly + if(!g_websocket_running) { + return; + } + + int flags, nlinks; + struct block_internal *ref, *link[MAX_LINKS]; + pthread_mutex_lock(&block_mutex); + ref = bi->ref; + flags = bi->flags; + nlinks = bi->nlinks; + memcpy(link, bi->link, nlinks * sizeof(struct block_internal*)); + pthread_mutex_unlock(&block_mutex); + + char time_buf[64] = {0}; + char address[33] = {0}; + uint64_t *h = bi->hash; + xdag_hash2address(h, address); + xdag_xtime_to_string(bi->time, time_buf); + + char message[4096] = {0}; + char buf[128] = {0}; + + sprintf(message, + "{\"time\":\"%s\"" + ",\"flags\":\"%x\"" + ",\"state\":\"%s\"" + ",\"hash\":\"%016llx%016llx%016llx%016llx\"" + ",\"difficulty\":\"%llx%016llx\"" + ",\"remark\":\"%s\"" + ",\"address\":\"%s\"" + ",\"balance\":\"%u.%09u\"" + ",\"fields\":[" + , time_buf + , flags & ~BI_OURS + , xdag_get_block_state_info(flags) + , (unsigned long long)h[3], (unsigned long long)h[2], (unsigned long long)h[1], (unsigned long long)h[0] + , xdag_diff_args(bi->difficulty) + , get_remark(bi) + , address + , pramount(bi->amount) + ); + + if((flags & BI_REF) && ref != NULL) { + xdag_hash2address(ref->hash, address); + } else { + strcpy(address, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + } + sprintf(buf, "{\"direction\":\"fee\",\"address\":\"%s\",\"amount\":\"%u.%09u\"}", address, pramount(bi->fee)); + strcat(message, buf); + + for (int i = 0; i < nlinks; ++i) { + xdag_hash2address(link[i]->hash, address); + sprintf(buf, ",{\"direction\":\"%s\",\"address\":\"%s\",\"amount\":\"%u.%09u\"}", (1 << i & bi->in_mask ? " input" : "output"),address, pramount(bi->linkamount[i])); + strcat(message, buf); + } + + strcat(message, "]}"); + + xdag_ws_message_append(message); +} + /* prints detailed information about block */ int xdag_print_block_info(xdag_hash_t hash, FILE *out) { diff --git a/client/init.c b/client/init.c index 4ccd23a8..c63d6267 100644 --- a/client/init.c +++ b/client/init.c @@ -32,6 +32,7 @@ #include "json-rpc/rpc_service.h" #include "../dnet/dnet_crypt.h" #include "utils/random.h" +#include "websocket/websocket.h" #define ARG_EQUAL(a,b,c) strcmp(c, "") == 0 ? strcmp(a, b) == 0 : (strcmp(a, b) == 0 || strcmp(a, c) == 0) @@ -338,6 +339,9 @@ int setup_pool(struct startup_parameters *parameters) if(parameters->is_rpc) { xdag_mess("Initializing RPC service..."); if(!!xdag_rpc_service_start(parameters->rpc_port)) return -1; + + xdag_mess("Initializing WebSocket service..."); + if(!!xdag_ws_server_start(-1, -1)) return -1; } xdag_mess("Starting blocks engine..."); if(xdag_blocks_start(parameters->mining_threads_count, !!parameters->miner_address)) return -1; diff --git a/client/utils/base64.c b/client/utils/base64.c new file mode 100644 index 00000000..14a8b680 --- /dev/null +++ b/client/utils/base64.c @@ -0,0 +1,122 @@ +// +// base64.c +// xdag +// +// Created by Rui Xie on 11/16/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#include "base64.h" +#include +#include + +static const uint8_t bits2mime[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const uint8_t mime2bits[256] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0xff,0x3f, + 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +int encode(const uint8_t *in, size_t inlen, char *out); +int decode(const char *in, size_t inlen, uint8_t *out, size_t *outlen); + +int encode(const uint8_t *in, size_t inlen, char *out) +{ + while(inlen) { + *out++ = bits2mime[in[0] >> 2]; + *out++ = bits2mime[(in[0] << 4 & 0x3f) | (--inlen ? in[1] >> 4 : 0)]; + if (!inlen) { + *out++ = '='; + *out++ = '='; + break; + } + *out++ = bits2mime[(in[1] << 2 & 0x3f) | (--inlen ? in[2] >> 6 : 0)]; + if(!inlen) { + *out++ = '='; + break; + } + *out++ = bits2mime[in[2] & 0x3f]; + --inlen; + + in += 3; + } + *out = '\0'; + + return 0; +} + +int decode(const char *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + while(inlen) { + if(mime2bits[in[0]] == 0xFF || mime2bits[in[1]] == 0xFF) { + return -1; + } + *out++ = mime2bits[in[0]] << 2 | mime2bits[in[1]] >> 4; + (*outlen)++; + if(in[2] == '=') { + break; + } + *out++ = mime2bits[in[1]] << 4 | mime2bits[in[2]] >> 2; + (*outlen)++; + + if(in[3] == '=') { + break; + } + *out++ = mime2bits[in[2]] << 6 | mime2bits[in[3]]; + (*outlen)++; + in += 4; + inlen -= 4; + } + + return 0; +} + +int base64_encode(const uint8_t *in, size_t inlen, char **out, size_t *outlen) +{ + *outlen = BASE64_LENGTH(inlen) + 1; /* extra byte for '\0' */ + *out = (char *)malloc(*outlen); + memset((void*)(*out), 0, *outlen); + int ret = encode(in, inlen, *out); + if(ret != 0) { + free(*out); + *out = NULL; + return ret; + } + return ret; +} + +int base64_decode(const char *in, size_t inlen, uint8_t **out, size_t *outlen) +{ + if(inlen % 4) { // wrong inlen + *outlen = 0; + return -1; + } + + /* This may allocate a few bytes too much, depending on input, + but it's not worth the extra CPU time to compute the exact amount. + The exact amount is 3 * inlen / 4, minus 1 if the input ends + with "=" and minus another 1 if the input ends with "==". + Dividing before multiplying avoids the possibility of overflow. */ + + *out = malloc(3 * (inlen / 4) + 2); + memset(*out, 0, 3 * (inlen / 4) + 2); + int ret = decode(in, inlen, *out, outlen); + if(ret != 0) { + free(*out); + *out = NULL; + } + return ret; +} diff --git a/client/utils/base64.h b/client/utils/base64.h new file mode 100644 index 00000000..2950ac5a --- /dev/null +++ b/client/utils/base64.h @@ -0,0 +1,31 @@ +// +// base64.h +// xdag +// +// Created by Rui Xie on 11/16/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#ifndef base64_h +#define base64_h + +#include +#include + +/* This uses that the expression (n+(k-1))/k means the smallest + integer >= n/k, i.e., the ceiling of n/k. */ +#define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) + +#ifdef __cplusplus +extern "C" { +#endif + /* encode data to base64 string, out should be freed manually */ + extern int base64_encode(const uint8_t *in, size_t inlen, char **out, size_t *outlen); + + /* decode base64 string to uint8_t array, out should be freed manually */ + extern int base64_decode(const char *in, size_t inlen, uint8_t **out, size_t *outlen); +#ifdef __cplusplus +}; +#endif + +#endif /* base64_h */ diff --git a/client/utils/uuid.c b/client/utils/uuid.c new file mode 100644 index 00000000..6f85289e --- /dev/null +++ b/client/utils/uuid.c @@ -0,0 +1,100 @@ +// +// uuid.c +// xdag +// +// Created by Rui Xie on 12/26/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#include "uuid.h" +#include +#include + +#if defined(_WIN32) +#include +#include +#endif + + +static const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"; +static const char *chars = "0123456789abcdef"; + +/* http://xorshift.di.unimi.it/xorshift128plus.c */ +static uint64_t xorshift128plus(uint64_t *s) { + uint64_t s1 = s[0]; + uint64_t s0 = s[1]; + s[0] = s0; + s1 ^= s1 << 23; + s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); + return s[1] + s0; +} + +int uuid(char *buf) +{ + uint64_t seed[2]; + +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) + size_t res; + FILE *fp = fopen("/dev/urandom", "rb"); + if (!fp) { + printf("uuid failed."); + return -1; + } + res = fread(seed, 1, sizeof(seed), fp); + fclose(fp); + if ( res != sizeof(seed) ) { + printf("uuid failed."); + return -1; + } + +#elif defined(_WIN32) + int res; + HCRYPTPROV hCryptProv; + res = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + if (!res) { + printf("uuid failed."); + return -1; + } + res = CryptGenRandom(hCryptProv, (DWORD) sizeof(seed), (PBYTE) seed); + CryptReleaseContext(hCryptProv, 0); + if (!res) { + printf("uuid failed."); + return -1; + } +#endif + + union { unsigned char b[16]; uint64_t word[2]; } s; + const char *p = template; + int i, n; + + s.word[0] = xorshift128plus(seed); + s.word[1] = xorshift128plus(seed); + + i = 0; + while (*p) { + n = s.b[i >> 1]; + n = (i & 1) ? (n >> 4) : (n & 0xf); + switch (*p) { + case 'x': { + *buf = chars[n]; + i++; + break; + } + + case 'y': { + *buf = chars[(n & 0x3) + 8]; + i++; + break; + } + default: { + *buf = *p; + break; + } + } + buf++; + p++; + } + *buf = '\0'; + + return 0; +} diff --git a/client/utils/uuid.h b/client/utils/uuid.h new file mode 100644 index 00000000..a1199192 --- /dev/null +++ b/client/utils/uuid.h @@ -0,0 +1,24 @@ +// +// uuid.h +// xdag +// +// Created by Rui Xie on 12/26/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#ifndef uuid_h +#define uuid_h + +#include + +#define UUID4_LEN 37 + +#ifdef __cplusplus +extern "C" { +#endif + extern int uuid(char *buf); +#ifdef __cplusplus +}; +#endif + +#endif /* uuid_h */ diff --git a/client/websocket/websocket.c b/client/websocket/websocket.c new file mode 100644 index 00000000..d71f8a7c --- /dev/null +++ b/client/websocket/websocket.c @@ -0,0 +1,696 @@ +// +// websocket.c +// xdag +// +// Created by Rui Xie on 11/14/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#include "websocket.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#define poll WSAPoll +#else +#include +#endif + +#include "wslay/wslay.h" +#include +#include "../utils/log.h" +#include "../utils/base64.h" +#include "../uthash/utlist.h" + +#define WS_LOG_FILE "websocket.log" + +#define ws_fatal(...) xdag_log(WS_LOG_FILE, XDAG_FATAL , __VA_ARGS__) +#define ws_crit(...) xdag_log(WS_LOG_FILE, XDAG_CRITICAL, __VA_ARGS__) +#define ws_err(...) xdag_log(WS_LOG_FILE, XDAG_ERROR , __VA_ARGS__) +#define ws_warn(...) xdag_log(WS_LOG_FILE, XDAG_WARNING , __VA_ARGS__) +#define ws_mess(...) xdag_log(WS_LOG_FILE, XDAG_MESSAGE , __VA_ARGS__) +#define ws_info(...) xdag_log(WS_LOG_FILE, XDAG_INFO , __VA_ARGS__) +#ifndef NDEBUG +#define ws_debug(...) xdag_log(WS_LOG_FILE, XDAG_DEBUG , __VA_ARGS__) +#else +#define ws_debug(...) +#endif + +#define WS_DEFAULT_PORT 9999 +#define WS_DEFAULT_MAX_LIMIT 100 + +static pthread_mutex_t g_mutex_sessions = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_mutex_messages = PTHREAD_MUTEX_INITIALIZER; +int g_websocket_running = 0; +int g_websocket_port = WS_DEFAULT_PORT; +int g_websocket_maxlimit = WS_DEFAULT_MAX_LIMIT; + +typedef struct { + int fd; + struct in_addr addr; + in_port_t port; + struct pollfd pfd; + wslay_event_context_ptr ctx; +} ws_session; + +typedef struct ws_session_list_element_t { + ws_session *session; + struct ws_session_list_element_t *next; +} ws_session_list_element; +static ws_session_list_element *g_session_list = NULL; + +typedef struct ws_message_list_element_t { + char *message; + struct ws_message_list_element_t *next; +} ws_message_list_element; +static ws_message_list_element *g_message_list = NULL; + +// functions +void ws_cleanup(void); +void cleanup_threads(void *args); +int ws_session_init(ws_session *session); +int ws_session_communicate(ws_session *session); +void *ws_handler_thread(void *args); +void *ws_server_thread(void *args); + +void xdag_ws_message_append(char *message) +{ + if (!g_websocket_running) { + return; + } + ws_message_list_element *msg = malloc(sizeof(ws_message_list_element)); + memset(msg, 0, sizeof(ws_message_list_element)); + msg->message = strdup(message); + pthread_mutex_lock(&g_mutex_messages); + LL_APPEND(g_message_list, msg); + pthread_mutex_unlock(&g_mutex_messages); +} + +static ws_message_list_element* ws_first_message(void) +{ + ws_message_list_element *first = NULL; + first = g_message_list; + pthread_mutex_lock(&g_mutex_messages); + if (first) { + LL_DELETE(g_message_list, first); + } + pthread_mutex_unlock(&g_mutex_messages); + return first; +} + +static void ws_session_close(ws_session *session) +{ + ws_info("session from %s:%d closed\n", inet_ntoa(session->addr), ntohs(session->port)); + shutdown(session->fd, SHUT_RDWR); + close(session->fd); + free(session); +} + +static void ws_session_append(ws_session *session) +{ + assert(session); + + ws_session_list_element *elem = NULL; + int count = 0; + + pthread_mutex_lock(&g_mutex_sessions); + LL_COUNT(g_session_list, elem, count); + pthread_mutex_unlock(&g_mutex_sessions); + + if (count >= g_websocket_maxlimit) { + ws_session_close(session); + } else { + elem = calloc(1, sizeof(ws_session_list_element)); + if (elem == NULL) { + ws_err("[ws_session_append] alloca failed!"); + ws_session_close(session); + } else { + elem->session = session; + ws_session_init(session); // init wslay websocket + pthread_mutex_lock(&g_mutex_sessions); + LL_APPEND(g_session_list, elem); + pthread_mutex_unlock(&g_mutex_sessions); + ws_info("%s connected\n", inet_ntoa(session->addr)); + } + } +} + +static void sha1(uint8_t *dst, const uint8_t *src, size_t src_length) +{ + SHA_CTX ctx; + SHA1_Init(&ctx); + SHA1_Update(&ctx, src, src_length); + SHA1_Final(dst, &ctx); +} + +static void base64(uint8_t *dst, const uint8_t *src, size_t src_length) +{ + size_t outlen = 0;; + char *outbuf = NULL; + base64_encode(src, src_length, &outbuf, &outlen); + memcpy(dst, outbuf, outlen); + free(outbuf); +} + +static int make_non_block(int fd) +{ + int flags, r; + while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); + if(flags == -1) { + ws_err("fcntl set F_GETFL 0 failed!"); + return -1; + } + while((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); + if(r == -1) { + ws_err("fcntl set F_SETFL O_NONBLOCK failed!"); + return -1; + } + return 0; +} + +#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" // UID from RFC6455 + +static void create_accept_key(char *dst, const char *client_key) +{ + uint8_t sha1buf[20], key_src[60]; + memcpy(key_src, client_key, 24); + memcpy(key_src+24, WS_GUID, 36); + sha1(sha1buf, key_src, sizeof(key_src)); + base64((uint8_t*)dst, sha1buf, 20); + dst[BASE64_LENGTH(20)] = '\0'; +} + +static char* http_header_find_field_value(char *header, char *field_name, char *value) +{ + char *header_end, + *field_start, + *field_end, + *next_crlf, + *value_start; + size_t field_name_len; + + /* Pointer to the last character in the header */ + header_end = header + strlen(header) - 1; + field_name_len = strlen(field_name); + field_start = header; + + do{ + field_start = strstr(field_start+1, field_name); + field_end = field_start + field_name_len - 1; + + if(field_start != NULL + && field_start - header >= 2 + && field_start[-2] == '\r' + && field_start[-1] == '\n' + && header_end - field_end >= 1 + && field_end[1] == ':') + { + break; /* Found the field */ + } else { + continue; /* This is not the one; keep looking. */ + } + } while(field_start != NULL); + + if(field_start == NULL) { + return NULL; + } + + /* Find the field terminator */ + next_crlf = strstr(field_start, "\r\n"); + + /* A field is expected to end with \r\n */ + if(next_crlf == NULL) { + return NULL; /* Malformed HTTP header! */ + } + + /* If not looking for a value, then return a pointer to the start of values string */ + if(value == NULL) { + return field_end+2; + } + + value_start = strstr(field_start, value); + + /* Value not found */ + if(value_start == NULL) { + return NULL; + } + + /* Found the value we're looking for */ + if(value_start > next_crlf) { + return NULL; /* but after the CRLF terminator of the field. */ + } + + /* The value we found should be properly delineated from the other tokens */ + if(isalnum(value_start[-1]) || isalnum(value_start[strlen(value)])) { + return NULL; + } + + return value_start; +} + +static int http_handshake(int fd) +{ + /* + * Note: The implementation of HTTP handshake in this function is + * written for just a example of how to use of wslay library and is + * not meant to be used in production code. In practice, you need + * to do more strict verification of the client's handshake. + */ + char header[16384], accept_key[29], *keyhdstart, *keyhdend, res_header[256]; + size_t header_length = 0, res_header_sent = 0, res_header_length; + ssize_t r; + while(1) { + while((r = read(fd, header+header_length, sizeof(header)-header_length)) == -1 && errno == EINTR); + if(r == -1) { + perror("read"); + return -1; + } else if(r == 0) { + ws_err("HTTP Handshake: Got EOF"); + return -1; + } else { + header_length += r; + if(header_length >= 4 && memcmp(header+header_length-4, "\r\n\r\n", 4) == 0) { + break; + } else if(header_length == sizeof(header)) { + ws_err("HTTP Handshake: Too large HTTP headers"); + return -1; + } + } + } + + if(http_header_find_field_value(header, "Upgrade", "websocket") == NULL || + http_header_find_field_value(header, "Connection", "Upgrade") == NULL || + (keyhdstart = http_header_find_field_value(header, "Sec-WebSocket-Key", NULL)) == NULL) { + fprintf(stderr, "HTTP Handshake: Missing required header fields"); + return -1; + } + for(; *keyhdstart == ' '; ++keyhdstart); + keyhdend = keyhdstart; + for(; *keyhdend != '\r' && *keyhdend != ' '; ++keyhdend); + if(keyhdend-keyhdstart != 24) { +// printf("%s\n", keyhdstart); + ws_err("HTTP Handshake: Invalid value in Sec-WebSocket-Key"); + return -1; + } + create_accept_key(accept_key, keyhdstart); + snprintf(res_header, sizeof(res_header), + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: %s\r\n" + "\r\n", accept_key); + res_header_length = strlen(res_header); + while(res_header_sent < res_header_length) { + while((r = write(fd, res_header + res_header_sent, res_header_length - res_header_sent)) == -1 && errno == EINTR); + if(r == -1) { + perror("write"); + return -1; + } else { + res_header_sent += r; + } + } + return 0; +} + +static void server_error_exit(const char *message, int sock) +{ + shutdown(sock, SHUT_RD); + printf("Server experienced an error: \t%s\nShutting down ...\n", message); + fflush(stdout); + close(sock); + exit(EXIT_FAILURE); +} + +static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data) +{ + ws_session *session = (ws_session *)user_data; + ssize_t r; + int sflags = 0; +#ifdef MSG_MORE + if(flags & WSLAY_MSG_MORE) { + sflags |= MSG_MORE; + } +#endif // MSG_MORE + while((r = send(session->fd, data, len, sflags)) == -1 && errno == EINTR); + if(r == -1) { + if(errno == EAGAIN || errno == EWOULDBLOCK) { + wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + } else { + wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + } + } + return r; +} + +static ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, int flags, void *user_data) +{ + ws_session *session = (ws_session *)user_data; + ssize_t r; + while((r = recv(session->fd, buf, len, 0)) == -1 && errno == EINTR); + if(r == -1) { + if(errno == EAGAIN || errno == EWOULDBLOCK) { + wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); + } else { + wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + } + } else if(r == 0) { + /* Unexpected EOF is also treated as an error */ + wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); + r = -1; + } + return r; +} + +static void on_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) +{ + /* Echo back non-control message */ + if(!wslay_is_ctrl_frame(arg->opcode)) { + struct wslay_event_msg msgarg = { + arg->opcode, arg->msg, arg->msg_length + }; + wslay_event_queue_msg(ctx, &msgarg); + } +} + +void ws_cleanup(void) +{ + pthread_mutex_lock(&g_mutex_sessions); + ws_session_list_element *elem1, *tmp1; + LL_FOREACH_SAFE(g_session_list, elem1, tmp1) + { + LL_DELETE(g_session_list, elem1); + if(elem1->session) { + ws_session_close(elem1->session); + } + free(elem1); + } + pthread_mutex_unlock(&g_mutex_sessions); + + pthread_mutex_lock(&g_mutex_messages); + ws_message_list_element *elem2, *tmp2; + LL_FOREACH_SAFE(g_message_list, elem2, tmp2) + { + LL_DELETE(g_message_list, elem2); + if(elem2->message) { + free(elem2->message); + } + free(elem2); + } + pthread_mutex_unlock(&g_mutex_messages); +} + +void cleanup_threads(void *args) +{ + //TODO: add thread cleanup code + return; +} + +static struct wslay_event_callbacks callbacks = { + recv_callback, + send_callback, + NULL, + NULL, + NULL, + NULL, + on_msg_recv_callback +}; + +int ws_session_init(ws_session *session) +{ + ws_info("session init"); + session->pfd.fd = session->fd; + session->pfd.events = POLLIN|POLLOUT; + + if(http_handshake(session->fd) == -1) { + return -1; + } + + if(make_non_block(session->fd) == -1) { + return -1; + } + + int val = 1; + if(setsockopt(session->fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) == -1) { + perror("setsockopt: TCP_NODELAY"); + return -1; + } + + wslay_event_context_server_init(&session->ctx, &callbacks, session); + + return 0; +} + +void *ws_handler_thread(void *args) +{ + pthread_cleanup_push(cleanup_threads, args); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + ws_message_list_element *msg_elem = NULL; + ws_session_list_element *session_elem = NULL, *tmp = NULL; + char *message = NULL; + ws_session *session = NULL; + + struct pollfd * fds = calloc(g_websocket_maxlimit, sizeof(struct pollfd)); + + while (g_websocket_running) { + msg_elem = ws_first_message(); + if(msg_elem) { + if(msg_elem->message) { + message = msg_elem->message; + pthread_mutex_lock(&g_mutex_sessions); + LL_FOREACH(g_session_list, session_elem) + { + session = session_elem->session; + struct wslay_event_msg msgarg = { + 1, (uint8_t*)message, strlen(message) + }; + wslay_event_queue_msg(session->ctx, &msgarg); + } + pthread_mutex_unlock(&g_mutex_sessions); + + free(msg_elem->message); + } + free(msg_elem); + } + + int count = 0; + pthread_mutex_lock(&g_mutex_sessions); + LL_COUNT(g_session_list, session_elem, count); + pthread_mutex_unlock(&g_mutex_sessions); + + assert(count <= g_websocket_maxlimit);//check + + int index = 0; + struct pollfd *fd = NULL; + + pthread_mutex_lock(&g_mutex_sessions); + LL_FOREACH(g_session_list, session_elem) + { + if(index >= g_websocket_maxlimit) { //skip invalid sessions + continue; + } + + fd = fds + index; + session = session_elem->session; + + if(wslay_event_want_read(session->ctx)) { + session->pfd.events |= POLLIN; + } + if(wslay_event_want_write(session->ctx)) { + session->pfd.events |= POLLOUT; + } + + memcpy(fd, &session->pfd, sizeof(struct pollfd)); + ++index; + } + pthread_mutex_unlock(&g_mutex_sessions); + + // poll + int res = poll(fds, g_websocket_maxlimit, 0); + if (res == -1 && errno == EINTR) { + continue; + } + + if (res == -1) { + ws_err("[ws_handle_thread] poll error, err : %s", strerror(errno)); + continue; + } + + index = 0; + fd = NULL; + res = 0; + int processed = 0; + pthread_mutex_lock(&g_mutex_sessions); + LL_FOREACH_SAFE(g_session_list, session_elem, tmp) + { + fd = fds + index; + session = session_elem->session; + + if(fd->revents & POLLIN){ + if(wslay_event_recv(session->ctx) != 0) { + ws_err("read error\n"); + res = -1; + } else { + processed = 1; + } + } + + if(fd->revents & POLLOUT){ + if(wslay_event_send(session->ctx) != 0) { + ws_err("write error\n"); + res = -1; + } else { + processed = 1; + } + } + + if(fd->revents & POLLERR) { + ws_err("POLLERR\n"); + res = -1; + } + + if(fd->revents & POLLHUP) { + ws_err("POLLHUP\n"); + res = -1; + } + + if(fd->revents & POLLNVAL) { + ws_err("POLLNVAL\n"); + res = -1; + } + + if(res != 0) { + LL_DELETE(g_session_list, session_elem); + if(session_elem == g_session_list) { + g_session_list = NULL; + } + ws_session_close(session); + free(session_elem); + } + ++index; + } + pthread_mutex_unlock(&g_mutex_sessions); + + if(!processed) { + sleep(1); // sleep 1 if nothing processed + } + } + + g_websocket_running = 0; + ws_cleanup(); + + pthread_cleanup_pop(0); + pthread_exit((void *) EXIT_SUCCESS); + return 0; +} + +void *ws_server_thread(void *args) +{ + pthread_cleanup_push(cleanup_threads, args); + + int port = g_websocket_port; + int sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) { + server_error_exit(strerror(errno), sock); + } + + int on = 1; + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { + server_error_exit(strerror(errno), sock); + } + + struct sockaddr_in peeraddr; + socklen_t peeraddr_len = sizeof(peeraddr); + memset(&peeraddr, 0, sizeof(struct sockaddr_in)); + peeraddr.sin_family = AF_INET; + peeraddr.sin_addr.s_addr = htonl(INADDR_ANY); + peeraddr.sin_port = htons(port); + + if(bind(sock, (struct sockaddr*)&peeraddr, sizeof(peeraddr)) < 0) { + server_error_exit(strerror(errno), sock); + } + + if(listen(sock, 100) < 0) { + server_error_exit(strerror(errno), sock); + } + + while(g_websocket_running) { + int peer_sock = accept(sock, (struct sockaddr*)&peeraddr, &peeraddr_len); + if(peer_sock < 0) { + ws_err("accept error : %s\n", strerror(errno)); + continue; + } + + ws_session *session = calloc(1, sizeof(ws_session)); + if (!session) { + ws_err("[ws_server_thread] calloc failed!"); + continue; + } + session->fd = peer_sock; + session->addr = peeraddr.sin_addr; + session->port = peeraddr.sin_port; + + ws_session_append(session);// append session to session list + } + + close(sock); + + pthread_cleanup_pop(0); + pthread_exit((void *) EXIT_SUCCESS); + return 0; +} + +int xdag_ws_server_start(int maxlimit, int port) +{ + g_websocket_running = 1; + if (maxlimit < 0 || maxlimit > 65535) { // set to default max limit + ws_warn("Invalid websocket max limit value, set to default value %d", WS_DEFAULT_MAX_LIMIT); + g_websocket_maxlimit = WS_DEFAULT_MAX_LIMIT; + } + + if (port < 0 || port > 65535) { // set to default websocket port + ws_warn("Invalid websocket port, set to default port %d", WS_DEFAULT_PORT); + g_websocket_port = WS_DEFAULT_PORT; + } + + pthread_t pthread_id; + pthread_attr_t pthread_attr; + + // create handler thread + pthread_attr_init(&pthread_attr); + pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED); + //pthread_attr_setstacksize(&pthread_attr, 524288); + if(pthread_create(&pthread_id, &pthread_attr, ws_handler_thread, NULL) < 0) { + ws_err("ws_handler_thread create failed due to error : %s\n", strerror(errno)); + pthread_attr_destroy(&pthread_attr); + return -1; + } + pthread_attr_destroy(&pthread_attr); + + // create server thread + pthread_attr_init(&pthread_attr); + pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED); + //pthread_attr_setstacksize(&pthread_attr, 524288); + if(pthread_create(&pthread_id, &pthread_attr, ws_server_thread, NULL) < 0) { + ws_err("ws_server_thread create failed due to error : %s\n", strerror(errno)); + pthread_attr_destroy(&pthread_attr); + return -1; + } + pthread_attr_destroy(&pthread_attr); + + return 0; +} diff --git a/client/websocket/websocket.h b/client/websocket/websocket.h new file mode 100644 index 00000000..31c2c708 --- /dev/null +++ b/client/websocket/websocket.h @@ -0,0 +1,29 @@ +// +// websocket.h +// xdag +// +// Created by Rui Xie on 11/14/18. +// Copyright © 2018 xrdavies. All rights reserved. +// + +#ifndef websocket_h +#define websocket_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + extern int g_websocket_running; + extern int g_websocket_port; + extern int g_websocket_maxlimit; //max websocket clients + + extern void xdag_ws_message_append(char *message); + extern int xdag_ws_server_start(int maxlimit, int port); + extern int xdag_ws_server_stop(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* websocket_h */ diff --git a/client/websocket/wslay/config.h b/client/websocket/wslay/config.h new file mode 100644 index 00000000..9424e87f --- /dev/null +++ b/client/websocket/wslay/config.h @@ -0,0 +1,145 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +#define HAVE_CONFIG_H +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `htons' function. */ +#define HAVE_HTONS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the `ntohl' function. */ +#define HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#define HAVE_NTOHS 1 + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#define HAVE_PTRDIFF_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "wslay" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "t-tujikawa@users.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "wslay" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "wslay 1.1.1-DEV" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "wslay" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.1.1-DEV" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.1.1-DEV" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to the type of an unsigned integer type of width exactly 16 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint16_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ diff --git a/client/websocket/wslay/wslay.h b/client/websocket/wslay/wslay.h new file mode 100755 index 00000000..395f3b11 --- /dev/null +++ b/client/websocket/wslay/wslay.h @@ -0,0 +1,772 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_H +#define WSLAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/* + * wslay/wslayver.h is generated from wslay/wslayver.h.in by + * configure. The projects which do not use autotools can set + * WSLAY_VERSION macro from outside to avoid to generating wslayver.h + */ +#ifndef WSLAY_VERSION +# include "wslayver.h" +#endif /* WSLAY_VERSION */ + +enum wslay_error { + WSLAY_ERR_WANT_READ = -100, + WSLAY_ERR_WANT_WRITE = -101, + WSLAY_ERR_PROTO = -200, + WSLAY_ERR_INVALID_ARGUMENT = -300, + WSLAY_ERR_INVALID_CALLBACK = -301, + WSLAY_ERR_NO_MORE_MSG = -302, + WSLAY_ERR_CALLBACK_FAILURE = -400, + WSLAY_ERR_WOULDBLOCK = -401, + WSLAY_ERR_NOMEM = -500 +}; + +/* + * Status codes defined in RFC6455 + */ +enum wslay_status_code { + WSLAY_CODE_NORMAL_CLOSURE = 1000, + WSLAY_CODE_GOING_AWAY = 1001, + WSLAY_CODE_PROTOCOL_ERROR = 1002, + WSLAY_CODE_UNSUPPORTED_DATA = 1003, + WSLAY_CODE_NO_STATUS_RCVD = 1005, + WSLAY_CODE_ABNORMAL_CLOSURE = 1006, + WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA = 1007, + WSLAY_CODE_POLICY_VIOLATION = 1008, + WSLAY_CODE_MESSAGE_TOO_BIG = 1009, + WSLAY_CODE_MANDATORY_EXT = 1010, + WSLAY_CODE_INTERNAL_SERVER_ERROR = 1011, + WSLAY_CODE_TLS_HANDSHAKE = 1015 +}; + +enum wslay_io_flags { + /* + * There is more data to send. + */ + WSLAY_MSG_MORE = 1 +}; + +/* + * Callback function used by wslay_frame_send() function when it needs + * to send data. The implementation of this function must send at most + * len bytes of data in data. flags is the bitwise OR of zero or more + * of the following flag: + * + * WSLAY_MSG_MORE + * There is more data to send + * + * It provides some hints to tune performance and behaviour. user_data + * is one given in wslay_frame_context_init() function. The + * implementation of this function must return the number of bytes + * sent. If there is an error, return -1. The return value 0 is also + * treated an error by the library. + */ +typedef ssize_t (*wslay_frame_send_callback)(const uint8_t *data, size_t len, + int flags, void *user_data); +/* + * Callback function used by wslay_frame_recv() function when it needs + * more data. The implementation of this function must fill at most + * len bytes of data into buf. The memory area of buf is allocated by + * library and not be freed by the application code. flags is always 0 + * in this version. user_data is one given in + * wslay_frame_context_init() function. The implementation of this + * function must return the number of bytes filled. If there is an + * error, return -1. The return value 0 is also treated an error by + * the library. + */ +typedef ssize_t (*wslay_frame_recv_callback)(uint8_t *buf, size_t len, + int flags, void *user_data); +/* + * Callback function used by wslay_frame_send() function when it needs + * new mask key. The implementation of this function must write + * exactly len bytes of mask key to buf. user_data is one given in + * wslay_frame_context_init() function. The implementation of this + * function return 0 on success. If there is an error, return -1. + */ +typedef int (*wslay_frame_genmask_callback)(uint8_t *buf, size_t len, + void *user_data); + +struct wslay_frame_callbacks { + wslay_frame_send_callback send_callback; + wslay_frame_recv_callback recv_callback; + wslay_frame_genmask_callback genmask_callback; +}; + +/* + * The opcode defined in RFC6455. + */ +enum wslay_opcode { + WSLAY_CONTINUATION_FRAME = 0x0u, + WSLAY_TEXT_FRAME = 0x1u, + WSLAY_BINARY_FRAME = 0x2u, + WSLAY_CONNECTION_CLOSE = 0x8u, + WSLAY_PING = 0x9u, + WSLAY_PONG = 0xau +}; + +/* + * Macro that returns 1 if opcode is control frame opcode, otherwise + * returns 0. + */ +#define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1) + +/* + * Macros that represent and return reserved bits: RSV1, RSV2, RSV3. + * These macros assume that rsv is constructed by ((RSV1 << 2) | + * (RSV2 << 1) | RSV3) + */ +#define WSLAY_RSV_NONE ((uint8_t) 0) +#define WSLAY_RSV1_BIT (((uint8_t) 1) << 2) +#define WSLAY_RSV2_BIT (((uint8_t) 1) << 1) +#define WSLAY_RSV3_BIT (((uint8_t) 1) << 0) + +#define wslay_get_rsv1(rsv) ((rsv >> 2) & 1) +#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1) +#define wslay_get_rsv3(rsv) (rsv & 1) + +struct wslay_frame_iocb { + /* 1 for fragmented final frame, 0 for otherwise */ + uint8_t fin; + /* + * reserved 3 bits. rsv = ((RSV1 << 2) | (RSV << 1) | RSV3). + * RFC6455 requires 0 unless extensions are negotiated. + */ + uint8_t rsv; + /* 4 bit opcode */ + uint8_t opcode; + /* payload length [0, 2**63-1] */ + uint64_t payload_length; + /* 1 for masked frame, 0 for unmasked */ + uint8_t mask; + /* part of payload data */ + const uint8_t *data; + /* bytes of data defined above */ + size_t data_length; +}; + +struct wslay_frame_context; +typedef struct wslay_frame_context *wslay_frame_context_ptr; + +/* + * Initializes ctx using given callbacks and user_data. This function + * allocates memory for struct wslay_frame_context and stores the + * result to *ctx. The callback functions specified in callbacks are + * copied to ctx. user_data is stored in ctx and it will be passed to + * callback functions. When the user code finished using ctx, it must + * call wslay_frame_context_free to deallocate memory. + */ +int wslay_frame_context_init(wslay_frame_context_ptr *ctx, + const struct wslay_frame_callbacks *callbacks, + void *user_data); + +/* + * Deallocates memory pointed by ctx. + */ +void wslay_frame_context_free(wslay_frame_context_ptr ctx); + +/* + * Send WebSocket frame specified in iocb. ctx must be initialized + * using wslay_frame_context_init() function. iocb->fin must be 1 if + * this is a fin frame, otherwise 0. iocb->rsv is reserved bits. + * iocb->opcode must be the opcode of this frame. iocb->mask must be + * 1 if this is masked frame, otherwise 0. iocb->payload_length is + * the payload_length of this frame. iocb->data must point to the + * payload data to be sent. iocb->data_length must be the length of + * the data. This function calls send_callback function if it needs + * to send bytes. This function calls gen_mask_callback function if + * it needs new mask key. This function returns the number of payload + * bytes sent. Please note that it does not include any number of + * header bytes. If it cannot send any single bytes of payload, it + * returns WSLAY_ERR_WANT_WRITE. If the library detects error in iocb, + * this function returns WSLAY_ERR_INVALID_ARGUMENT. If callback + * functions report a failure, this function returns + * WSLAY_ERR_INVALID_CALLBACK. This function does not always send all + * given data in iocb. If there are remaining data to be sent, adjust + * data and data_length in iocb accordingly and call this function + * again. + */ +ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb); + +/* + * Receives WebSocket frame and stores it in iocb. This function + * returns the number of payload bytes received. This does not + * include header bytes. In this case, iocb will be populated as + * follows: iocb->fin is 1 if received frame is fin frame, otherwise + * 0. iocb->rsv is reserved bits of received frame. iocb->opcode is + * opcode of received frame. iocb->mask is 1 if received frame is + * masked, otherwise 0. iocb->payload_length is the payload length of + * received frame. iocb->data is pointed to the buffer containing + * received payload data. This buffer is allocated by the library and + * must be read-only. iocb->data_length is the number of payload + * bytes recieved. This function calls recv_callback if it needs to + * receive additional bytes. If it cannot receive any single bytes of + * payload, it returns WSLAY_ERR_WANT_READ. If the library detects + * protocol violation in a received frame, this function returns + * WSLAY_ERR_PROTO. If callback functions report a failure, this + * function returns WSLAY_ERR_INVALID_CALLBACK. This function does + * not always receive whole frame in a single call. If there are + * remaining data to be received, call this function again. This + * function ensures frame alignment. + */ +ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb); + +struct wslay_event_context; +/* Pointer to the event-based API context */ +typedef struct wslay_event_context *wslay_event_context_ptr; + +struct wslay_event_on_msg_recv_arg { + /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */ + uint8_t rsv; + /* opcode */ + uint8_t opcode; + /* received message */ + const uint8_t *msg; + /* message length */ + size_t msg_length; + /* + * Status code iff opcode == WSLAY_CONNECTION_CLOSE. If no status + * code is included in the close control frame, it is set to 0. + */ + uint16_t status_code; +}; + +/* + * Callback function invoked by wslay_event_recv() when a message is + * completely received. + */ +typedef void (*wslay_event_on_msg_recv_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_msg_recv_arg *arg, void *user_data); + +struct wslay_event_on_frame_recv_start_arg { + /* fin bit; 1 for final frame, or 0. */ + uint8_t fin; + /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */ + uint8_t rsv; + /* opcode of the frame */ + uint8_t opcode; + /* payload length of ths frame */ + uint64_t payload_length; +}; + +/* + * Callback function invoked by wslay_event_recv() when a new frame + * starts to be received. This callback function is only invoked once + * for each frame. + */ +typedef void (*wslay_event_on_frame_recv_start_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data); + +struct wslay_event_on_frame_recv_chunk_arg { + /* chunk of payload data */ + const uint8_t *data; + /* length of data */ + size_t data_length; +}; + +/* + * Callback function invoked by wslay_event_recv() when a chunk of + * frame payload is received. + */ +typedef void (*wslay_event_on_frame_recv_chunk_callback) +(wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data); + +/* + * Callback function invoked by wslay_event_recv() when a frame is + * completely received. + */ +typedef void (*wslay_event_on_frame_recv_end_callback) +(wslay_event_context_ptr ctx, void *user_data); + +/* + * Callback function invoked by wslay_event_recv() when it wants to + * receive more data from peer. The implementation of this callback + * function must read data at most len bytes from peer and store them + * in buf and return the number of bytes read. flags is always 0 in + * this version. + * + * If there is an error, return -1 and set error code + * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay + * event-based API on the whole assumes non-blocking I/O. If the cause + * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK + * instead. This is important because it tells wslay_event_recv() to + * stop receiving further data and return. + */ +typedef ssize_t (*wslay_event_recv_callback)(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, + int flags, void *user_data); + +/* + * Callback function invoked by wslay_event_send() when it wants to + * send more data to peer. The implementation of this callback + * function must send data at most len bytes to peer and return the + * number of bytes sent. flags is the bitwise OR of zero or more of + * the following flag: + * + * WSLAY_MSG_MORE + * There is more data to send + * + * It provides some hints to tune performance and behaviour. + * + * If there is an error, return -1 and set error code + * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay + * event-based API on the whole assumes non-blocking I/O. If the cause + * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK + * instead. This is important because it tells wslay_event_send() to + * stop sending data and return. + */ +typedef ssize_t (*wslay_event_send_callback)(wslay_event_context_ptr ctx, + const uint8_t *data, size_t len, + int flags, void *user_data); + +/* + * Callback function invoked by wslay_event_send() when it wants new + * mask key. As described in RFC6455, only the traffic from WebSocket + * client is masked, so this callback function is only needed if an + * event-based API is initialized for WebSocket client use. + */ +typedef int (*wslay_event_genmask_callback)(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, + void *user_data); + +struct wslay_event_callbacks { + wslay_event_recv_callback recv_callback; + wslay_event_send_callback send_callback; + wslay_event_genmask_callback genmask_callback; + wslay_event_on_frame_recv_start_callback on_frame_recv_start_callback; + wslay_event_on_frame_recv_chunk_callback on_frame_recv_chunk_callback; + wslay_event_on_frame_recv_end_callback on_frame_recv_end_callback; + wslay_event_on_msg_recv_callback on_msg_recv_callback; +}; + +/* + * Initializes ctx as WebSocket Server. user_data is an arbitrary + * pointer, which is directly passed to each callback functions as + * user_data argument. + * + * On success, returns 0. On error, returns one of following negative + * values: + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_context_server_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, void *user_data); + +/* + * Initializes ctx as WebSocket client. user_data is an arbitrary + * pointer, which is directly passed to each callback functions as + * user_data argument. + * + * On success, returns 0. On error, returns one of following negative + * values: + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_context_client_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, void *user_data); + +/* + * Releases allocated resources for ctx. + */ +void wslay_event_context_free(wslay_event_context_ptr ctx); + +/* + * Sets a bit mask of allowed reserved bits. + * Currently only permitted values are WSLAY_RSV1_BIT to allow PMCE + * extension (see RFC-7692) or WSLAY_RSV_NONE to disable. + * + * Default: WSLAY_RSV_NONE + */ +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv); + +/* + * Enables or disables buffering of an entire message for non-control + * frames. If val is 0, buffering is enabled. Otherwise, buffering is + * disabled. If wslay_event_on_msg_recv_callback is invoked when + * buffering is disabled, the msg_length member of struct + * wslay_event_on_msg_recv_arg is set to 0. + * + * The control frames are always buffered regardless of this function call. + * + * This function must not be used after the first invocation of + * wslay_event_recv() function. + */ +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val); + +/* + * Sets maximum length of a message that can be received. The length + * of message is checked by wslay_event_recv() function. If the length + * of a message is larger than this value, reading operation is + * disabled (same effect with wslay_event_shutdown_read() call) and + * close control frame with WSLAY_CODE_MESSAGE_TOO_BIG is queued. If + * buffering for non-control frames is disabled, the library checks + * each frame payload length and does not check length of entire + * message. + * + * The default value is (1u << 31)-1. + */ +void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, + uint64_t val); + +/* + * Sets callbacks to ctx. The callbacks previouly set by this function + * or wslay_event_context_server_init() or + * wslay_event_context_client_init() are replaced with callbacks. + */ +void wslay_event_config_set_callbacks +(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks); + +/* + * Receives messages from peer. When receiving + * messages, it uses wslay_event_recv_callback function. Single call + * of this function receives multiple messages until + * wslay_event_recv_callback function sets error code + * WSLAY_ERR_WOULDBLOCK. + * + * When close control frame is received, this function automatically + * queues close control frame. Also this function calls + * wslay_event_set_read_enabled() with second argument 0 to disable + * further read from peer. + * + * When ping control frame is received, this function automatically + * queues pong control frame. + * + * In case of a fatal errror which leads to negative return code, this + * function calls wslay_event_set_read_enabled() with second argument + * 0 to disable further read from peer. + * + * wslay_event_recv() returns 0 if it succeeds, or one of the + * following negative error codes: + * + * WSLAY_ERR_CALLBACK_FAILURE + * User defined callback function is failed. + * + * WSLAY_ERR_NOMEM + * Out of memory. + * + * When negative error code is returned, application must not make any + * further call of wslay_event_recv() and must close WebSocket + * connection. + */ +int wslay_event_recv(wslay_event_context_ptr ctx); + +/* + * Sends queued messages to peer. When sending a + * message, it uses wslay_event_send_callback function. Single call of + * wslay_event_send() sends multiple messages until + * wslay_event_send_callback sets error code WSLAY_ERR_WOULDBLOCK. + * + * If ctx is initialized for WebSocket client use, wslay_event_send() + * uses wslay_event_genmask_callback to get new mask key. + * + * When a message queued using wslay_event_queue_fragmented_msg() is + * sent, wslay_event_send() invokes + * wslay_event_fragmented_msg_callback for that message. + * + * After close control frame is sent, this function calls + * wslay_event_set_write_enabled() with second argument 0 to disable + * further transmission to peer. + * + * If there are any pending messages, wslay_event_want_write() returns + * 1, otherwise returns 0. + * + * In case of a fatal errror which leads to negative return code, this + * function calls wslay_event_set_write_enabled() with second argument + * 0 to disable further transmission to peer. + * + * wslay_event_send() returns 0 if it succeeds, or one of the + * following negative error codes: + * + * WSLAY_ERR_CALLBACK_FAILURE + * User defined callback function is failed. + * + * WSLAY_ERR_NOMEM + * Out of memory. + * + * When negative error code is returned, application must not make any + * further call of wslay_event_send() and must close WebSocket + * connection. + */ +int wslay_event_send(wslay_event_context_ptr ctx); + +struct wslay_event_msg { + uint8_t opcode; + const uint8_t *msg; + size_t msg_length; +}; + +/* + * Queues message specified in arg. + * + * This function supports both control and non-control messages and + * the given message is sent without fragmentation. If fragmentation + * is needed, use wslay_event_queue_fragmented_msg() function instead. + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_msg() returns 0 if it succeeds, or returns the + * following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_msg(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg); + +/* + * Extended version of wslay_event_queue_msg which allows to set reserved bits. + */ +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv); + +/* + * Specify "source" to generate message. + */ +union wslay_event_msg_source { + int fd; + void *data; +}; + +/* + * Callback function called by wslay_event_send() to read message data + * from source. The implementation of + * wslay_event_fragmented_msg_callback must store at most len bytes of + * data to buf and return the number of stored bytes. If all data is + * read (i.e., EOF), set *eof to 1. If no data can be generated at the + * moment, return 0. If there is an error, return -1 and set error + * code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). + */ +typedef ssize_t (*wslay_event_fragmented_msg_callback) +(wslay_event_context_ptr ctx, + uint8_t *buf, size_t len, const union wslay_event_msg_source *source, + int *eof, void *user_data); + +struct wslay_event_fragmented_msg { + /* opcode */ + uint8_t opcode; + /* "source" to generate message data */ + union wslay_event_msg_source source; + /* Callback function to read message data from source. */ + wslay_event_fragmented_msg_callback read_callback; +}; + +/* + * Queues a fragmented message specified in arg. + * + * This function supports non-control messages only. For control frames, + * use wslay_event_queue_msg() or wslay_event_queue_close(). + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_fragmented_msg() returns 0 if it succeeds, or + * returns the following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_fragmented_msg +(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg); + +/* + * Extended version of wslay_event_queue_fragmented_msg which allows to set + * reserved bits. + */ +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv); + +/* + * Queues close control frame. This function is provided just for + * convenience. wslay_event_queue_msg() can queue a close control + * frame as well. status_code is the status code of close control + * frame. reason is the close reason encoded in UTF-8. reason_length + * is the length of reason in bytes. reason_length must be less than + * 123 bytes. + * + * If status_code is 0, reason and reason_length is not used and close + * control frame with zero-length payload will be queued. + * + * This function just queues a message and does not send + * it. wslay_event_send() function call sends these queued messages. + * + * wslay_event_queue_close() returns 0 if it succeeds, or returns the + * following negative error codes: + * + * WSLAY_ERR_NO_MORE_MSG + * Could not queue given message. The one of possible reason is that + * close control frame has been queued/sent and no further queueing + * message is not allowed. + * + * WSLAY_ERR_INVALID_ARGUMENT + * The given message is invalid. + * + * WSLAY_ERR_NOMEM + * Out of memory. + */ +int wslay_event_queue_close(wslay_event_context_ptr ctx, + uint16_t status_code, + const uint8_t *reason, size_t reason_length); + +/* + * Sets error code to tell the library there is an error. This + * function is typically used in user defined callback functions. See + * the description of callback function to know which error code + * should be used. + */ +void wslay_event_set_error(wslay_event_context_ptr ctx, int val); + +/* + * Query whehter the library want to read more data from peer. + * + * wslay_event_want_read() returns 1 if the library want to read more + * data from peer, or returns 0. + */ +int wslay_event_want_read(wslay_event_context_ptr ctx); + +/* + * Query whehter the library want to send more data to peer. + * + * wslay_event_want_write() returns 1 if the library want to send more + * data to peer, or returns 0. + */ +int wslay_event_want_write(wslay_event_context_ptr ctx); + +/* + * Prevents the event-based API context from reading any further data + * from peer. + * + * This function may be used with wslay_event_queue_close() if the + * application detects error in the data received and wants to fail + * WebSocket connection. + */ +void wslay_event_shutdown_read(wslay_event_context_ptr ctx); + +/* + * Prevents the event-based API context from sending any further data + * to peer. + */ +void wslay_event_shutdown_write(wslay_event_context_ptr ctx); + +/* + * Returns 1 if the event-based API context allows read operation, or + * return 0. + * + * After wslay_event_shutdown_read() is called, + * wslay_event_get_read_enabled() returns 0. + */ +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx); + +/* + * Returns 1 if the event-based API context allows write operation, or + * return 0. + * + * After wslay_event_shutdown_write() is called, + * wslay_event_get_write_enabled() returns 0. + */ +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx); + +/* + * Returns 1 if a close control frame has been received from peer, or + * returns 0. + */ +int wslay_event_get_close_received(wslay_event_context_ptr ctx); + +/* + * Returns 1 if a close control frame has been sent to peer, or + * returns 0. + */ +int wslay_event_get_close_sent(wslay_event_context_ptr ctx); + +/* + * Returns status code received in close control frame. If no close + * control frame has not been received, returns + * WSLAY_CODE_ABNORMAL_CLOSURE. If received close control frame has no + * status code, returns WSLAY_CODE_NO_STATUS_RCVD. + */ +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx); + +/* + * Returns status code sent in close control frame. If no close + * control frame has not been sent, returns + * WSLAY_CODE_ABNORMAL_CLOSURE. If sent close control frame has no + * status code, returns WSLAY_CODE_NO_STATUS_RCVD. + */ +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx); + +/* + * Returns the number of queued messages. + */ +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx); + +/* + * Returns the sum of queued message length. It only counts the + * message length queued using wslay_event_queue_msg() or + * wslay_event_queue_close(). + */ +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* WSLAY_H */ diff --git a/client/websocket/wslay/wslay_event.c b/client/websocket/wslay/wslay_event.c new file mode 100755 index 00000000..57415c51 --- /dev/null +++ b/client/websocket/wslay/wslay_event.c @@ -0,0 +1,1027 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "wslay_event.h" + +#include +#include +#include + +#include "wslay_queue.h" +#include "wslay_frame.h" +#include "wslay_net.h" +/* Start of utf8 dfa */ +/* Copyright (c) 2008-2010 Bjoern Hoehrmann + * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + * + * Copyright (c) 2008-2009 Bjoern Hoehrmann + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 + +static const uint8_t utf8d[] = { + /* + * The first part of the table maps bytes to character classes that + * to reduce the size of the transition table and create bitmasks. + */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + /* + * The second part is a transition table that maps a combination + * of a state of the automaton and a character class to a state. + */ + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + +static uint32_t +decode(uint32_t* state, uint32_t* codep, uint32_t byte) { + uint32_t type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +/* End of utf8 dfa */ + +static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len, + int flags, void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data); +} + +static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len, + int flags, void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.send_callback(e->ctx, data, len, flags, + e->user_data); +} + +static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len, + void *user_data) +{ + struct wslay_event_frame_user_data *e = + (struct wslay_event_frame_user_data*)user_data; + return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data); +} + +static int wslay_event_byte_chunk_init +(struct wslay_event_byte_chunk **chunk, size_t len) +{ + *chunk = (struct wslay_event_byte_chunk*)malloc + (sizeof(struct wslay_event_byte_chunk)); + if(*chunk == NULL) { + return WSLAY_ERR_NOMEM; + } + memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk)); + if(len) { + (*chunk)->data = (uint8_t*)malloc(len); + if((*chunk)->data == NULL) { + free(*chunk); + return WSLAY_ERR_NOMEM; + } + (*chunk)->data_length = len; + } + return 0; +} + +static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) +{ + if(!c) { + return; + } + free(c->data); + free(c); +} + +static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c, + size_t off, + const uint8_t *data, size_t data_length) +{ + memcpy(c->data+off, data, data_length); +} + +static void wslay_event_imsg_set(struct wslay_event_imsg *m, + uint8_t fin, uint8_t rsv, uint8_t opcode) +{ + m->fin = fin; + m->rsv = rsv; + m->opcode = opcode; + m->msg_length = 0; +} + +static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) +{ + if(!m->chunks) { + return; + } + while(!wslay_queue_empty(m->chunks)) { + wslay_event_byte_chunk_free(wslay_queue_top(m->chunks)); + wslay_queue_pop(m->chunks); + } +} + +static void wslay_event_imsg_reset(struct wslay_event_imsg *m) +{ + m->opcode = 0xffu; + m->utf8state = UTF8_ACCEPT; + wslay_event_imsg_chunks_free(m); +} + +static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len) +{ + if(len == 0) { + return 0; + } else { + int r; + struct wslay_event_byte_chunk *chunk; + if((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { + return r; + } + if((r = wslay_queue_push(m->chunks, chunk)) != 0) { + return r; + } + m->msg_length += len; + return 0; + } +} + +static int wslay_event_omsg_non_fragmented_init +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, + const uint8_t *msg, size_t msg_length) +{ + *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); + if(!*m) { + return WSLAY_ERR_NOMEM; + } + memset(*m, 0, sizeof(struct wslay_event_omsg)); + (*m)->fin = 1; + (*m)->opcode = opcode; + (*m)->rsv = rsv; + (*m)->type = WSLAY_NON_FRAGMENTED; + if(msg_length) { + (*m)->data = (uint8_t*)malloc(msg_length); + if(!(*m)->data) { + free(*m); + return WSLAY_ERR_NOMEM; + } + memcpy((*m)->data, msg, msg_length); + (*m)->data_length = msg_length; + } + return 0; +} + +static int wslay_event_omsg_fragmented_init +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, + const union wslay_event_msg_source source, + wslay_event_fragmented_msg_callback read_callback) +{ + *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); + if(!*m) { + return WSLAY_ERR_NOMEM; + } + memset(*m, 0, sizeof(struct wslay_event_omsg)); + (*m)->opcode = opcode; + (*m)->rsv = rsv; + (*m)->type = WSLAY_FRAGMENTED; + (*m)->source = source; + (*m)->read_callback = read_callback; + return 0; +} + +static void wslay_event_omsg_free(struct wslay_event_omsg *m) +{ + if(!m) { + return; + } + free(m->data); + free(m); +} + +static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) +{ + if(len == 0) { + return NULL; + } else { + size_t off = 0; + uint8_t *buf = (uint8_t*)malloc(len); + if(!buf) { + return NULL; + } + while(!wslay_queue_empty(queue)) { + struct wslay_event_byte_chunk *chunk = wslay_queue_top(queue); + memcpy(buf+off, chunk->data, chunk->data_length); + off += chunk->data_length; + wslay_event_byte_chunk_free(chunk); + wslay_queue_pop(queue); + assert(off <= len); + } + assert(len == off); + return buf; + } +} + +static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0; +} + +int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, + const uint8_t *reason, size_t reason_length) +{ + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } else if(reason_length > 123) { + return WSLAY_ERR_INVALID_ARGUMENT; + } else { + uint8_t msg[128]; + size_t msg_length; + struct wslay_event_msg arg; + uint16_t ncode; + int r; + if(status_code == 0) { + msg_length = 0; + } else { + ncode = htons(status_code); + memcpy(msg, &ncode, 2); + if(reason_length) { + memcpy(msg+2, reason, reason_length); + } + msg_length = reason_length+2; + } + arg.opcode = WSLAY_CONNECTION_CLOSE; + arg.msg = msg; + arg.msg_length = msg_length; + r = wslay_event_queue_msg(ctx, &arg); + if(r == 0) { + ctx->close_status |= WSLAY_CLOSE_QUEUED; + } + return r; + } +} + +static int wslay_event_queue_close_wrapper +(wslay_event_context_ptr ctx, uint16_t status_code, + const uint8_t *reason, size_t reason_length) +{ + int r; + ctx->read_enabled = 0; + if((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && + r != WSLAY_ERR_NO_MORE_MSG) { + return r; + } + return 0; +} + +static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv) +{ + return ((rsv & ~ctx->allowed_rsv_bits) == 0); +} + +int wslay_event_queue_msg(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg) +{ + return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv) +{ + int r; + struct wslay_event_omsg *omsg; + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } + /* RSV1 is not allowed for control frames */ + if((wslay_is_ctrl_frame(arg->opcode) && + (arg->msg_length > 125 || wslay_get_rsv1(rsv))) + || !wslay_event_verify_rsv_bits(ctx, rsv)) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if((r = wslay_event_omsg_non_fragmented_init + (&omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { + return r; + } + if(wslay_is_ctrl_frame(arg->opcode)) { + if((r = wslay_queue_push(ctx->send_ctrl_queue, omsg)) != 0) { + return r; + } + } else { + if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + return r; + } + } + ++ctx->queued_msg_count; + ctx->queued_msg_length += arg->msg_length; + return 0; +} + +int wslay_event_queue_fragmented_msg +(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) +{ + return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv) +{ + int r; + struct wslay_event_omsg *omsg; + if(!wslay_event_is_msg_queueable(ctx)) { + return WSLAY_ERR_NO_MORE_MSG; + } + if(wslay_is_ctrl_frame(arg->opcode) || + !wslay_event_verify_rsv_bits(ctx, rsv)) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if((r = wslay_event_omsg_fragmented_init + (&omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { + return r; + } + if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + return r; + } + ++ctx->queued_msg_count; + return 0; +} + +void wslay_event_config_set_callbacks +(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks) +{ + ctx->callbacks = *callbacks; +} + +static int wslay_event_context_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int i, r; + struct wslay_frame_callbacks frame_callbacks = { + wslay_event_frame_send_callback, + wslay_event_frame_recv_callback, + wslay_event_frame_genmask_callback + }; + *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context)); + if(!*ctx) { + return WSLAY_ERR_NOMEM; + } + memset(*ctx, 0, sizeof(struct wslay_event_context)); + wslay_event_config_set_callbacks(*ctx, callbacks); + (*ctx)->user_data = user_data; + (*ctx)->frame_user_data.ctx = *ctx; + (*ctx)->frame_user_data.user_data = user_data; + if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, + &(*ctx)->frame_user_data)) != 0) { + wslay_event_context_free(*ctx); + return r; + } + (*ctx)->read_enabled = (*ctx)->write_enabled = 1; + (*ctx)->send_queue = wslay_queue_new(); + if(!(*ctx)->send_queue) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + (*ctx)->send_ctrl_queue = wslay_queue_new(); + if(!(*ctx)->send_ctrl_queue) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + (*ctx)->queued_msg_count = 0; + (*ctx)->queued_msg_length = 0; + for(i = 0; i < 2; ++i) { + wslay_event_imsg_reset(&(*ctx)->imsgs[i]); + (*ctx)->imsgs[i].chunks = wslay_queue_new(); + if(!(*ctx)->imsgs[i].chunks) { + wslay_event_context_free(*ctx); + return WSLAY_ERR_NOMEM; + } + } + (*ctx)->imsg = &(*ctx)->imsgs[0]; + (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf; + (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE; + (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE; + (*ctx)->max_recv_msg_length = (1u << 31)-1; + return 0; +} + +int wslay_event_context_server_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int r; + if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + return r; + } + (*ctx)->server = 1; + return 0; +} + +int wslay_event_context_client_init +(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) +{ + int r; + if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + return r; + } + (*ctx)->server = 0; + return 0; +} + +void wslay_event_context_free(wslay_event_context_ptr ctx) +{ + int i; + if(!ctx) { + return; + } + for(i = 0; i < 2; ++i) { + wslay_event_imsg_chunks_free(&ctx->imsgs[i]); + wslay_queue_free(ctx->imsgs[i].chunks); + } + if(ctx->send_queue) { + while(!wslay_queue_empty(ctx->send_queue)) { + wslay_event_omsg_free(wslay_queue_top(ctx->send_queue)); + wslay_queue_pop(ctx->send_queue); + } + wslay_queue_free(ctx->send_queue); + } + if(ctx->send_ctrl_queue) { + while(!wslay_queue_empty(ctx->send_ctrl_queue)) { + wslay_event_omsg_free(wslay_queue_top(ctx->send_ctrl_queue)); + wslay_queue_pop(ctx->send_ctrl_queue); + } + wslay_queue_free(ctx->send_ctrl_queue); + } + wslay_frame_context_free(ctx->frame_ctx); + wslay_event_omsg_free(ctx->omsg); + free(ctx); +} + +static void wslay_event_call_on_frame_recv_start_callback +(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) +{ + if(ctx->callbacks.on_frame_recv_start_callback) { + struct wslay_event_on_frame_recv_start_arg arg; + arg.fin = iocb->fin; + arg.rsv = iocb->rsv; + arg.opcode = iocb->opcode; + arg.payload_length = iocb->payload_length; + ctx->callbacks.on_frame_recv_start_callback(ctx, &arg, ctx->user_data); + } +} + +static void wslay_event_call_on_frame_recv_chunk_callback +(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) +{ + if(ctx->callbacks.on_frame_recv_chunk_callback) { + struct wslay_event_on_frame_recv_chunk_arg arg; + arg.data = iocb->data; + arg.data_length = iocb->data_length; + ctx->callbacks.on_frame_recv_chunk_callback(ctx, &arg, ctx->user_data); + } +} + +static void wslay_event_call_on_frame_recv_end_callback +(wslay_event_context_ptr ctx) +{ + if(ctx->callbacks.on_frame_recv_end_callback) { + ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data); + } +} + +static int wslay_event_is_valid_status_code(uint16_t status_code) +{ + return (1000 <= status_code && status_code <= 1011 && + status_code != 1004 && status_code != 1005 && status_code != 1006) || + (3000 <= status_code && status_code <= 4999); +} + +static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) +{ + return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0; +} + +int wslay_event_recv(wslay_event_context_ptr ctx) +{ + struct wslay_frame_iocb iocb; + ssize_t r; + while(ctx->read_enabled) { + memset(&iocb, 0, sizeof(iocb)); + r = wslay_frame_recv(ctx->frame_ctx, &iocb); + if(r >= 0) { + int new_frame = 0; + /* RSV1 is not allowed on control and continuation frames */ + if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || + (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) || + iocb.opcode == WSLAY_CONTINUATION_FRAME)) || + (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + if(ctx->imsg->opcode == 0xffu) { + if(iocb.opcode == WSLAY_TEXT_FRAME || + iocb.opcode == WSLAY_BINARY_FRAME || + iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || + iocb.opcode == WSLAY_PONG) { + wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); + new_frame = 1; + } else { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + } else if(ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { + if(iocb.opcode == WSLAY_CONTINUATION_FRAME) { + ctx->imsg->fin = iocb.fin; + } else if(iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || + iocb.opcode == WSLAY_PONG) { + ctx->imsg = &ctx->imsgs[1]; + wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); + } else { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + new_frame = 1; + } + if(new_frame) { + if(ctx->imsg->msg_length+iocb.payload_length > + ctx->max_recv_msg_length) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { + return r; + } + break; + } + ctx->ipayloadlen = iocb.payload_length; + wslay_event_call_on_frame_recv_start_callback(ctx, &iocb); + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + if((r = wslay_event_imsg_append_chunk(ctx->imsg, + iocb.payload_length)) != 0) { + ctx->read_enabled = 0; + return r; + } + } + } + /* If RSV1 bit is set then it is too early for utf-8 validation */ + if((!wslay_get_rsv1(ctx->imsg->rsv) && + ctx->imsg->opcode == WSLAY_TEXT_FRAME) || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + size_t i; + if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + i = 2; + } else { + i = 0; + } + for(; i < iocb.data_length; ++i) { + uint32_t codep; + if(decode(&ctx->imsg->utf8state, &codep, + iocb.data[i]) == UTF8_REJECT) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return r; + } + break; + } + } + } + if(ctx->imsg->utf8state == UTF8_REJECT) { + break; + } + wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb); + if(iocb.data_length > 0) { + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + struct wslay_event_byte_chunk *chunk; + chunk = wslay_queue_tail(ctx->imsg->chunks); + wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, + iocb.data, iocb.data_length); + } + ctx->ipayloadoff += iocb.data_length; + } + if(ctx->ipayloadoff == ctx->ipayloadlen) { + if(ctx->imsg->fin && + (ctx->imsg->opcode == WSLAY_TEXT_FRAME || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && + ctx->imsg->utf8state != UTF8_ACCEPT) { + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return r; + } + break; + } + wslay_event_call_on_frame_recv_end_callback(ctx); + if(ctx->imsg->fin) { + if(ctx->callbacks.on_msg_recv_callback || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || + ctx->imsg->opcode == WSLAY_PING) { + struct wslay_event_on_msg_recv_arg arg; + uint16_t status_code = 0; + uint8_t *msg = NULL; + size_t msg_length = 0; + if(!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + msg = wslay_event_flatten_queue(ctx->imsg->chunks, + ctx->imsg->msg_length); + if(ctx->imsg->msg_length && !msg) { + ctx->read_enabled = 0; + return WSLAY_ERR_NOMEM; + } + msg_length = ctx->imsg->msg_length; + } + if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + const uint8_t *reason; + size_t reason_length; + if(ctx->imsg->msg_length >= 2) { + memcpy(&status_code, msg, 2); + status_code = ntohs(status_code); + if(!wslay_event_is_valid_status_code(status_code)) { + free(msg); + if((r = wslay_event_queue_close_wrapper + (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return r; + } + break; + } + reason = msg+2; + reason_length = ctx->imsg->msg_length-2; + } else { + reason = NULL; + reason_length = 0; + } + ctx->close_status |= WSLAY_CLOSE_RECEIVED; + ctx->status_code_recv = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + if((r = wslay_event_queue_close_wrapper + (ctx, status_code, reason, reason_length)) != 0) { + free(msg); + return r; + } + } else if(ctx->imsg->opcode == WSLAY_PING) { + struct wslay_event_msg arg; + arg.opcode = WSLAY_PONG; + arg.msg = msg; + arg.msg_length = ctx->imsg->msg_length; + if((r = wslay_event_queue_msg(ctx, &arg)) && + r != WSLAY_ERR_NO_MORE_MSG) { + ctx->read_enabled = 0; + free(msg); + return r; + } + } + if(ctx->callbacks.on_msg_recv_callback) { + arg.rsv = ctx->imsg->rsv; + arg.opcode = ctx->imsg->opcode; + arg.msg = msg; + arg.msg_length = msg_length; + arg.status_code = status_code; + ctx->error = 0; + ctx->callbacks.on_msg_recv_callback(ctx, &arg, ctx->user_data); + } + free(msg); + } + wslay_event_imsg_reset(ctx->imsg); + if(ctx->imsg == &ctx->imsgs[1]) { + ctx->imsg = &ctx->imsgs[0]; + } + } + ctx->ipayloadlen = ctx->ipayloadoff = 0; + } + } else { + if(r != WSLAY_ERR_WANT_READ || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { + return r; + } + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } + return 0; +} + +static void wslay_event_on_non_fragmented_msg_popped +(wslay_event_context_ptr ctx) +{ + ctx->omsg->fin = 1; + ctx->opayloadlen = ctx->omsg->data_length; + ctx->opayloadoff = 0; +} + +static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop +(wslay_event_context_ptr ctx) +{ + /* + * If Close control frame is queued, we don't send any control frame + * other than Close. + */ + if(ctx->close_status & WSLAY_CLOSE_QUEUED) { + while(!wslay_queue_empty(ctx->send_ctrl_queue)) { + struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); + wslay_queue_pop(ctx->send_ctrl_queue); + if(msg->opcode == WSLAY_CONNECTION_CLOSE) { + return msg; + } else { + wslay_event_omsg_free(msg); + } + } + return NULL; + } else { + struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); + wslay_queue_pop(ctx->send_ctrl_queue); + return msg; + } +} + +int wslay_event_send(wslay_event_context_ptr ctx) +{ + struct wslay_frame_iocb iocb; + ssize_t r; + while(ctx->write_enabled && + (!wslay_queue_empty(ctx->send_queue) || + !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg)) { + if(!ctx->omsg) { + if(wslay_queue_empty(ctx->send_ctrl_queue)) { + ctx->omsg = wslay_queue_top(ctx->send_queue); + wslay_queue_pop(ctx->send_queue); + } else { + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if(ctx->omsg == NULL) { + break; + } + } + if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + wslay_event_on_non_fragmented_msg_popped(ctx); + } + } else if(!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(ctx->send_ctrl_queue)) { + if((r = wslay_queue_push_front(ctx->send_queue, ctx->omsg)) != 0) { + ctx->write_enabled = 0; + return r; + } + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if(ctx->omsg == NULL) { + break; + } + /* ctrl message has WSLAY_NON_FRAGMENTED */ + wslay_event_on_non_fragmented_msg_popped(ctx); + } + if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server^1; + iocb.data = ctx->omsg->data+ctx->opayloadoff; + iocb.data_length = ctx->opayloadlen-ctx->opayloadoff; + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_send(ctx->frame_ctx, &iocb); + if(r >= 0) { + ctx->opayloadoff += r; + if(ctx->opayloadoff == ctx->opayloadlen) { + --ctx->queued_msg_count; + ctx->queued_msg_length -= ctx->omsg->data_length; + if(ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + uint16_t status_code = 0; + ctx->write_enabled = 0; + ctx->close_status |= WSLAY_CLOSE_SENT; + if(ctx->omsg->data_length >= 2) { + memcpy(&status_code, ctx->omsg->data, 2); + status_code = ntohs(status_code); + } + ctx->status_code_sent = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + } + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + break; + } + } else { + if(r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } else { + if(ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + int eof = 0; + r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), + &ctx->omsg->source, + &eof, ctx->user_data); + if(r == 0) { + break; + } else if(r < 0) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + ctx->obuflimit = ctx->obuf+r; + if(eof) { + ctx->omsg->fin = 1; + } + ctx->opayloadlen = r; + ctx->opayloadoff = 0; + } + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = ctx->omsg->fin; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server ? 0 : 1; + iocb.data = ctx->obufmark; + iocb.data_length = ctx->obuflimit-ctx->obufmark; + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_send(ctx->frame_ctx, &iocb); + if(r >= 0) { + ctx->obufmark += r; + if(ctx->obufmark == ctx->obuflimit) { + ctx->obufmark = ctx->obuflimit = ctx->obuf; + if(ctx->omsg->fin) { + --ctx->queued_msg_count; + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; + /* RSV1 is not set on continuation frames */ + ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT; + } + } else { + break; + } + } else { + if(r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && + ctx->error != 0)) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + break; + } + } + } + return 0; +} + +void wslay_event_set_error(wslay_event_context_ptr ctx, int val) +{ + ctx->error = val; +} + +int wslay_event_want_read(wslay_event_context_ptr ctx) +{ + return ctx->read_enabled; +} + +int wslay_event_want_write(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled && + (!wslay_queue_empty(ctx->send_queue) || + !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg); +} + +void wslay_event_shutdown_read(wslay_event_context_ptr ctx) +{ + ctx->read_enabled = 0; +} + +void wslay_event_shutdown_write(wslay_event_context_ptr ctx) +{ + ctx->write_enabled = 0; +} + +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) +{ + return ctx->read_enabled; +} + +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) +{ + return ctx->write_enabled; +} + +int wslay_event_get_close_received(wslay_event_context_ptr ctx) +{ + return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0; +} + +int wslay_event_get_close_sent(wslay_event_context_ptr ctx) +{ + return (ctx->close_status & WSLAY_CLOSE_SENT) > 0; +} + +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv) +{ + /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */ + ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT; +} + +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) +{ + if(val) { + ctx->config |= WSLAY_CONFIG_NO_BUFFERING; + } else { + ctx->config &= ~WSLAY_CONFIG_NO_BUFFERING; + } +} + +void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, + uint64_t val) +{ + ctx->max_recv_msg_length = val; +} + +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) +{ + return ctx->status_code_recv; +} + +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) +{ + return ctx->status_code_sent; +} + +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) +{ + return ctx->queued_msg_count; +} + +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) +{ + return ctx->queued_msg_length; +} diff --git a/client/websocket/wslay/wslay_event.h b/client/websocket/wslay/wslay_event.h new file mode 100755 index 00000000..9ced0e52 --- /dev/null +++ b/client/websocket/wslay/wslay_event.h @@ -0,0 +1,142 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_EVENT_H +#define WSLAY_EVENT_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include "wslay.h" + +struct wslay_stack; +struct wslay_queue; + +struct wslay_event_byte_chunk { + uint8_t *data; + size_t data_length; +}; + +struct wslay_event_imsg { + uint8_t fin; + uint8_t rsv; + uint8_t opcode; + uint32_t utf8state; + struct wslay_queue *chunks; + size_t msg_length; +}; + +enum wslay_event_msg_type { + WSLAY_NON_FRAGMENTED, + WSLAY_FRAGMENTED +}; + +struct wslay_event_omsg { + uint8_t fin; + uint8_t opcode; + uint8_t rsv; + enum wslay_event_msg_type type; + + uint8_t *data; + size_t data_length; + + union wslay_event_msg_source source; + wslay_event_fragmented_msg_callback read_callback; +}; + +struct wslay_event_frame_user_data { + wslay_event_context_ptr ctx; + void *user_data; +}; + +enum wslay_event_close_status { + WSLAY_CLOSE_RECEIVED = 1 << 0, + WSLAY_CLOSE_QUEUED = 1 << 1, + WSLAY_CLOSE_SENT = 1 << 2 +}; + +enum wslay_event_config { + WSLAY_CONFIG_NO_BUFFERING = 1 << 0 +}; + +struct wslay_event_context { + /* config status, bitwise OR of enum wslay_event_config values*/ + uint32_t config; + /* maximum message length that can be received */ + uint64_t max_recv_msg_length; + /* 1 if initialized for server, otherwise 0 */ + uint8_t server; + /* bitwise OR of enum wslay_event_close_status values */ + uint8_t close_status; + /* status code in received close control frame */ + uint16_t status_code_recv; + /* status code in sent close control frame */ + uint16_t status_code_sent; + wslay_frame_context_ptr frame_ctx; + /* 1 if reading is enabled, otherwise 0. Upon receiving close + control frame this value set to 0. If any errors in read + operation will also set this value to 0. */ + uint8_t read_enabled; + /* 1 if writing is enabled, otherwise 0 Upon completing sending + close control frame, this value set to 0. If any errors in write + opration will also set this value to 0. */ + uint8_t write_enabled; + /* imsg buffer to allow interleaved control frame between + non-control frames. */ + struct wslay_event_imsg imsgs[2]; + /* Pointer to imsgs to indicate current used buffer. */ + struct wslay_event_imsg *imsg; + /* payload length of frame currently being received. */ + uint64_t ipayloadlen; + /* next byte offset of payload currently being received. */ + uint64_t ipayloadoff; + /* error value set by user callback */ + int error; + /* Pointer to the message currently being sent. NULL if no message + is currently sent. */ + struct wslay_event_omsg *omsg; + /* Queue for non-control frames */ + struct wslay_queue/**/ *send_queue; + /* Queue for control frames */ + struct wslay_queue/**/ *send_ctrl_queue; + /* Size of send_queue + size of send_ctrl_queue */ + size_t queued_msg_count; + /* The sum of message length in send_queue */ + size_t queued_msg_length; + /* Buffer used for fragmented messages */ + uint8_t obuf[4096]; + uint8_t *obuflimit; + uint8_t *obufmark; + /* payload length of frame currently being sent. */ + uint64_t opayloadlen; + /* next byte offset of payload currently being sent. */ + uint64_t opayloadoff; + struct wslay_event_callbacks callbacks; + struct wslay_event_frame_user_data frame_user_data; + void *user_data; + uint8_t allowed_rsv_bits; +}; + +#endif /* WSLAY_EVENT_H */ diff --git a/client/websocket/wslay/wslay_frame.c b/client/websocket/wslay/wslay_frame.c new file mode 100755 index 00000000..445e750c --- /dev/null +++ b/client/websocket/wslay/wslay_frame.c @@ -0,0 +1,340 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "wslay_frame.h" + +#include +#include +#include + +#include "wslay_net.h" + +#define wslay_min(A, B) (((A) < (B)) ? (A) : (B)) + +int wslay_frame_context_init(wslay_frame_context_ptr *ctx, + const struct wslay_frame_callbacks *callbacks, + void *user_data) +{ + *ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context)); + if(*ctx == NULL) { + return -1; + } + memset(*ctx, 0, sizeof(struct wslay_frame_context)); + (*ctx)->istate = RECV_HEADER1; + (*ctx)->ireqread = 2; + (*ctx)->ostate = PREP_HEADER; + (*ctx)->user_data = user_data; + (*ctx)->ibufmark = (*ctx)->ibuflimit = (*ctx)->ibuf; + (*ctx)->callbacks = *callbacks; + return 0; +} + +void wslay_frame_context_free(wslay_frame_context_ptr ctx) +{ + free(ctx); +} + +ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb) +{ + if(iocb->data_length > iocb->payload_length) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(ctx->ostate == PREP_HEADER) { + uint8_t *hdptr = ctx->oheader; + memset(ctx->oheader, 0, sizeof(ctx->oheader)); + *hdptr |= (iocb->fin << 7) & 0x80u; + *hdptr |= (iocb->rsv << 4) & 0x70u; + *hdptr |= iocb->opcode & 0xfu; + ++hdptr; + *hdptr |= (iocb->mask << 7) & 0x80u; + if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(iocb->payload_length < 126) { + *hdptr |= iocb->payload_length; + ++hdptr; + } else if(iocb->payload_length < (1 << 16)) { + uint16_t len = htons(iocb->payload_length); + *hdptr |= 126; + ++hdptr; + memcpy(hdptr, &len, 2); + hdptr += 2; + } else if(iocb->payload_length < (1ull << 63)) { + uint64_t len = hton64(iocb->payload_length); + *hdptr |= 127; + ++hdptr; + memcpy(hdptr, &len, 8); + hdptr += 8; + } else { + /* Too large payload length */ + return WSLAY_ERR_INVALID_ARGUMENT; + } + if(iocb->mask) { + if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4, + ctx->user_data) != 0) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->omask = 1; + memcpy(hdptr, ctx->omaskkey, 4); + hdptr += 4; + } + } + ctx->ostate = SEND_HEADER; + ctx->oheadermark = ctx->oheader; + ctx->oheaderlimit = hdptr; + ctx->opayloadlen = iocb->payload_length; + ctx->opayloadoff = 0; + } + if(ctx->ostate == SEND_HEADER) { + ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark; + ssize_t r; + int flags = 0; + if(iocb->data_length > 0) { + flags |= WSLAY_MSG_MORE; + }; + r = ctx->callbacks.send_callback(ctx->oheadermark, len, flags, + ctx->user_data); + if(r > 0) { + if(r > len) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->oheadermark += r; + if(ctx->oheadermark == ctx->oheaderlimit) { + ctx->ostate = SEND_PAYLOAD; + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + if(ctx->ostate == SEND_PAYLOAD) { + size_t totallen = 0; + if(iocb->data_length > 0) { + if(ctx->omask) { + uint8_t temp[4096]; + const uint8_t *datamark = iocb->data, + *datalimit = iocb->data+iocb->data_length; + while(datamark < datalimit) { + size_t datalen = datalimit - datamark; + const uint8_t *writelimit = datamark+ + wslay_min(sizeof(temp), datalen); + size_t writelen = writelimit-datamark; + ssize_t r; + size_t i; + for(i = 0; i < writelen; ++i) { + temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4]; + } + r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data); + if(r > 0) { + if((size_t)r > writelen) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + datamark += r; + ctx->opayloadoff += r; + totallen += r; + } + } else { + if(totallen > 0) { + break; + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } + } else { + ssize_t r; + r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0, + ctx->user_data); + if(r > 0) { + if((size_t)r > iocb->data_length) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->opayloadoff += r; + totallen = r; + } + } else { + return WSLAY_ERR_WANT_WRITE; + } + } + } + if(ctx->opayloadoff == ctx->opayloadlen) { + ctx->ostate = PREP_HEADER; + } + return totallen; + } + return WSLAY_ERR_INVALID_ARGUMENT; +} + +static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) +{ + ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark; + memmove(ctx->ibuf, ctx->ibufmark, len); + ctx->ibuflimit = ctx->ibuf+len; + ctx->ibufmark = ctx->ibuf; +} + +static ssize_t wslay_recv(wslay_frame_context_ptr ctx) +{ + ssize_t r; + if(ctx->ibufmark != ctx->ibuf) { + wslay_shift_ibuf(ctx); + } + r = ctx->callbacks.recv_callback + (ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit, + 0, ctx->user_data); + if(r > 0) { + ctx->ibuflimit += r; + } else { + r = WSLAY_ERR_WANT_READ; + } + return r; +} + +#define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark)) + +ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb) +{ + ssize_t r; + if(ctx->istate == RECV_HEADER1) { + uint8_t fin, opcode, rsv, payloadlen; + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + fin = (ctx->ibufmark[0] >> 7) & 1; + rsv = (ctx->ibufmark[0] >> 4) & 7; + opcode = ctx->ibufmark[0] & 0xfu; + ctx->iom.opcode = opcode; + ctx->iom.fin = fin; + ctx->iom.rsv = rsv; + ++ctx->ibufmark; + ctx->imask = (ctx->ibufmark[0] >> 7) & 1; + payloadlen = ctx->ibufmark[0] & 0x7fu; + ++ctx->ibufmark; + if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { + return WSLAY_ERR_PROTO; + } + if(payloadlen == 126) { + ctx->istate = RECV_EXT_PAYLOADLEN; + ctx->ireqread = 2; + } else if(payloadlen == 127) { + ctx->istate = RECV_EXT_PAYLOADLEN; + ctx->ireqread = 8; + } else { + ctx->ipayloadlen = payloadlen; + ctx->ipayloadoff = 0; + if(ctx->imask) { + ctx->istate = RECV_MASKKEY; + ctx->ireqread = 4; + } else { + ctx->istate = RECV_PAYLOAD; + } + } + } + if(ctx->istate == RECV_EXT_PAYLOADLEN) { + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + } + ctx->ipayloadlen = 0; + ctx->ipayloadoff = 0; + memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread), + ctx->ibufmark, ctx->ireqread); + ctx->ipayloadlen = ntoh64(ctx->ipayloadlen); + ctx->ibufmark += ctx->ireqread; + if(ctx->ireqread == 8) { + if(ctx->ipayloadlen < (1 << 16) || + ctx->ipayloadlen & (1ull << 63)) { + return WSLAY_ERR_PROTO; + } + } else if(ctx->ipayloadlen < 126) { + return WSLAY_ERR_PROTO; + } + if(ctx->imask) { + ctx->istate = RECV_MASKKEY; + ctx->ireqread = 4; + } else { + ctx->istate = RECV_PAYLOAD; + } + } + if(ctx->istate == RECV_MASKKEY) { + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + return WSLAY_ERR_WANT_READ; + } + } + memcpy(ctx->imaskkey, ctx->ibufmark, 4); + ctx->ibufmark += 4; + ctx->istate = RECV_PAYLOAD; + } + if(ctx->istate == RECV_PAYLOAD) { + uint8_t *readlimit, *readmark; + uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff; + if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { + if((r = wslay_recv(ctx)) <= 0) { + return r; + } + } + readmark = ctx->ibufmark; + readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ? + ctx->ibuflimit : ctx->ibufmark+rempayloadlen; + if(ctx->imask) { + for(; ctx->ibufmark != readlimit; + ++ctx->ibufmark, ++ctx->ipayloadoff) { + ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4]; + } + } else { + ctx->ibufmark = readlimit; + ctx->ipayloadoff += readlimit-readmark; + } + iocb->fin = ctx->iom.fin; + iocb->rsv = ctx->iom.rsv; + iocb->opcode = ctx->iom.opcode; + iocb->payload_length = ctx->ipayloadlen; + iocb->mask = ctx->imask; + iocb->data = readmark; + iocb->data_length = ctx->ibufmark-readmark; + if(ctx->ipayloadlen == ctx->ipayloadoff) { + ctx->istate = RECV_HEADER1; + ctx->ireqread = 2; + } + return iocb->data_length; + } + return WSLAY_ERR_INVALID_ARGUMENT; +} diff --git a/client/websocket/wslay/wslay_frame.h b/client/websocket/wslay/wslay_frame.h new file mode 100755 index 00000000..85f255ef --- /dev/null +++ b/client/websocket/wslay/wslay_frame.h @@ -0,0 +1,76 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_FRAME_H +#define WSLAY_FRAME_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include "wslay.h" + +enum wslay_frame_state { + PREP_HEADER, + SEND_HEADER, + SEND_PAYLOAD, + RECV_HEADER1, + RECV_PAYLOADLEN, + RECV_EXT_PAYLOADLEN, + RECV_MASKKEY, + RECV_PAYLOAD +}; + +struct wslay_frame_opcode_memo { + uint8_t fin; + uint8_t opcode; + uint8_t rsv; +}; + +struct wslay_frame_context { + uint8_t ibuf[4096]; + uint8_t *ibufmark; + uint8_t *ibuflimit; + struct wslay_frame_opcode_memo iom; + uint64_t ipayloadlen; + uint64_t ipayloadoff; + uint8_t imask; + uint8_t imaskkey[4]; + enum wslay_frame_state istate; + size_t ireqread; + + uint8_t oheader[14]; + uint8_t *oheadermark; + uint8_t *oheaderlimit; + uint64_t opayloadlen; + uint64_t opayloadoff; + uint8_t omask; + uint8_t omaskkey[4]; + enum wslay_frame_state ostate; + + struct wslay_frame_callbacks callbacks; + void *user_data; +}; + +#endif /* WSLAY_FRAME_H */ diff --git a/client/websocket/wslay/wslay_net.c b/client/websocket/wslay/wslay_net.c new file mode 100755 index 00000000..d3867c21 --- /dev/null +++ b/client/websocket/wslay/wslay_net.c @@ -0,0 +1,36 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "wslay_net.h" + +#ifndef WORDS_BIGENDIAN + +uint64_t wslay_byteswap64(uint64_t x) +{ + uint64_t u = ntohl(x & 0xffffffffllu); + uint64_t l = ntohl(x >> 32); + return (u << 32) | l; +} + +#endif /* !WORDS_BIGENDIAN */ diff --git a/client/websocket/wslay/wslay_net.h b/client/websocket/wslay/wslay_net.h new file mode 100755 index 00000000..60689838 --- /dev/null +++ b/client/websocket/wslay/wslay_net.h @@ -0,0 +1,54 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_NET_H +#define WSLAY_NET_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include "wslay.h" + +#ifdef HAVE_ARPA_INET_H +# include +#endif /* HAVE_ARPA_INET_H */ +#ifdef HAVE_NETINET_IN_H +# include +#endif /* HAVE_NETINET_IN_H */ +/* For Mingw build */ +#ifdef HAVE_WINSOCK2_H +# include +#endif /* HAVE_WINSOCK2_H */ + +#ifdef WORDS_BIGENDIAN +# define ntoh64(x) (x) +# define hton64(x) (x) +#else /* !WORDS_BIGENDIAN */ +uint64_t wslay_byteswap64(uint64_t x); +# define ntoh64(x) wslay_byteswap64(x) +# define hton64(x) wslay_byteswap64(x) +#endif /* !WORDS_BIGENDIAN */ + +#endif /* WSLAY_NET_H */ diff --git a/client/websocket/wslay/wslay_queue.c b/client/websocket/wslay/wslay_queue.c new file mode 100755 index 00000000..8d266968 --- /dev/null +++ b/client/websocket/wslay/wslay_queue.c @@ -0,0 +1,117 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "wslay_queue.h" + +#include +#include + +struct wslay_queue* wslay_queue_new(void) +{ + struct wslay_queue *queue = (struct wslay_queue*)malloc + (sizeof(struct wslay_queue)); + if(!queue) { + return NULL; + } + queue->top = queue->tail = NULL; + return queue; +} + +void wslay_queue_free(struct wslay_queue *queue) +{ + if(!queue) { + return; + } else { + struct wslay_queue_cell *p = queue->top; + while(p) { + struct wslay_queue_cell *next = p->next; + free(p); + p = next; + } + free(queue); + } +} + +int wslay_queue_push(struct wslay_queue *queue, void *data) +{ + struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc + (sizeof(struct wslay_queue_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = NULL; + if(queue->tail) { + queue->tail->next = new_cell; + queue->tail = new_cell; + + } else { + queue->top = queue->tail = new_cell; + } + return 0; +} + +int wslay_queue_push_front(struct wslay_queue *queue, void *data) +{ + struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc + (sizeof(struct wslay_queue_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = queue->top; + queue->top = new_cell; + if(!queue->tail) { + queue->tail = queue->top; + } + return 0; +} + +void wslay_queue_pop(struct wslay_queue *queue) +{ + struct wslay_queue_cell *top = queue->top; + assert(top); + queue->top = top->next; + if(top == queue->tail) { + queue->tail = NULL; + } + free(top); +} + +void* wslay_queue_top(struct wslay_queue *queue) +{ + assert(queue->top); + return queue->top->data; +} + +void* wslay_queue_tail(struct wslay_queue *queue) +{ + assert(queue->tail); + return queue->tail->data; +} + +int wslay_queue_empty(struct wslay_queue *queue) +{ + return queue->top == NULL; +} diff --git a/client/websocket/wslay/wslay_queue.h b/client/websocket/wslay/wslay_queue.h new file mode 100755 index 00000000..567e0a37 --- /dev/null +++ b/client/websocket/wslay/wslay_queue.h @@ -0,0 +1,53 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_QUEUE_H +#define WSLAY_QUEUE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "wslay.h" + +struct wslay_queue_cell { + void *data; + struct wslay_queue_cell *next; +}; + +struct wslay_queue { + struct wslay_queue_cell *top; + struct wslay_queue_cell *tail; +}; + +struct wslay_queue* wslay_queue_new(void); +void wslay_queue_free(struct wslay_queue *queue); +int wslay_queue_push(struct wslay_queue *queue, void *data); +int wslay_queue_push_front(struct wslay_queue *queue, void *data); +void wslay_queue_pop(struct wslay_queue *queue); +void* wslay_queue_top(struct wslay_queue *queue); +void* wslay_queue_tail(struct wslay_queue *queue); +int wslay_queue_empty(struct wslay_queue *queue); + +#endif /* WSLAY_QUEUE_H */ diff --git a/client/websocket/wslay/wslay_stack.c b/client/websocket/wslay/wslay_stack.c new file mode 100755 index 00000000..0e05d740 --- /dev/null +++ b/client/websocket/wslay/wslay_stack.c @@ -0,0 +1,86 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "wslay_stack.h" + +#include +#include + +struct wslay_stack* wslay_stack_new() +{ + struct wslay_stack *stack = (struct wslay_stack*)malloc + (sizeof(struct wslay_stack)); + if(!stack) { + return NULL; + } + stack->top = NULL; + return stack; +} + +void wslay_stack_free(struct wslay_stack *stack) +{ + struct wslay_stack_cell *p; + if(!stack) { + return; + } + p = stack->top; + while(p) { + struct wslay_stack_cell *next = p->next; + free(p); + p = next; + } + free(stack); +} + +int wslay_stack_push(struct wslay_stack *stack, void *data) +{ + struct wslay_stack_cell *new_cell = (struct wslay_stack_cell*)malloc + (sizeof(struct wslay_stack_cell)); + if(!new_cell) { + return WSLAY_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = stack->top; + stack->top = new_cell; + return 0; +} + +void wslay_stack_pop(struct wslay_stack *stack) +{ + struct wslay_stack_cell *top = stack->top; + assert(top); + stack->top = top->next; + free(top); +} + +void* wslay_stack_top(struct wslay_stack *stack) +{ + assert(stack->top); + return stack->top->data; +} + +int wslay_stack_empty(struct wslay_stack *stack) +{ + return stack->top == NULL; +} diff --git a/client/websocket/wslay/wslay_stack.h b/client/websocket/wslay/wslay_stack.h new file mode 100755 index 00000000..2b3b932a --- /dev/null +++ b/client/websocket/wslay/wslay_stack.h @@ -0,0 +1,50 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAY_STACK_H +#define WSLAY_STACK_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "wslay.h" + +struct wslay_stack_cell { + void *data; + struct wslay_stack_cell *next; +}; + +struct wslay_stack { + struct wslay_stack_cell *top; +}; + +struct wslay_stack* wslay_stack_new(); +void wslay_stack_free(struct wslay_stack *stack); +int wslay_stack_push(struct wslay_stack *stack, void *data); +void wslay_stack_pop(struct wslay_stack *stack); +void* wslay_stack_top(struct wslay_stack *stack); +int wslay_stack_empty(struct wslay_stack *stack); + +#endif /* WSLAY_STACK_H */ diff --git a/client/websocket/wslay/wslayver.h b/client/websocket/wslay/wslayver.h new file mode 100644 index 00000000..0a93390d --- /dev/null +++ b/client/websocket/wslay/wslayver.h @@ -0,0 +1,31 @@ +/* + * Wslay - The WebSocket Library + * + * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef WSLAYVER_H +#define WSLAYVER_H + +/* Version number of wslay release */ +#define WSLAY_VERSION "1.1.1-DEV" + +#endif /* WSLAYVER_H */ diff --git a/mac/xdag.xcodeproj/project.pbxproj b/mac/xdag.xcodeproj/project.pbxproj index e558ee36..399e2d8f 100644 --- a/mac/xdag.xcodeproj/project.pbxproj +++ b/mac/xdag.xcodeproj/project.pbxproj @@ -7,70 +7,85 @@ objects = { /* Begin PBXBuildFile section */ - 380AAA94211B6DA50090A5A4 /* dnet_crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 380AAA8A211B6DA40090A5A4 /* dnet_crypt.c */; }; - 380AAA96211B6DA50090A5A4 /* dnet_xdag.c in Sources */ = {isa = PBXBuildFile; fileRef = 380AAA90211B6DA40090A5A4 /* dnet_xdag.c */; }; + 385EB84221D3D64200287D2B /* address.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7A721D3D64200287D2B /* address.c */; }; + 385EB84321D3D64200287D2B /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7AA21D3D64200287D2B /* crc.c */; }; 382A4FF621DE73C900209951 /* netdb-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABB221D2BD9F00252F71 /* netdb-testnet.txt */; }; 382A4FF721DE73C900209951 /* netdb-white-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABB321D2BD9F00252F71 /* netdb-white-testnet.txt */; }; 382A4FF821DE73C900209951 /* netdb-white.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABB421D2BD9F00252F71 /* netdb-white.txt */; }; 382A4FF921DE73C900209951 /* netdb.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABB721D2BD9F00252F71 /* netdb.txt */; }; 382A4FFA21DE73C900209951 /* pools-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABBC21D2BD9F00252F71 /* pools-testnet.txt */; }; 382A4FFB21DE73C900209951 /* pools.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3845ABBD21D2BD9F00252F71 /* pools.txt */; }; - 384457BC21233982008BBBBD /* dnet_keys.bin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 380AAA8D211B6DA40090A5A4 /* dnet_keys.bin */; }; - 3845AB5F21D2BC1000252F71 /* dfslib_crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB5621D2BC1000252F71 /* dfslib_crypt.c */; }; - 3845AB6021D2BC1000252F71 /* dfslib_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB5821D2BC1000252F71 /* dfslib_random.c */; }; - 3845AB6121D2BC1000252F71 /* dfslib_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB5A21D2BC1000252F71 /* dfslib_string.c */; }; - 3845AB6221D2BC1000252F71 /* dfsrsa.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB5D21D2BC1000252F71 /* dfsrsa.c */; }; - 3845ABEB21D2BD9F00252F71 /* address.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB7B21D2BD9F00252F71 /* address.c */; }; - 3845ABEC21D2BD9F00252F71 /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB7E21D2BD9F00252F71 /* crc.c */; }; - 3845ABED21D2BD9F00252F71 /* sha256-mb-x86_64-mac.s in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8021D2BD9F00252F71 /* sha256-mb-x86_64-mac.s */; }; - 3845ABEF21D2BD9F00252F71 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8221D2BD9F00252F71 /* sha256.c */; }; - 3845ABF121D2BD9F00252F71 /* block.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8521D2BD9F00252F71 /* block.c */; }; - 3845ABF321D2BD9F00252F71 /* commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8821D2BD9F00252F71 /* commands.c */; }; - 3845ABF421D2BD9F00252F71 /* crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8A21D2BD9F00252F71 /* crypt.c */; }; - 3845ABF621D2BD9F00252F71 /* example.pool.config in Resources */ = {isa = PBXBuildFile; fileRef = 3845AB8D21D2BD9F00252F71 /* example.pool.config */; }; - 3845ABF721D2BD9F00252F71 /* global.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB8E21D2BD9F00252F71 /* global.c */; }; - 3845ABF821D2BD9F00252F71 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9021D2BD9F00252F71 /* hash.c */; }; - 3845ABF921D2BD9F00252F71 /* http.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9321D2BD9F00252F71 /* http.c */; }; - 3845ABFA21D2BD9F00252F71 /* url.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9521D2BD9F00252F71 /* url.c */; }; - 3845ABFB21D2BD9F00252F71 /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9721D2BD9F00252F71 /* init.c */; }; - 3845ABFC21D2BD9F00252F71 /* cJSON.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9A21D2BD9F00252F71 /* cJSON.c */; }; - 3845ABFD21D2BD9F00252F71 /* cJSON_Utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9C21D2BD9F00252F71 /* cJSON_Utils.c */; }; - 3845ABFE21D2BD9F00252F71 /* rpc_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AB9E21D2BD9F00252F71 /* rpc_commands.c */; }; - 3845ABFF21D2BD9F00252F71 /* rpc_procedure.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA021D2BD9F00252F71 /* rpc_procedure.c */; }; - 3845AC0021D2BD9F00252F71 /* rpc_procedures.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA221D2BD9F00252F71 /* rpc_procedures.c */; }; - 3845AC0121D2BD9F00252F71 /* rpc_service.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA421D2BD9F00252F71 /* rpc_service.c */; }; - 3845AC0221D2BD9F00252F71 /* rpc_wrapper.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA621D2BD9F00252F71 /* rpc_wrapper.c */; }; - 3845AC0321D2BD9F00252F71 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA821D2BD9F00252F71 /* main.c */; }; - 3845AC0421D2BD9F00252F71 /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABA921D2BD9F00252F71 /* Makefile */; }; - 3845AC0521D2BD9F00252F71 /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABAA21D2BD9F00252F71 /* math.c */; }; - 3845AC0621D2BD9F00252F71 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABAC21D2BD9F00252F71 /* memory.c */; }; - 3845AC0721D2BD9F00252F71 /* miner.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABAE21D2BD9F00252F71 /* miner.c */; }; - 3845AC0821D2BD9F00252F71 /* mining_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABB021D2BD9F00252F71 /* mining_common.c */; }; - 3845AC0921D2BD9F00252F71 /* netdb-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABB221D2BD9F00252F71 /* netdb-testnet.txt */; }; - 3845AC0A21D2BD9F00252F71 /* netdb-white-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABB321D2BD9F00252F71 /* netdb-white-testnet.txt */; }; - 3845AC0B21D2BD9F00252F71 /* netdb-white.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABB421D2BD9F00252F71 /* netdb-white.txt */; }; - 3845AC0C21D2BD9F00252F71 /* netdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABB521D2BD9F00252F71 /* netdb.c */; }; - 3845AC0D21D2BD9F00252F71 /* netdb.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABB721D2BD9F00252F71 /* netdb.txt */; }; - 3845AC0E21D2BD9F00252F71 /* network.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABB821D2BD9F00252F71 /* network.c */; }; - 3845AC0F21D2BD9F00252F71 /* pool.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABBA21D2BD9F00252F71 /* pool.c */; }; - 3845AC1021D2BD9F00252F71 /* pools-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABBC21D2BD9F00252F71 /* pools-testnet.txt */; }; - 3845AC1121D2BD9F00252F71 /* pools.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3845ABBD21D2BD9F00252F71 /* pools.txt */; }; - 3845AC1321D2BD9F00252F71 /* storage.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABC421D2BD9F00252F71 /* storage.c */; }; - 3845AC1421D2BD9F00252F71 /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABC621D2BD9F00252F71 /* sync.c */; }; - 3845AC1521D2BD9F00252F71 /* terminal.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABC921D2BD9F00252F71 /* terminal.c */; }; - 3845AC1621D2BD9F00252F71 /* time.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABCB21D2BD9F00252F71 /* time.c */; }; - 3845AC1721D2BD9F00252F71 /* transport.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABCD21D2BD9F00252F71 /* transport.c */; }; - 3845AC1821D2BD9F00252F71 /* atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABD421D2BD9F00252F71 /* atomic.c */; }; - 3845AC1921D2BD9F00252F71 /* dirname.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABD621D2BD9F00252F71 /* dirname.c */; }; - 3845AC1A21D2BD9F00252F71 /* linenoise.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABD821D2BD9F00252F71 /* linenoise.c */; }; - 3845AC1B21D2BD9F00252F71 /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABDA21D2BD9F00252F71 /* log.c */; }; - 3845AC1C21D2BD9F00252F71 /* moving_average.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABDD21D2BD9F00252F71 /* moving_average.c */; }; - 3845AC1D21D2BD9F00252F71 /* string_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABDF21D2BD9F00252F71 /* string_utils.c */; }; - 3845AC1E21D2BD9F00252F71 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABE121D2BD9F00252F71 /* utils.c */; }; - 3845AC1F21D2BD9F00252F71 /* wallet.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABE421D2BD9F00252F71 /* wallet.c */; }; - 3845AC2021D2BD9F00252F71 /* x86_64cpuid-mac.s in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABE721D2BD9F00252F71 /* x86_64cpuid-mac.s */; }; - 3845AC2221D2BD9F00252F71 /* xdag_config.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845ABE921D2BD9F00252F71 /* xdag_config.c */; }; - 3845AC2621D2C36100252F71 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = 3845AC2421D2C36100252F71 /* random.c */; }; + 385EB84421D3D64200287D2B /* sha256-mb-x86_64-mac.s in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7AC21D3D64200287D2B /* sha256-mb-x86_64-mac.s */; }; + 385EB84621D3D64200287D2B /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7AE21D3D64200287D2B /* sha256.c */; }; + 385EB84821D3D64200287D2B /* block.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7B121D3D64200287D2B /* block.c */; }; + 385EB84A21D3D64200287D2B /* commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7B421D3D64200287D2B /* commands.c */; }; + 385EB84B21D3D64200287D2B /* crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7B621D3D64200287D2B /* crypt.c */; }; + 385EB84D21D3D64200287D2B /* example.pool.config in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7B921D3D64200287D2B /* example.pool.config */; }; + 385EB84E21D3D64200287D2B /* global.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7BA21D3D64200287D2B /* global.c */; }; + 385EB84F21D3D64200287D2B /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7BC21D3D64200287D2B /* hash.c */; }; + 385EB85021D3D64200287D2B /* http.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7BF21D3D64200287D2B /* http.c */; }; + 385EB85121D3D64200287D2B /* url.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7C121D3D64200287D2B /* url.c */; }; + 385EB85221D3D64200287D2B /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7C321D3D64200287D2B /* init.c */; }; + 385EB85321D3D64200287D2B /* cJSON.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7C621D3D64200287D2B /* cJSON.c */; }; + 385EB85421D3D64200287D2B /* cJSON_Utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7C821D3D64200287D2B /* cJSON_Utils.c */; }; + 385EB85521D3D64200287D2B /* rpc_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7CA21D3D64200287D2B /* rpc_commands.c */; }; + 385EB85621D3D64200287D2B /* rpc_procedure.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7CC21D3D64200287D2B /* rpc_procedure.c */; }; + 385EB85721D3D64200287D2B /* rpc_procedures.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7CE21D3D64200287D2B /* rpc_procedures.c */; }; + 385EB85821D3D64200287D2B /* rpc_service.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7D021D3D64200287D2B /* rpc_service.c */; }; + 385EB85921D3D64200287D2B /* rpc_wrapper.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7D221D3D64200287D2B /* rpc_wrapper.c */; }; + 385EB85A21D3D64200287D2B /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7D421D3D64200287D2B /* main.c */; }; + 385EB85C21D3D64200287D2B /* math.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7D621D3D64200287D2B /* math.c */; }; + 385EB85D21D3D64200287D2B /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7D821D3D64200287D2B /* memory.c */; }; + 385EB85E21D3D64200287D2B /* miner.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7DA21D3D64200287D2B /* miner.c */; }; + 385EB85F21D3D64200287D2B /* mining_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7DC21D3D64200287D2B /* mining_common.c */; }; + 385EB86021D3D64200287D2B /* netdb-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7DE21D3D64200287D2B /* netdb-testnet.txt */; }; + 385EB86121D3D64200287D2B /* netdb-white-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7DF21D3D64200287D2B /* netdb-white-testnet.txt */; }; + 385EB86221D3D64200287D2B /* netdb-white.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7E021D3D64200287D2B /* netdb-white.txt */; }; + 385EB86321D3D64200287D2B /* netdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7E121D3D64200287D2B /* netdb.c */; }; + 385EB86421D3D64200287D2B /* netdb.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7E321D3D64200287D2B /* netdb.txt */; }; + 385EB86521D3D64200287D2B /* network.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7E421D3D64200287D2B /* network.c */; }; + 385EB86621D3D64200287D2B /* pool.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7E621D3D64200287D2B /* pool.c */; }; + 385EB86721D3D64200287D2B /* pools-testnet.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7E821D3D64200287D2B /* pools-testnet.txt */; }; + 385EB86821D3D64200287D2B /* pools.txt in Resources */ = {isa = PBXBuildFile; fileRef = 385EB7E921D3D64200287D2B /* pools.txt */; }; + 385EB86A21D3D64200287D2B /* storage.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7F021D3D64200287D2B /* storage.c */; }; + 385EB86B21D3D64200287D2B /* sync.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7F221D3D64200287D2B /* sync.c */; }; + 385EB86C21D3D64200287D2B /* terminal.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7F521D3D64200287D2B /* terminal.c */; }; + 385EB86D21D3D64200287D2B /* time.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7F721D3D64200287D2B /* time.c */; }; + 385EB86E21D3D64200287D2B /* transport.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB7F921D3D64200287D2B /* transport.c */; }; + 385EB86F21D3D64200287D2B /* atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80021D3D64200287D2B /* atomic.c */; }; + 385EB87021D3D64200287D2B /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80221D3D64200287D2B /* base64.c */; }; + 385EB87121D3D64200287D2B /* dirname.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80421D3D64200287D2B /* dirname.c */; }; + 385EB87221D3D64200287D2B /* linenoise.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80621D3D64200287D2B /* linenoise.c */; }; + 385EB87321D3D64200287D2B /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80821D3D64200287D2B /* log.c */; }; + 385EB87421D3D64200287D2B /* moving_average.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80B21D3D64200287D2B /* moving_average.c */; }; + 385EB87521D3D64200287D2B /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80D21D3D64200287D2B /* random.c */; }; + 385EB87621D3D64200287D2B /* string_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB80F21D3D64200287D2B /* string_utils.c */; }; + 385EB87721D3D64200287D2B /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB81121D3D64200287D2B /* utils.c */; }; + 385EB87821D3D64200287D2B /* uuid.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB81321D3D64200287D2B /* uuid.c */; }; + 385EB87921D3D64200287D2B /* wallet.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB81621D3D64200287D2B /* wallet.c */; }; + 385EB87A21D3D64200287D2B /* websocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB81921D3D64200287D2B /* websocket.c */; }; + 385EB87B21D3D64200287D2B /* wslay_event.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB81E21D3D64200287D2B /* wslay_event.c */; }; + 385EB87C21D3D64200287D2B /* wslay_frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82021D3D64200287D2B /* wslay_frame.c */; }; + 385EB87D21D3D64200287D2B /* wslay_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82221D3D64200287D2B /* wslay_net.c */; }; + 385EB87E21D3D64200287D2B /* wslay_queue.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82421D3D64200287D2B /* wslay_queue.c */; }; + 385EB87F21D3D64200287D2B /* wslay_stack.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82621D3D64200287D2B /* wslay_stack.c */; }; + 385EB88021D3D64200287D2B /* x86_64cpuid-mac.s in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82921D3D64200287D2B /* x86_64cpuid-mac.s */; }; + 385EB88221D3D64200287D2B /* xdag_config.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82B21D3D64200287D2B /* xdag_config.c */; }; + 385EB88321D3D64200287D2B /* dfslib_crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB82E21D3D64200287D2B /* dfslib_crypt.c */; }; + 385EB88421D3D64200287D2B /* dfslib_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB83021D3D64200287D2B /* dfslib_random.c */; }; + 385EB88521D3D64200287D2B /* dfslib_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB83221D3D64200287D2B /* dfslib_string.c */; }; + 385EB88621D3D64200287D2B /* dfsrsa.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB83521D3D64200287D2B /* dfsrsa.c */; }; + 385EB88721D3D64200287D2B /* dnet_crypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB83821D3D64200287D2B /* dnet_crypt.c */; }; + 385EB88921D3D64200287D2B /* dnet_xdag.c in Sources */ = {isa = PBXBuildFile; fileRef = 385EB83F21D3D64200287D2B /* dnet_xdag.c */; }; + 385EB88B21D3D76100287D2B /* dnet_keys.bin in Resources */ = {isa = PBXBuildFile; fileRef = 385EB83B21D3D64200287D2B /* dnet_keys.bin */; }; + 385EB88C21D3D83800287D2B /* dnet_keys.bin in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB83B21D3D64200287D2B /* dnet_keys.bin */; }; + 385EB88D21D3D84000287D2B /* example.pool.config in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7B921D3D64200287D2B /* example.pool.config */; }; + 385EB88E21D3D84000287D2B /* pools-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7E821D3D64200287D2B /* pools-testnet.txt */; }; + 385EB88F21D3D84000287D2B /* pools.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7E921D3D64200287D2B /* pools.txt */; }; + 385EB89021D3D84900287D2B /* netdb-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7DE21D3D64200287D2B /* netdb-testnet.txt */; }; + 385EB89121D3D84900287D2B /* netdb-white-testnet.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7DF21D3D64200287D2B /* netdb-white-testnet.txt */; }; + 385EB89221D3D84900287D2B /* netdb-white.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7E021D3D64200287D2B /* netdb-white.txt */; }; + 385EB89321D3D84900287D2B /* netdb.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 385EB7E321D3D64200287D2B /* netdb.txt */; }; 418AAFF6213BB3A900E96520 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 418AAFF5213BB3A900E96520 /* libcrypto.a */; }; 418AAFF8213BB3B300E96520 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 418AAFF7213BB3B300E96520 /* libssl.a */; }; /* End PBXBuildFile section */ @@ -82,136 +97,155 @@ dstPath = .; dstSubfolderSpec = 6; files = ( - 382A4FF621DE73C900209951 /* netdb-testnet.txt in CopyFiles */, - 382A4FF721DE73C900209951 /* netdb-white-testnet.txt in CopyFiles */, - 382A4FF821DE73C900209951 /* netdb-white.txt in CopyFiles */, - 382A4FF921DE73C900209951 /* netdb.txt in CopyFiles */, - 382A4FFA21DE73C900209951 /* pools-testnet.txt in CopyFiles */, - 382A4FFB21DE73C900209951 /* pools.txt in CopyFiles */, - 384457BC21233982008BBBBD /* dnet_keys.bin in CopyFiles */, + 385EB89021D3D84900287D2B /* netdb-testnet.txt in CopyFiles */, + 385EB89121D3D84900287D2B /* netdb-white-testnet.txt in CopyFiles */, + 385EB89221D3D84900287D2B /* netdb-white.txt in CopyFiles */, + 385EB89321D3D84900287D2B /* netdb.txt in CopyFiles */, + 385EB88D21D3D84000287D2B /* example.pool.config in CopyFiles */, + 385EB88E21D3D84000287D2B /* pools-testnet.txt in CopyFiles */, + 385EB88F21D3D84000287D2B /* pools.txt in CopyFiles */, + 385EB88C21D3D83800287D2B /* dnet_keys.bin in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 380AAA8A211B6DA40090A5A4 /* dnet_crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnet_crypt.c; sourceTree = ""; }; - 380AAA8B211B6DA40090A5A4 /* dnet_crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_crypt.h; sourceTree = ""; }; - 380AAA8C211B6DA40090A5A4 /* dnet_history.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_history.h; sourceTree = ""; }; - 380AAA8D211B6DA40090A5A4 /* dnet_keys.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = dnet_keys.bin; sourceTree = ""; }; - 380AAA8E211B6DA40090A5A4 /* dnet_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_main.h; sourceTree = ""; }; - 380AAA8F211B6DA40090A5A4 /* dnet_packet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_packet.h; sourceTree = ""; }; - 380AAA90211B6DA40090A5A4 /* dnet_xdag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnet_xdag.c; sourceTree = ""; }; - 3845AB5221D2BC1000252F71 /* atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomic.h; sourceTree = ""; }; - 3845AB5321D2BC1000252F71 /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = ""; }; - 3845AB5421D2BC1000252F71 /* rbtree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rbtree.h; sourceTree = ""; }; - 3845AB5621D2BC1000252F71 /* dfslib_crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_crypt.c; sourceTree = ""; }; - 3845AB5721D2BC1000252F71 /* dfslib_crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_crypt.h; sourceTree = ""; }; - 3845AB5821D2BC1000252F71 /* dfslib_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_random.c; sourceTree = ""; }; - 3845AB5921D2BC1000252F71 /* dfslib_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_random.h; sourceTree = ""; }; - 3845AB5A21D2BC1000252F71 /* dfslib_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_string.c; sourceTree = ""; }; - 3845AB5B21D2BC1000252F71 /* dfslib_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_string.h; sourceTree = ""; }; - 3845AB5C21D2BC1000252F71 /* dfslib_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_types.h; sourceTree = ""; }; - 3845AB5D21D2BC1000252F71 /* dfsrsa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfsrsa.c; sourceTree = ""; }; - 3845AB5E21D2BC1000252F71 /* dfsrsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfsrsa.h; sourceTree = ""; }; - 3845AB7B21D2BD9F00252F71 /* address.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = address.c; sourceTree = ""; }; - 3845AB7C21D2BD9F00252F71 /* address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = address.h; sourceTree = ""; }; - 3845AB7E21D2BD9F00252F71 /* crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc.c; sourceTree = ""; }; - 3845AB7F21D2BD9F00252F71 /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; - 3845AB8021D2BD9F00252F71 /* sha256-mb-x86_64-mac.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "sha256-mb-x86_64-mac.s"; sourceTree = ""; }; - 3845AB8221D2BD9F00252F71 /* sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha256.c; sourceTree = ""; }; - 3845AB8321D2BD9F00252F71 /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha256.h; sourceTree = ""; }; - 3845AB8521D2BD9F00252F71 /* block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = block.c; sourceTree = ""; }; - 3845AB8721D2BD9F00252F71 /* block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = block.h; sourceTree = ""; }; - 3845AB8821D2BD9F00252F71 /* commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = commands.c; sourceTree = ""; }; - 3845AB8921D2BD9F00252F71 /* commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commands.h; sourceTree = ""; }; - 3845AB8A21D2BD9F00252F71 /* crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crypt.c; sourceTree = ""; }; - 3845AB8B21D2BD9F00252F71 /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; - 3845AB8D21D2BD9F00252F71 /* example.pool.config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = example.pool.config; sourceTree = ""; }; - 3845AB8E21D2BD9F00252F71 /* global.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = global.c; sourceTree = ""; }; - 3845AB8F21D2BD9F00252F71 /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = global.h; sourceTree = ""; }; - 3845AB9021D2BD9F00252F71 /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hash.c; sourceTree = ""; }; - 3845AB9121D2BD9F00252F71 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; - 3845AB9321D2BD9F00252F71 /* http.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = http.c; sourceTree = ""; }; - 3845AB9421D2BD9F00252F71 /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = ""; }; - 3845AB9521D2BD9F00252F71 /* url.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = url.c; sourceTree = ""; }; - 3845AB9621D2BD9F00252F71 /* url.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = url.h; sourceTree = ""; }; - 3845AB9721D2BD9F00252F71 /* init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = init.c; sourceTree = ""; }; - 3845AB9821D2BD9F00252F71 /* init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = init.h; sourceTree = ""; }; - 3845AB9A21D2BD9F00252F71 /* cJSON.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cJSON.c; sourceTree = ""; }; - 3845AB9B21D2BD9F00252F71 /* cJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cJSON.h; sourceTree = ""; }; - 3845AB9C21D2BD9F00252F71 /* cJSON_Utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cJSON_Utils.c; sourceTree = ""; }; - 3845AB9D21D2BD9F00252F71 /* cJSON_Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cJSON_Utils.h; sourceTree = ""; }; - 3845AB9E21D2BD9F00252F71 /* rpc_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_commands.c; sourceTree = ""; }; - 3845AB9F21D2BD9F00252F71 /* rpc_commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_commands.h; sourceTree = ""; }; - 3845ABA021D2BD9F00252F71 /* rpc_procedure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_procedure.c; sourceTree = ""; }; - 3845ABA121D2BD9F00252F71 /* rpc_procedure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_procedure.h; sourceTree = ""; }; - 3845ABA221D2BD9F00252F71 /* rpc_procedures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_procedures.c; sourceTree = ""; }; - 3845ABA321D2BD9F00252F71 /* rpc_procedures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_procedures.h; sourceTree = ""; }; - 3845ABA421D2BD9F00252F71 /* rpc_service.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_service.c; sourceTree = ""; }; - 3845ABA521D2BD9F00252F71 /* rpc_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_service.h; sourceTree = ""; }; - 3845ABA621D2BD9F00252F71 /* rpc_wrapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_wrapper.c; sourceTree = ""; }; - 3845ABA721D2BD9F00252F71 /* rpc_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_wrapper.h; sourceTree = ""; }; - 3845ABA821D2BD9F00252F71 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; - 3845ABA921D2BD9F00252F71 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - 3845ABAA21D2BD9F00252F71 /* math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = math.c; sourceTree = ""; }; - 3845ABAB21D2BD9F00252F71 /* math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = math.h; sourceTree = ""; }; - 3845ABAC21D2BD9F00252F71 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = ""; }; - 3845ABAD21D2BD9F00252F71 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = ""; }; - 3845ABAE21D2BD9F00252F71 /* miner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = miner.c; sourceTree = ""; }; - 3845ABAF21D2BD9F00252F71 /* miner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = miner.h; sourceTree = ""; }; - 3845ABB021D2BD9F00252F71 /* mining_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mining_common.c; sourceTree = ""; }; - 3845ABB121D2BD9F00252F71 /* mining_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mining_common.h; sourceTree = ""; }; - 3845ABB221D2BD9F00252F71 /* netdb-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-testnet.txt"; sourceTree = ""; }; - 3845ABB321D2BD9F00252F71 /* netdb-white-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-white-testnet.txt"; sourceTree = ""; }; - 3845ABB421D2BD9F00252F71 /* netdb-white.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-white.txt"; sourceTree = ""; }; - 3845ABB521D2BD9F00252F71 /* netdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = netdb.c; sourceTree = ""; }; - 3845ABB621D2BD9F00252F71 /* netdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = netdb.h; sourceTree = ""; }; - 3845ABB721D2BD9F00252F71 /* netdb.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = netdb.txt; sourceTree = ""; }; - 3845ABB821D2BD9F00252F71 /* network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = network.c; sourceTree = ""; }; - 3845ABB921D2BD9F00252F71 /* network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = network.h; sourceTree = ""; }; - 3845ABBA21D2BD9F00252F71 /* pool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pool.c; sourceTree = ""; }; - 3845ABBB21D2BD9F00252F71 /* pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pool.h; sourceTree = ""; }; - 3845ABBC21D2BD9F00252F71 /* pools-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pools-testnet.txt"; sourceTree = ""; }; - 3845ABBD21D2BD9F00252F71 /* pools.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pools.txt; sourceTree = ""; }; - 3845ABBE21D2BD9F00252F71 /* state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = state.h; sourceTree = ""; }; - 3845ABC421D2BD9F00252F71 /* storage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = storage.c; sourceTree = ""; }; - 3845ABC521D2BD9F00252F71 /* storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = storage.h; sourceTree = ""; }; - 3845ABC621D2BD9F00252F71 /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = ""; }; - 3845ABC721D2BD9F00252F71 /* sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sync.h; sourceTree = ""; }; - 3845ABC821D2BD9F00252F71 /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system.h; sourceTree = ""; }; - 3845ABC921D2BD9F00252F71 /* terminal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = terminal.c; sourceTree = ""; }; - 3845ABCA21D2BD9F00252F71 /* terminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = terminal.h; sourceTree = ""; }; - 3845ABCB21D2BD9F00252F71 /* time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = time.c; sourceTree = ""; }; - 3845ABCC21D2BD9F00252F71 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; - 3845ABCD21D2BD9F00252F71 /* transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = transport.c; sourceTree = ""; }; - 3845ABCE21D2BD9F00252F71 /* transport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transport.h; sourceTree = ""; }; - 3845ABCF21D2BD9F00252F71 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; - 3845ABD121D2BD9F00252F71 /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uthash.h; sourceTree = ""; }; - 3845ABD221D2BD9F00252F71 /* utlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utlist.h; sourceTree = ""; }; - 3845ABD421D2BD9F00252F71 /* atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atomic.c; sourceTree = ""; }; - 3845ABD521D2BD9F00252F71 /* atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomic.h; sourceTree = ""; }; - 3845ABD621D2BD9F00252F71 /* dirname.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dirname.c; sourceTree = ""; }; - 3845ABD721D2BD9F00252F71 /* dirname.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirname.h; sourceTree = ""; }; - 3845ABD821D2BD9F00252F71 /* linenoise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = linenoise.c; sourceTree = ""; }; - 3845ABD921D2BD9F00252F71 /* linenoise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linenoise.h; sourceTree = ""; }; - 3845ABDA21D2BD9F00252F71 /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = ""; }; - 3845ABDB21D2BD9F00252F71 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; - 3845ABDD21D2BD9F00252F71 /* moving_average.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = moving_average.c; sourceTree = ""; }; - 3845ABDE21D2BD9F00252F71 /* moving_average.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moving_average.h; sourceTree = ""; }; - 3845ABDF21D2BD9F00252F71 /* string_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = string_utils.c; sourceTree = ""; }; - 3845ABE021D2BD9F00252F71 /* string_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_utils.h; sourceTree = ""; }; - 3845ABE121D2BD9F00252F71 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; }; - 3845ABE221D2BD9F00252F71 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; - 3845ABE321D2BD9F00252F71 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - 3845ABE421D2BD9F00252F71 /* wallet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wallet.c; sourceTree = ""; }; - 3845ABE521D2BD9F00252F71 /* wallet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wallet.h; sourceTree = ""; }; - 3845ABE721D2BD9F00252F71 /* x86_64cpuid-mac.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "x86_64cpuid-mac.s"; sourceTree = ""; }; - 3845ABE921D2BD9F00252F71 /* xdag_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xdag_config.c; sourceTree = ""; }; - 3845ABEA21D2BD9F00252F71 /* xdag_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdag_config.h; sourceTree = ""; }; - 3845AC2321D2BE0D00252F71 /* dnet_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_system.h; sourceTree = ""; }; - 3845AC2421D2C36100252F71 /* random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = random.c; sourceTree = ""; }; - 3845AC2521D2C36100252F71 /* random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random.h; sourceTree = ""; }; + 385EB7A321D3D64200287D2B /* atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomic.h; sourceTree = ""; }; + 385EB7A421D3D64200287D2B /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = ""; }; + 385EB7A521D3D64200287D2B /* rbtree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rbtree.h; sourceTree = ""; }; + 385EB7A721D3D64200287D2B /* address.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = address.c; sourceTree = ""; }; + 385EB7A821D3D64200287D2B /* address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = address.h; sourceTree = ""; }; + 385EB7AA21D3D64200287D2B /* crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc.c; sourceTree = ""; }; + 385EB7AB21D3D64200287D2B /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; + 385EB7AC21D3D64200287D2B /* sha256-mb-x86_64-mac.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "sha256-mb-x86_64-mac.s"; sourceTree = ""; }; + 385EB7AE21D3D64200287D2B /* sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha256.c; sourceTree = ""; }; + 385EB7AF21D3D64200287D2B /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha256.h; sourceTree = ""; }; + 385EB7B121D3D64200287D2B /* block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = block.c; sourceTree = ""; }; + 385EB7B321D3D64200287D2B /* block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = block.h; sourceTree = ""; }; + 385EB7B421D3D64200287D2B /* commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = commands.c; sourceTree = ""; }; + 385EB7B521D3D64200287D2B /* commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commands.h; sourceTree = ""; }; + 385EB7B621D3D64200287D2B /* crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crypt.c; sourceTree = ""; }; + 385EB7B721D3D64200287D2B /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; + 385EB7B921D3D64200287D2B /* example.pool.config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = example.pool.config; sourceTree = ""; }; + 385EB7BA21D3D64200287D2B /* global.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = global.c; sourceTree = ""; }; + 385EB7BB21D3D64200287D2B /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = global.h; sourceTree = ""; }; + 385EB7BC21D3D64200287D2B /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hash.c; sourceTree = ""; }; + 385EB7BD21D3D64200287D2B /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; + 385EB7BF21D3D64200287D2B /* http.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = http.c; sourceTree = ""; }; + 385EB7C021D3D64200287D2B /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = ""; }; + 385EB7C121D3D64200287D2B /* url.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = url.c; sourceTree = ""; }; + 385EB7C221D3D64200287D2B /* url.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = url.h; sourceTree = ""; }; + 385EB7C321D3D64200287D2B /* init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = init.c; sourceTree = ""; }; + 385EB7C421D3D64200287D2B /* init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = init.h; sourceTree = ""; }; + 385EB7C621D3D64200287D2B /* cJSON.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cJSON.c; sourceTree = ""; }; + 385EB7C721D3D64200287D2B /* cJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cJSON.h; sourceTree = ""; }; + 385EB7C821D3D64200287D2B /* cJSON_Utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cJSON_Utils.c; sourceTree = ""; }; + 385EB7C921D3D64200287D2B /* cJSON_Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cJSON_Utils.h; sourceTree = ""; }; + 385EB7CA21D3D64200287D2B /* rpc_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_commands.c; sourceTree = ""; }; + 385EB7CB21D3D64200287D2B /* rpc_commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_commands.h; sourceTree = ""; }; + 385EB7CC21D3D64200287D2B /* rpc_procedure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_procedure.c; sourceTree = ""; }; + 385EB7CD21D3D64200287D2B /* rpc_procedure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_procedure.h; sourceTree = ""; }; + 385EB7CE21D3D64200287D2B /* rpc_procedures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_procedures.c; sourceTree = ""; }; + 385EB7CF21D3D64200287D2B /* rpc_procedures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_procedures.h; sourceTree = ""; }; + 385EB7D021D3D64200287D2B /* rpc_service.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_service.c; sourceTree = ""; }; + 385EB7D121D3D64200287D2B /* rpc_service.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_service.h; sourceTree = ""; }; + 385EB7D221D3D64200287D2B /* rpc_wrapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpc_wrapper.c; sourceTree = ""; }; + 385EB7D321D3D64200287D2B /* rpc_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc_wrapper.h; sourceTree = ""; }; + 385EB7D421D3D64200287D2B /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 385EB7D621D3D64200287D2B /* math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = math.c; sourceTree = ""; }; + 385EB7D721D3D64200287D2B /* math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = math.h; sourceTree = ""; }; + 385EB7D821D3D64200287D2B /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = ""; }; + 385EB7D921D3D64200287D2B /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = ""; }; + 385EB7DA21D3D64200287D2B /* miner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = miner.c; sourceTree = ""; }; + 385EB7DB21D3D64200287D2B /* miner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = miner.h; sourceTree = ""; }; + 385EB7DC21D3D64200287D2B /* mining_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mining_common.c; sourceTree = ""; }; + 385EB7DD21D3D64200287D2B /* mining_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mining_common.h; sourceTree = ""; }; + 385EB7DE21D3D64200287D2B /* netdb-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-testnet.txt"; sourceTree = ""; }; + 385EB7DF21D3D64200287D2B /* netdb-white-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-white-testnet.txt"; sourceTree = ""; }; + 385EB7E021D3D64200287D2B /* netdb-white.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "netdb-white.txt"; sourceTree = ""; }; + 385EB7E121D3D64200287D2B /* netdb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = netdb.c; sourceTree = ""; }; + 385EB7E221D3D64200287D2B /* netdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = netdb.h; sourceTree = ""; }; + 385EB7E321D3D64200287D2B /* netdb.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = netdb.txt; sourceTree = ""; }; + 385EB7E421D3D64200287D2B /* network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = network.c; sourceTree = ""; }; + 385EB7E521D3D64200287D2B /* network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = network.h; sourceTree = ""; }; + 385EB7E621D3D64200287D2B /* pool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pool.c; sourceTree = ""; }; + 385EB7E721D3D64200287D2B /* pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pool.h; sourceTree = ""; }; + 385EB7E821D3D64200287D2B /* pools-testnet.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pools-testnet.txt"; sourceTree = ""; }; + 385EB7E921D3D64200287D2B /* pools.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pools.txt; sourceTree = ""; }; + 385EB7EA21D3D64200287D2B /* state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = state.h; sourceTree = ""; }; + 385EB7F021D3D64200287D2B /* storage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = storage.c; sourceTree = ""; }; + 385EB7F121D3D64200287D2B /* storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = storage.h; sourceTree = ""; }; + 385EB7F221D3D64200287D2B /* sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sync.c; sourceTree = ""; }; + 385EB7F321D3D64200287D2B /* sync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sync.h; sourceTree = ""; }; + 385EB7F421D3D64200287D2B /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system.h; sourceTree = ""; }; + 385EB7F521D3D64200287D2B /* terminal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = terminal.c; sourceTree = ""; }; + 385EB7F621D3D64200287D2B /* terminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = terminal.h; sourceTree = ""; }; + 385EB7F721D3D64200287D2B /* time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = time.c; sourceTree = ""; }; + 385EB7F821D3D64200287D2B /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; + 385EB7F921D3D64200287D2B /* transport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = transport.c; sourceTree = ""; }; + 385EB7FA21D3D64200287D2B /* transport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transport.h; sourceTree = ""; }; + 385EB7FB21D3D64200287D2B /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; + 385EB7FD21D3D64200287D2B /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uthash.h; sourceTree = ""; }; + 385EB7FE21D3D64200287D2B /* utlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utlist.h; sourceTree = ""; }; + 385EB80021D3D64200287D2B /* atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atomic.c; sourceTree = ""; }; + 385EB80121D3D64200287D2B /* atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomic.h; sourceTree = ""; }; + 385EB80221D3D64200287D2B /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; }; + 385EB80321D3D64200287D2B /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; + 385EB80421D3D64200287D2B /* dirname.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dirname.c; sourceTree = ""; }; + 385EB80521D3D64200287D2B /* dirname.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirname.h; sourceTree = ""; }; + 385EB80621D3D64200287D2B /* linenoise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = linenoise.c; sourceTree = ""; }; + 385EB80721D3D64200287D2B /* linenoise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linenoise.h; sourceTree = ""; }; + 385EB80821D3D64200287D2B /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = ""; }; + 385EB80921D3D64200287D2B /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; + 385EB80B21D3D64200287D2B /* moving_average.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = moving_average.c; sourceTree = ""; }; + 385EB80C21D3D64200287D2B /* moving_average.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moving_average.h; sourceTree = ""; }; + 385EB80D21D3D64200287D2B /* random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = random.c; sourceTree = ""; }; + 385EB80E21D3D64200287D2B /* random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random.h; sourceTree = ""; }; + 385EB80F21D3D64200287D2B /* string_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = string_utils.c; sourceTree = ""; }; + 385EB81021D3D64200287D2B /* string_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_utils.h; sourceTree = ""; }; + 385EB81121D3D64200287D2B /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; }; + 385EB81221D3D64200287D2B /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 385EB81321D3D64200287D2B /* uuid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uuid.c; sourceTree = ""; }; + 385EB81421D3D64200287D2B /* uuid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uuid.h; sourceTree = ""; }; + 385EB81521D3D64200287D2B /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; + 385EB81621D3D64200287D2B /* wallet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wallet.c; sourceTree = ""; }; + 385EB81721D3D64200287D2B /* wallet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wallet.h; sourceTree = ""; }; + 385EB81921D3D64200287D2B /* websocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = websocket.c; sourceTree = ""; }; + 385EB81A21D3D64200287D2B /* websocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = websocket.h; sourceTree = ""; }; + 385EB81C21D3D64200287D2B /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 385EB81D21D3D64200287D2B /* wslay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay.h; sourceTree = ""; }; + 385EB81E21D3D64200287D2B /* wslay_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wslay_event.c; sourceTree = ""; }; + 385EB81F21D3D64200287D2B /* wslay_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay_event.h; sourceTree = ""; }; + 385EB82021D3D64200287D2B /* wslay_frame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wslay_frame.c; sourceTree = ""; }; + 385EB82121D3D64200287D2B /* wslay_frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay_frame.h; sourceTree = ""; }; + 385EB82221D3D64200287D2B /* wslay_net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wslay_net.c; sourceTree = ""; }; + 385EB82321D3D64200287D2B /* wslay_net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay_net.h; sourceTree = ""; }; + 385EB82421D3D64200287D2B /* wslay_queue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wslay_queue.c; sourceTree = ""; }; + 385EB82521D3D64200287D2B /* wslay_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay_queue.h; sourceTree = ""; }; + 385EB82621D3D64200287D2B /* wslay_stack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wslay_stack.c; sourceTree = ""; }; + 385EB82721D3D64200287D2B /* wslay_stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslay_stack.h; sourceTree = ""; }; + 385EB82821D3D64200287D2B /* wslayver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wslayver.h; sourceTree = ""; }; + 385EB82921D3D64200287D2B /* x86_64cpuid-mac.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "x86_64cpuid-mac.s"; sourceTree = ""; }; + 385EB82B21D3D64200287D2B /* xdag_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xdag_config.c; sourceTree = ""; }; + 385EB82C21D3D64200287D2B /* xdag_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xdag_config.h; sourceTree = ""; }; + 385EB82E21D3D64200287D2B /* dfslib_crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_crypt.c; sourceTree = ""; }; + 385EB82F21D3D64200287D2B /* dfslib_crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_crypt.h; sourceTree = ""; }; + 385EB83021D3D64200287D2B /* dfslib_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_random.c; sourceTree = ""; }; + 385EB83121D3D64200287D2B /* dfslib_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_random.h; sourceTree = ""; }; + 385EB83221D3D64200287D2B /* dfslib_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfslib_string.c; sourceTree = ""; }; + 385EB83321D3D64200287D2B /* dfslib_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_string.h; sourceTree = ""; }; + 385EB83421D3D64200287D2B /* dfslib_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfslib_types.h; sourceTree = ""; }; + 385EB83521D3D64200287D2B /* dfsrsa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dfsrsa.c; sourceTree = ""; }; + 385EB83621D3D64200287D2B /* dfsrsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dfsrsa.h; sourceTree = ""; }; + 385EB83821D3D64200287D2B /* dnet_crypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnet_crypt.c; sourceTree = ""; }; + 385EB83921D3D64200287D2B /* dnet_crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_crypt.h; sourceTree = ""; }; + 385EB83A21D3D64200287D2B /* dnet_history.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_history.h; sourceTree = ""; }; + 385EB83B21D3D64200287D2B /* dnet_keys.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = dnet_keys.bin; sourceTree = ""; }; + 385EB83C21D3D64200287D2B /* dnet_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_main.h; sourceTree = ""; }; + 385EB83D21D3D64200287D2B /* dnet_packet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_packet.h; sourceTree = ""; }; + 385EB83E21D3D64200287D2B /* dnet_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dnet_system.h; sourceTree = ""; }; + 385EB83F21D3D64200287D2B /* dnet_xdag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dnet_xdag.c; sourceTree = ""; }; 389F043620544EDC003F3084 /* xdag */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xdag; sourceTree = BUILT_PRODUCTS_DIR; }; 418AAFF5213BB3A900E96520 /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = lib/openssl/lib/libcrypto.a; sourceTree = ""; }; 418AAFF7213BB3B300E96520 /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = lib/openssl/lib/libssl.a; sourceTree = ""; }; @@ -230,210 +264,244 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 380AAA89211B6DA40090A5A4 /* dnet */ = { + 385EB7A221D3D64200287D2B /* ldus */ = { isa = PBXGroup; children = ( - 380AAA8A211B6DA40090A5A4 /* dnet_crypt.c */, - 380AAA8B211B6DA40090A5A4 /* dnet_crypt.h */, - 380AAA8C211B6DA40090A5A4 /* dnet_history.h */, - 380AAA8D211B6DA40090A5A4 /* dnet_keys.bin */, - 380AAA8E211B6DA40090A5A4 /* dnet_main.h */, - 380AAA8F211B6DA40090A5A4 /* dnet_packet.h */, - 3845AC2321D2BE0D00252F71 /* dnet_system.h */, - 380AAA90211B6DA40090A5A4 /* dnet_xdag.c */, - ); - name = dnet; - path = ../dnet; - sourceTree = ""; - }; - 3845AB5121D2BC1000252F71 /* ldus */ = { - isa = PBXGroup; - children = ( - 3845AB5221D2BC1000252F71 /* atomic.h */, - 3845AB5321D2BC1000252F71 /* list.h */, - 3845AB5421D2BC1000252F71 /* rbtree.h */, + 385EB7A321D3D64200287D2B /* atomic.h */, + 385EB7A421D3D64200287D2B /* list.h */, + 385EB7A521D3D64200287D2B /* rbtree.h */, ); name = ldus; path = ../ldus; sourceTree = ""; }; - 3845AB5521D2BC1000252F71 /* dfslib */ = { + 385EB7A621D3D64200287D2B /* client */ = { isa = PBXGroup; children = ( - 3845AB5621D2BC1000252F71 /* dfslib_crypt.c */, - 3845AB5721D2BC1000252F71 /* dfslib_crypt.h */, - 3845AB5821D2BC1000252F71 /* dfslib_random.c */, - 3845AB5921D2BC1000252F71 /* dfslib_random.h */, - 3845AB5A21D2BC1000252F71 /* dfslib_string.c */, - 3845AB5B21D2BC1000252F71 /* dfslib_string.h */, - 3845AB5C21D2BC1000252F71 /* dfslib_types.h */, - 3845AB5D21D2BC1000252F71 /* dfsrsa.c */, - 3845AB5E21D2BC1000252F71 /* dfsrsa.h */, - ); - name = dfslib; - path = ../dfslib; - sourceTree = ""; - }; - 3845AB7A21D2BD9F00252F71 /* client */ = { - isa = PBXGroup; - children = ( - 3845AB7B21D2BD9F00252F71 /* address.c */, - 3845AB7C21D2BD9F00252F71 /* address.h */, - 3845AB7D21D2BD9F00252F71 /* algorithms */, - 3845AB8521D2BD9F00252F71 /* block.c */, - 3845AB8721D2BD9F00252F71 /* block.h */, - 3845AB8821D2BD9F00252F71 /* commands.c */, - 3845AB8921D2BD9F00252F71 /* commands.h */, - 3845AB8A21D2BD9F00252F71 /* crypt.c */, - 3845AB8B21D2BD9F00252F71 /* crypt.h */, - 3845AB8D21D2BD9F00252F71 /* example.pool.config */, - 3845AB8E21D2BD9F00252F71 /* global.c */, - 3845AB8F21D2BD9F00252F71 /* global.h */, - 3845AB9021D2BD9F00252F71 /* hash.c */, - 3845AB9121D2BD9F00252F71 /* hash.h */, - 3845AB9221D2BD9F00252F71 /* http */, - 3845AB9721D2BD9F00252F71 /* init.c */, - 3845AB9821D2BD9F00252F71 /* init.h */, - 3845AB9921D2BD9F00252F71 /* json-rpc */, - 3845ABA821D2BD9F00252F71 /* main.c */, - 3845ABA921D2BD9F00252F71 /* Makefile */, - 3845ABAA21D2BD9F00252F71 /* math.c */, - 3845ABAB21D2BD9F00252F71 /* math.h */, - 3845ABAC21D2BD9F00252F71 /* memory.c */, - 3845ABAD21D2BD9F00252F71 /* memory.h */, - 3845ABAE21D2BD9F00252F71 /* miner.c */, - 3845ABAF21D2BD9F00252F71 /* miner.h */, - 3845ABB021D2BD9F00252F71 /* mining_common.c */, - 3845ABB121D2BD9F00252F71 /* mining_common.h */, - 3845ABB221D2BD9F00252F71 /* netdb-testnet.txt */, - 3845ABB321D2BD9F00252F71 /* netdb-white-testnet.txt */, - 3845ABB421D2BD9F00252F71 /* netdb-white.txt */, - 3845ABB521D2BD9F00252F71 /* netdb.c */, - 3845ABB621D2BD9F00252F71 /* netdb.h */, - 3845ABB721D2BD9F00252F71 /* netdb.txt */, - 3845ABB821D2BD9F00252F71 /* network.c */, - 3845ABB921D2BD9F00252F71 /* network.h */, - 3845ABBA21D2BD9F00252F71 /* pool.c */, - 3845ABBB21D2BD9F00252F71 /* pool.h */, - 3845ABBC21D2BD9F00252F71 /* pools-testnet.txt */, - 3845ABBD21D2BD9F00252F71 /* pools.txt */, - 3845ABBE21D2BD9F00252F71 /* state.h */, - 3845ABC421D2BD9F00252F71 /* storage.c */, - 3845ABC521D2BD9F00252F71 /* storage.h */, - 3845ABC621D2BD9F00252F71 /* sync.c */, - 3845ABC721D2BD9F00252F71 /* sync.h */, - 3845ABC821D2BD9F00252F71 /* system.h */, - 3845ABC921D2BD9F00252F71 /* terminal.c */, - 3845ABCA21D2BD9F00252F71 /* terminal.h */, - 3845ABCB21D2BD9F00252F71 /* time.c */, - 3845ABCC21D2BD9F00252F71 /* time.h */, - 3845ABCD21D2BD9F00252F71 /* transport.c */, - 3845ABCE21D2BD9F00252F71 /* transport.h */, - 3845ABCF21D2BD9F00252F71 /* types.h */, - 3845ABD021D2BD9F00252F71 /* uthash */, - 3845ABD321D2BD9F00252F71 /* utils */, - 3845ABE321D2BD9F00252F71 /* version.h */, - 3845ABE421D2BD9F00252F71 /* wallet.c */, - 3845ABE521D2BD9F00252F71 /* wallet.h */, - 3845ABE721D2BD9F00252F71 /* x86_64cpuid-mac.s */, - 3845ABE921D2BD9F00252F71 /* xdag_config.c */, - 3845ABEA21D2BD9F00252F71 /* xdag_config.h */, + 385EB7A721D3D64200287D2B /* address.c */, + 385EB7A821D3D64200287D2B /* address.h */, + 385EB7A921D3D64200287D2B /* algorithms */, + 385EB7B121D3D64200287D2B /* block.c */, + 385EB7B321D3D64200287D2B /* block.h */, + 385EB7B421D3D64200287D2B /* commands.c */, + 385EB7B521D3D64200287D2B /* commands.h */, + 385EB7B621D3D64200287D2B /* crypt.c */, + 385EB7B721D3D64200287D2B /* crypt.h */, + 385EB7B921D3D64200287D2B /* example.pool.config */, + 385EB7BA21D3D64200287D2B /* global.c */, + 385EB7BB21D3D64200287D2B /* global.h */, + 385EB7BC21D3D64200287D2B /* hash.c */, + 385EB7BD21D3D64200287D2B /* hash.h */, + 385EB7BE21D3D64200287D2B /* http */, + 385EB7C321D3D64200287D2B /* init.c */, + 385EB7C421D3D64200287D2B /* init.h */, + 385EB7C521D3D64200287D2B /* json-rpc */, + 385EB7D421D3D64200287D2B /* main.c */, + 385EB7D621D3D64200287D2B /* math.c */, + 385EB7D721D3D64200287D2B /* math.h */, + 385EB7D821D3D64200287D2B /* memory.c */, + 385EB7D921D3D64200287D2B /* memory.h */, + 385EB7DA21D3D64200287D2B /* miner.c */, + 385EB7DB21D3D64200287D2B /* miner.h */, + 385EB7DC21D3D64200287D2B /* mining_common.c */, + 385EB7DD21D3D64200287D2B /* mining_common.h */, + 385EB7DE21D3D64200287D2B /* netdb-testnet.txt */, + 385EB7DF21D3D64200287D2B /* netdb-white-testnet.txt */, + 385EB7E021D3D64200287D2B /* netdb-white.txt */, + 385EB7E121D3D64200287D2B /* netdb.c */, + 385EB7E221D3D64200287D2B /* netdb.h */, + 385EB7E321D3D64200287D2B /* netdb.txt */, + 385EB7E421D3D64200287D2B /* network.c */, + 385EB7E521D3D64200287D2B /* network.h */, + 385EB7E621D3D64200287D2B /* pool.c */, + 385EB7E721D3D64200287D2B /* pool.h */, + 385EB7E821D3D64200287D2B /* pools-testnet.txt */, + 385EB7E921D3D64200287D2B /* pools.txt */, + 385EB7EA21D3D64200287D2B /* state.h */, + 385EB7F021D3D64200287D2B /* storage.c */, + 385EB7F121D3D64200287D2B /* storage.h */, + 385EB7F221D3D64200287D2B /* sync.c */, + 385EB7F321D3D64200287D2B /* sync.h */, + 385EB7F421D3D64200287D2B /* system.h */, + 385EB7F521D3D64200287D2B /* terminal.c */, + 385EB7F621D3D64200287D2B /* terminal.h */, + 385EB7F721D3D64200287D2B /* time.c */, + 385EB7F821D3D64200287D2B /* time.h */, + 385EB7F921D3D64200287D2B /* transport.c */, + 385EB7FA21D3D64200287D2B /* transport.h */, + 385EB7FB21D3D64200287D2B /* types.h */, + 385EB7FC21D3D64200287D2B /* uthash */, + 385EB7FF21D3D64200287D2B /* utils */, + 385EB81521D3D64200287D2B /* version.h */, + 385EB81621D3D64200287D2B /* wallet.c */, + 385EB81721D3D64200287D2B /* wallet.h */, + 385EB81821D3D64200287D2B /* websocket */, + 385EB82921D3D64200287D2B /* x86_64cpuid-mac.s */, + 385EB82B21D3D64200287D2B /* xdag_config.c */, + 385EB82C21D3D64200287D2B /* xdag_config.h */, ); name = client; path = ../client; sourceTree = ""; }; - 3845AB7D21D2BD9F00252F71 /* algorithms */ = { + 385EB7A921D3D64200287D2B /* algorithms */ = { isa = PBXGroup; children = ( - 3845AB7E21D2BD9F00252F71 /* crc.c */, - 3845AB7F21D2BD9F00252F71 /* crc.h */, - 3845AB8021D2BD9F00252F71 /* sha256-mb-x86_64-mac.s */, - 3845AB8221D2BD9F00252F71 /* sha256.c */, - 3845AB8321D2BD9F00252F71 /* sha256.h */, + 385EB7AA21D3D64200287D2B /* crc.c */, + 385EB7AB21D3D64200287D2B /* crc.h */, + 385EB7AC21D3D64200287D2B /* sha256-mb-x86_64-mac.s */, + 385EB7AE21D3D64200287D2B /* sha256.c */, + 385EB7AF21D3D64200287D2B /* sha256.h */, ); path = algorithms; sourceTree = ""; }; - 3845AB9221D2BD9F00252F71 /* http */ = { + 385EB7BE21D3D64200287D2B /* http */ = { isa = PBXGroup; children = ( - 3845AB9321D2BD9F00252F71 /* http.c */, - 3845AB9421D2BD9F00252F71 /* http.h */, - 3845AB9521D2BD9F00252F71 /* url.c */, - 3845AB9621D2BD9F00252F71 /* url.h */, + 385EB7BF21D3D64200287D2B /* http.c */, + 385EB7C021D3D64200287D2B /* http.h */, + 385EB7C121D3D64200287D2B /* url.c */, + 385EB7C221D3D64200287D2B /* url.h */, ); path = http; sourceTree = ""; }; - 3845AB9921D2BD9F00252F71 /* json-rpc */ = { + 385EB7C521D3D64200287D2B /* json-rpc */ = { isa = PBXGroup; children = ( - 3845AB9A21D2BD9F00252F71 /* cJSON.c */, - 3845AB9B21D2BD9F00252F71 /* cJSON.h */, - 3845AB9C21D2BD9F00252F71 /* cJSON_Utils.c */, - 3845AB9D21D2BD9F00252F71 /* cJSON_Utils.h */, - 3845AB9E21D2BD9F00252F71 /* rpc_commands.c */, - 3845AB9F21D2BD9F00252F71 /* rpc_commands.h */, - 3845ABA021D2BD9F00252F71 /* rpc_procedure.c */, - 3845ABA121D2BD9F00252F71 /* rpc_procedure.h */, - 3845ABA221D2BD9F00252F71 /* rpc_procedures.c */, - 3845ABA321D2BD9F00252F71 /* rpc_procedures.h */, - 3845ABA421D2BD9F00252F71 /* rpc_service.c */, - 3845ABA521D2BD9F00252F71 /* rpc_service.h */, - 3845ABA621D2BD9F00252F71 /* rpc_wrapper.c */, - 3845ABA721D2BD9F00252F71 /* rpc_wrapper.h */, + 385EB7C621D3D64200287D2B /* cJSON.c */, + 385EB7C721D3D64200287D2B /* cJSON.h */, + 385EB7C821D3D64200287D2B /* cJSON_Utils.c */, + 385EB7C921D3D64200287D2B /* cJSON_Utils.h */, + 385EB7CA21D3D64200287D2B /* rpc_commands.c */, + 385EB7CB21D3D64200287D2B /* rpc_commands.h */, + 385EB7CC21D3D64200287D2B /* rpc_procedure.c */, + 385EB7CD21D3D64200287D2B /* rpc_procedure.h */, + 385EB7CE21D3D64200287D2B /* rpc_procedures.c */, + 385EB7CF21D3D64200287D2B /* rpc_procedures.h */, + 385EB7D021D3D64200287D2B /* rpc_service.c */, + 385EB7D121D3D64200287D2B /* rpc_service.h */, + 385EB7D221D3D64200287D2B /* rpc_wrapper.c */, + 385EB7D321D3D64200287D2B /* rpc_wrapper.h */, ); path = "json-rpc"; sourceTree = ""; }; - 3845ABD021D2BD9F00252F71 /* uthash */ = { + 385EB7FC21D3D64200287D2B /* uthash */ = { isa = PBXGroup; children = ( - 3845ABD121D2BD9F00252F71 /* uthash.h */, - 3845ABD221D2BD9F00252F71 /* utlist.h */, + 385EB7FD21D3D64200287D2B /* uthash.h */, + 385EB7FE21D3D64200287D2B /* utlist.h */, ); path = uthash; sourceTree = ""; }; - 3845ABD321D2BD9F00252F71 /* utils */ = { + 385EB7FF21D3D64200287D2B /* utils */ = { isa = PBXGroup; children = ( - 3845AC2421D2C36100252F71 /* random.c */, - 3845AC2521D2C36100252F71 /* random.h */, - 3845ABD421D2BD9F00252F71 /* atomic.c */, - 3845ABD521D2BD9F00252F71 /* atomic.h */, - 3845ABD621D2BD9F00252F71 /* dirname.c */, - 3845ABD721D2BD9F00252F71 /* dirname.h */, - 3845ABD821D2BD9F00252F71 /* linenoise.c */, - 3845ABD921D2BD9F00252F71 /* linenoise.h */, - 3845ABDA21D2BD9F00252F71 /* log.c */, - 3845ABDB21D2BD9F00252F71 /* log.h */, - 3845ABDC21D2BD9F00252F71 /* moving_statistics */, - 3845ABDF21D2BD9F00252F71 /* string_utils.c */, - 3845ABE021D2BD9F00252F71 /* string_utils.h */, - 3845ABE121D2BD9F00252F71 /* utils.c */, - 3845ABE221D2BD9F00252F71 /* utils.h */, + 385EB80021D3D64200287D2B /* atomic.c */, + 385EB80121D3D64200287D2B /* atomic.h */, + 385EB80221D3D64200287D2B /* base64.c */, + 385EB80321D3D64200287D2B /* base64.h */, + 385EB80421D3D64200287D2B /* dirname.c */, + 385EB80521D3D64200287D2B /* dirname.h */, + 385EB80621D3D64200287D2B /* linenoise.c */, + 385EB80721D3D64200287D2B /* linenoise.h */, + 385EB80821D3D64200287D2B /* log.c */, + 385EB80921D3D64200287D2B /* log.h */, + 385EB80A21D3D64200287D2B /* moving_statistics */, + 385EB80D21D3D64200287D2B /* random.c */, + 385EB80E21D3D64200287D2B /* random.h */, + 385EB80F21D3D64200287D2B /* string_utils.c */, + 385EB81021D3D64200287D2B /* string_utils.h */, + 385EB81121D3D64200287D2B /* utils.c */, + 385EB81221D3D64200287D2B /* utils.h */, + 385EB81321D3D64200287D2B /* uuid.c */, + 385EB81421D3D64200287D2B /* uuid.h */, ); path = utils; sourceTree = ""; }; - 3845ABDC21D2BD9F00252F71 /* moving_statistics */ = { + 385EB80A21D3D64200287D2B /* moving_statistics */ = { isa = PBXGroup; children = ( - 3845ABDD21D2BD9F00252F71 /* moving_average.c */, - 3845ABDE21D2BD9F00252F71 /* moving_average.h */, + 385EB80B21D3D64200287D2B /* moving_average.c */, + 385EB80C21D3D64200287D2B /* moving_average.h */, ); path = moving_statistics; sourceTree = ""; }; + 385EB81821D3D64200287D2B /* websocket */ = { + isa = PBXGroup; + children = ( + 385EB81921D3D64200287D2B /* websocket.c */, + 385EB81A21D3D64200287D2B /* websocket.h */, + 385EB81B21D3D64200287D2B /* wslay */, + ); + path = websocket; + sourceTree = ""; + }; + 385EB81B21D3D64200287D2B /* wslay */ = { + isa = PBXGroup; + children = ( + 385EB81C21D3D64200287D2B /* config.h */, + 385EB81D21D3D64200287D2B /* wslay.h */, + 385EB81E21D3D64200287D2B /* wslay_event.c */, + 385EB81F21D3D64200287D2B /* wslay_event.h */, + 385EB82021D3D64200287D2B /* wslay_frame.c */, + 385EB82121D3D64200287D2B /* wslay_frame.h */, + 385EB82221D3D64200287D2B /* wslay_net.c */, + 385EB82321D3D64200287D2B /* wslay_net.h */, + 385EB82421D3D64200287D2B /* wslay_queue.c */, + 385EB82521D3D64200287D2B /* wslay_queue.h */, + 385EB82621D3D64200287D2B /* wslay_stack.c */, + 385EB82721D3D64200287D2B /* wslay_stack.h */, + 385EB82821D3D64200287D2B /* wslayver.h */, + ); + path = wslay; + sourceTree = ""; + }; + 385EB82D21D3D64200287D2B /* dfslib */ = { + isa = PBXGroup; + children = ( + 385EB82E21D3D64200287D2B /* dfslib_crypt.c */, + 385EB82F21D3D64200287D2B /* dfslib_crypt.h */, + 385EB83021D3D64200287D2B /* dfslib_random.c */, + 385EB83121D3D64200287D2B /* dfslib_random.h */, + 385EB83221D3D64200287D2B /* dfslib_string.c */, + 385EB83321D3D64200287D2B /* dfslib_string.h */, + 385EB83421D3D64200287D2B /* dfslib_types.h */, + 385EB83521D3D64200287D2B /* dfsrsa.c */, + 385EB83621D3D64200287D2B /* dfsrsa.h */, + ); + name = dfslib; + path = ../dfslib; + sourceTree = ""; + }; + 385EB83721D3D64200287D2B /* dnet */ = { + isa = PBXGroup; + children = ( + 385EB83821D3D64200287D2B /* dnet_crypt.c */, + 385EB83921D3D64200287D2B /* dnet_crypt.h */, + 385EB83A21D3D64200287D2B /* dnet_history.h */, + 385EB83B21D3D64200287D2B /* dnet_keys.bin */, + 385EB83C21D3D64200287D2B /* dnet_main.h */, + 385EB83D21D3D64200287D2B /* dnet_packet.h */, + 385EB83E21D3D64200287D2B /* dnet_system.h */, + 385EB83F21D3D64200287D2B /* dnet_xdag.c */, + ); + name = dnet; + path = ../dnet; + sourceTree = ""; + }; 389F042D20544EDC003F3084 = { isa = PBXGroup; children = ( - 3845AB7A21D2BD9F00252F71 /* client */, - 380AAA89211B6DA40090A5A4 /* dnet */, - 3845AB5521D2BC1000252F71 /* dfslib */, - 3845AB5121D2BC1000252F71 /* ldus */, + 385EB7A621D3D64200287D2B /* client */, + 385EB82D21D3D64200287D2B /* dfslib */, + 385EB83721D3D64200287D2B /* dnet */, + 385EB7A221D3D64200287D2B /* ldus */, 389F043720544EDC003F3084 /* Products */, 38A15E9E20545CCE00598EC2 /* Frameworks */, ); @@ -514,13 +582,14 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3845AC1021D2BD9F00252F71 /* pools-testnet.txt in Resources */, - 3845AC0B21D2BD9F00252F71 /* netdb-white.txt in Resources */, - 3845AC0D21D2BD9F00252F71 /* netdb.txt in Resources */, - 3845AC0921D2BD9F00252F71 /* netdb-testnet.txt in Resources */, - 3845AC0A21D2BD9F00252F71 /* netdb-white-testnet.txt in Resources */, - 3845AC1121D2BD9F00252F71 /* pools.txt in Resources */, - 3845ABF621D2BD9F00252F71 /* example.pool.config in Resources */, + 385EB88B21D3D76100287D2B /* dnet_keys.bin in Resources */, + 385EB86721D3D64200287D2B /* pools-testnet.txt in Resources */, + 385EB86221D3D64200287D2B /* netdb-white.txt in Resources */, + 385EB86421D3D64200287D2B /* netdb.txt in Resources */, + 385EB86021D3D64200287D2B /* netdb-testnet.txt in Resources */, + 385EB86121D3D64200287D2B /* netdb-white-testnet.txt in Resources */, + 385EB86821D3D64200287D2B /* pools.txt in Resources */, + 385EB84D21D3D64200287D2B /* example.pool.config in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -531,56 +600,63 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3845AC1721D2BD9F00252F71 /* transport.c in Sources */, - 3845AC0521D2BD9F00252F71 /* math.c in Sources */, - 380AAA96211B6DA50090A5A4 /* dnet_xdag.c in Sources */, - 3845AC1921D2BD9F00252F71 /* dirname.c in Sources */, - 3845AB6221D2BC1000252F71 /* dfsrsa.c in Sources */, - 3845AC0721D2BD9F00252F71 /* miner.c in Sources */, - 3845ABEB21D2BD9F00252F71 /* address.c in Sources */, - 380AAA94211B6DA50090A5A4 /* dnet_crypt.c in Sources */, - 3845AC0F21D2BD9F00252F71 /* pool.c in Sources */, - 3845AB5F21D2BC1000252F71 /* dfslib_crypt.c in Sources */, - 3845ABFB21D2BD9F00252F71 /* init.c in Sources */, - 3845AC1521D2BD9F00252F71 /* terminal.c in Sources */, - 3845AB6121D2BC1000252F71 /* dfslib_string.c in Sources */, - 3845AC1621D2BD9F00252F71 /* time.c in Sources */, - 3845AC1F21D2BD9F00252F71 /* wallet.c in Sources */, - 3845AC1821D2BD9F00252F71 /* atomic.c in Sources */, - 3845ABFD21D2BD9F00252F71 /* cJSON_Utils.c in Sources */, - 3845AC1321D2BD9F00252F71 /* storage.c in Sources */, - 3845ABED21D2BD9F00252F71 /* sha256-mb-x86_64-mac.s in Sources */, - 3845ABF421D2BD9F00252F71 /* crypt.c in Sources */, - 3845ABFE21D2BD9F00252F71 /* rpc_commands.c in Sources */, - 3845AC1B21D2BD9F00252F71 /* log.c in Sources */, - 3845AC0121D2BD9F00252F71 /* rpc_service.c in Sources */, - 3845ABF721D2BD9F00252F71 /* global.c in Sources */, - 3845ABEC21D2BD9F00252F71 /* crc.c in Sources */, - 3845AC0621D2BD9F00252F71 /* memory.c in Sources */, - 3845AC0E21D2BD9F00252F71 /* network.c in Sources */, - 3845AC1E21D2BD9F00252F71 /* utils.c in Sources */, - 3845ABEF21D2BD9F00252F71 /* sha256.c in Sources */, - 3845ABF921D2BD9F00252F71 /* http.c in Sources */, - 3845AC0321D2BD9F00252F71 /* main.c in Sources */, - 3845ABF821D2BD9F00252F71 /* hash.c in Sources */, - 3845AC0221D2BD9F00252F71 /* rpc_wrapper.c in Sources */, - 3845AC1421D2BD9F00252F71 /* sync.c in Sources */, - 3845AB6021D2BC1000252F71 /* dfslib_random.c in Sources */, - 3845ABFC21D2BD9F00252F71 /* cJSON.c in Sources */, - 3845AC2021D2BD9F00252F71 /* x86_64cpuid-mac.s in Sources */, - 3845AC0821D2BD9F00252F71 /* mining_common.c in Sources */, - 3845AC2621D2C36100252F71 /* random.c in Sources */, - 3845AC1A21D2BD9F00252F71 /* linenoise.c in Sources */, - 3845ABFA21D2BD9F00252F71 /* url.c in Sources */, - 3845AC1D21D2BD9F00252F71 /* string_utils.c in Sources */, - 3845ABF121D2BD9F00252F71 /* block.c in Sources */, - 3845AC1C21D2BD9F00252F71 /* moving_average.c in Sources */, - 3845AC0021D2BD9F00252F71 /* rpc_procedures.c in Sources */, - 3845AC2221D2BD9F00252F71 /* xdag_config.c in Sources */, - 3845AC0421D2BD9F00252F71 /* Makefile in Sources */, - 3845AC0C21D2BD9F00252F71 /* netdb.c in Sources */, - 3845ABF321D2BD9F00252F71 /* commands.c in Sources */, - 3845ABFF21D2BD9F00252F71 /* rpc_procedure.c in Sources */, + 385EB84F21D3D64200287D2B /* hash.c in Sources */, + 385EB86A21D3D64200287D2B /* storage.c in Sources */, + 385EB85521D3D64200287D2B /* rpc_commands.c in Sources */, + 385EB87921D3D64200287D2B /* wallet.c in Sources */, + 385EB84821D3D64200287D2B /* block.c in Sources */, + 385EB86B21D3D64200287D2B /* sync.c in Sources */, + 385EB87B21D3D64200287D2B /* wslay_event.c in Sources */, + 385EB84A21D3D64200287D2B /* commands.c in Sources */, + 385EB86C21D3D64200287D2B /* terminal.c in Sources */, + 385EB88921D3D64200287D2B /* dnet_xdag.c in Sources */, + 385EB88521D3D64200287D2B /* dfslib_string.c in Sources */, + 385EB87E21D3D64200287D2B /* wslay_queue.c in Sources */, + 385EB84621D3D64200287D2B /* sha256.c in Sources */, + 385EB88321D3D64200287D2B /* dfslib_crypt.c in Sources */, + 385EB88021D3D64200287D2B /* x86_64cpuid-mac.s in Sources */, + 385EB86521D3D64200287D2B /* network.c in Sources */, + 385EB85921D3D64200287D2B /* rpc_wrapper.c in Sources */, + 385EB87221D3D64200287D2B /* linenoise.c in Sources */, + 385EB87521D3D64200287D2B /* random.c in Sources */, + 385EB85121D3D64200287D2B /* url.c in Sources */, + 385EB87D21D3D64200287D2B /* wslay_net.c in Sources */, + 385EB86321D3D64200287D2B /* netdb.c in Sources */, + 385EB84B21D3D64200287D2B /* crypt.c in Sources */, + 385EB85721D3D64200287D2B /* rpc_procedures.c in Sources */, + 385EB84E21D3D64200287D2B /* global.c in Sources */, + 385EB85D21D3D64200287D2B /* memory.c in Sources */, + 385EB85C21D3D64200287D2B /* math.c in Sources */, + 385EB88421D3D64200287D2B /* dfslib_random.c in Sources */, + 385EB86621D3D64200287D2B /* pool.c in Sources */, + 385EB87721D3D64200287D2B /* utils.c in Sources */, + 385EB87121D3D64200287D2B /* dirname.c in Sources */, + 385EB87621D3D64200287D2B /* string_utils.c in Sources */, + 385EB85E21D3D64200287D2B /* miner.c in Sources */, + 385EB84421D3D64200287D2B /* sha256-mb-x86_64-mac.s in Sources */, + 385EB86F21D3D64200287D2B /* atomic.c in Sources */, + 385EB85221D3D64200287D2B /* init.c in Sources */, + 385EB87A21D3D64200287D2B /* websocket.c in Sources */, + 385EB88721D3D64200287D2B /* dnet_crypt.c in Sources */, + 385EB87821D3D64200287D2B /* uuid.c in Sources */, + 385EB84321D3D64200287D2B /* crc.c in Sources */, + 385EB87C21D3D64200287D2B /* wslay_frame.c in Sources */, + 385EB85021D3D64200287D2B /* http.c in Sources */, + 385EB84221D3D64200287D2B /* address.c in Sources */, + 385EB85F21D3D64200287D2B /* mining_common.c in Sources */, + 385EB87021D3D64200287D2B /* base64.c in Sources */, + 385EB87F21D3D64200287D2B /* wslay_stack.c in Sources */, + 385EB85821D3D64200287D2B /* rpc_service.c in Sources */, + 385EB88621D3D64200287D2B /* dfsrsa.c in Sources */, + 385EB87421D3D64200287D2B /* moving_average.c in Sources */, + 385EB86E21D3D64200287D2B /* transport.c in Sources */, + 385EB85A21D3D64200287D2B /* main.c in Sources */, + 385EB86D21D3D64200287D2B /* time.c in Sources */, + 385EB85621D3D64200287D2B /* rpc_procedure.c in Sources */, + 385EB85321D3D64200287D2B /* cJSON.c in Sources */, + 385EB85421D3D64200287D2B /* cJSON_Utils.c in Sources */, + 385EB88221D3D64200287D2B /* xdag_config.c in Sources */, + 385EB87321D3D64200287D2B /* log.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -698,9 +774,6 @@ CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_ENABLE_ASM_KEYWORD = YES; - GCC_ENABLE_BUILTIN_FUNCTIONS = YES; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -734,9 +807,6 @@ CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_ENABLE_ASM_KEYWORD = YES; - GCC_ENABLE_BUILTIN_FUNCTIONS = YES; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_PREPROCESSOR_DEFINITIONS = ( __MACOS__,