├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── client ├── client.c └── client.h ├── config.json ├── lib ├── base64.c ├── base64.h ├── log.c ├── log.h ├── parson.c ├── parson.h ├── parson_test.c ├── password.c ├── password.h ├── password_test.c ├── securesocket.c └── securesocket.h └── server ├── server.c └── server.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.out 3 | cmake-build-debug/ 4 | .idea/ 5 | .vscode/ 6 | CMake* 7 | bin/ 8 | test* 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 LeeReindeer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -g -std=c99 2 | EVENTLIB?=-levent 3 | BINDIR?=./bin 4 | SERVERDIR?=./server 5 | CLIENTDIR?=./client 6 | LIB?=./lib 7 | 8 | $(shell mkdir -p $(BINDIR)) 9 | 10 | 11 | all: lib lightclient lightserver 12 | 13 | lib: base64 log password securesocket parson 14 | 15 | lightclient: 16 | gcc $(CFLAGS) -o $(BINDIR)/client $(CLIENTDIR)/client.c $(BINDIR)/base64.o $(BINDIR)/log.o $(BINDIR)/password.o $(BINDIR)/securesocket.o $(BINDIR)/parson.o $(EVENTLIB) 17 | 18 | lightserver: 19 | gcc $(CFLAGS) -o $(BINDIR)/server $(SERVERDIR)/server.c $(BINDIR)/base64.o $(BINDIR)/log.o $(BINDIR)/password.o $(BINDIR)/securesocket.o $(BINDIR)/parson.o $(EVENTLIB) 20 | 21 | # libs 22 | base64: 23 | gcc $(CFLAGS) -c $(LIB)/base64.c -o $(BINDIR)/base64.o 24 | 25 | log: 26 | gcc $(CFLAGS) -c $(LIB)/log.c -o $(BINDIR)/log.o -DLOG_USE_COLOR 27 | 28 | password: 29 | gcc $(CFLAGS) -c $(LIB)/password.c -o $(BINDIR)/password.o 30 | 31 | securesocket: 32 | gcc $(CFLAGS) -c $(LIB)/securesocket.c -o $(BINDIR)/securesocket.o 33 | 34 | parson: 35 | gcc $(CFLAGS) -c $(LIB)/parson.c -o $(BINDIR)/parson.o 36 | 37 | clean: 38 | rm -rf bin 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lightsocks-c (Deprecated) 2 | 3 | > A tiny SOCKS5 proxy which is inspired by [lightsocks-go](https://github.com/gwuhaolin/lightsocks) and uses [libevent](http://libevent.org/). 4 | > 5 | > **WARNING: Lightsocks-server does not work now.** 6 | 7 | ## Build 8 | 9 | **required libevent installed.** 10 | 11 | ```shell 12 | make all 13 | ``` 14 | 15 | ## Usage 16 | 17 | ``` shell 18 | ./bin/client 19 | ``` 20 | 21 | ## Thanks 22 | 23 | - [libevent](http://libevent.org/) 24 | 25 | - [b64.c](https://github.com/littlstar/b64.c) 26 | 27 | - [log.c](https://github.com/rxi/log.c) 28 | 29 | - [parson](https://github.com/kgabis/parson) 30 | -------------------------------------------------------------------------------- /client/client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by leer on 6/28/18. 3 | **/ 4 | #include "client.h" 5 | #include "../lib/log.h" 6 | #include "../lib/parson.h" 7 | #include "../lib/password.h" 8 | #include "../lib/securesocket.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #ifdef _WIN32 19 | #include 20 | #include 21 | #else 22 | // For inet_addr 23 | #include 24 | #include 25 | #include 26 | #endif 27 | 28 | typedef struct { 29 | bufferevent *remote_bev; 30 | bufferevent *local_bev; 31 | } Client; 32 | 33 | static event_base *base = NULL; 34 | static SecureSocket *ss = NULL; 35 | 36 | void remote_readcb(bufferevent *remote_bev, void *arg) { 37 | log_t("read from remote"); 38 | Client *client = (Client *)arg; 39 | check(client, "null context"); 40 | bufferevent *local_bev = client->local_bev; 41 | // read data from remote, decode then write to local. 42 | check(decode_copy(ss, local_bev, remote_bev) != -1, "close all connection"); 43 | return; 44 | error: 45 | bufferevent_clear_free(local_bev); 46 | bufferevent_clear_free(remote_bev); 47 | } 48 | 49 | void local_readcb(bufferevent *bev, void *arg) { 50 | log_t("read from local"); 51 | Client *client = (Client *)arg; 52 | check(client, "null context"); 53 | bufferevent *remote_bev = client->remote_bev; 54 | 55 | // encode data then write to remote 56 | check(encode_copy(ss, remote_bev, bev) != -1, "close all connection"); 57 | return; 58 | error: 59 | bufferevent_clear_free(bev); 60 | bufferevent_clear_free(remote_bev); 61 | } 62 | 63 | void local_eventcb(bufferevent *bev, short events, void *arg) { 64 | if (events && (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { 65 | // event_base *base = arg; 66 | Client *client = (Client *)arg; 67 | if (bev) { 68 | bufferevent_clear_free(bev); // client->local_bev 69 | bufferevent_clear_free(client->remote_bev); 70 | if (client) { 71 | free(client); 72 | } 73 | } 74 | if (events & BEV_EVENT_EOF) { 75 | log_d("connection %d closed", bufferevent_getfd(bev)); 76 | } else if (events & BEV_EVENT_ERROR) { 77 | log_e("got an error on the connection"); 78 | } 79 | } 80 | } 81 | 82 | void local_listener_cb(evconnlistener *listener, evutil_socket_t fd, 83 | struct sockaddr *sa, int socklen, void *arg) { 84 | // set nonblocking 85 | check(evutil_make_socket_nonblocking(fd) == 0, "can't make no blocking"); 86 | // no waiting for unsent data before closing socketing 87 | struct linger linger; 88 | memset(&linger, 0, sizeof(struct linger)); 89 | check(setsockopt(fd, SOL_SOCKET, SO_LINGER, (const void *)&linger, 90 | sizeof(struct linger)) == 0, 91 | "can't disable linger"); 92 | 93 | // each connection has a client. 94 | Client *client = calloc(1, sizeof(Client)); 95 | ss = (SecureSocket *)arg; 96 | 97 | bufferevent *bufev, *remote_bev; 98 | bufev = bufferevent_socket_new( 99 | base, fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 100 | log_d("new client conncted"); 101 | 102 | remote_bev = bufferevent_socket_new( 103 | base, -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 104 | 105 | int rc = 106 | bufferevent_socket_connect(remote_bev, (struct sockaddr *)ss->remote_addr, 107 | sizeof(struct sockaddr_in)); 108 | check(rc != -1, "can't connect proxy server"); 109 | log_d("connected to proxy server"); 110 | 111 | int remotefd = bufferevent_getfd(remote_bev); 112 | check(setsockopt(remotefd, SOL_SOCKET, SO_LINGER, (const void *)&linger, 113 | sizeof(struct linger)) == 0, 114 | "can't disable linger"); 115 | 116 | client->local_bev = bufev; 117 | client->remote_bev = remote_bev; 118 | 119 | bufferevent_setcb(bufev, local_readcb, NULL, local_eventcb, client); 120 | bufferevent_enable(bufev, EV_READ | EV_WRITE); 121 | bufferevent_setcb(remote_bev, remote_readcb, NULL, NULL, client); 122 | bufferevent_enable(remote_bev, EV_READ | EV_WRITE); 123 | return; 124 | error: 125 | log_d("close all connection"); 126 | bufferevent_clear_free(bufev); 127 | bufferevent_clear_free(remote_bev); 128 | } 129 | 130 | void listener_errorcb(evconnlistener *listener, void *arg) { 131 | log_e("listen error, exit"); 132 | event_base_loopbreak(base); 133 | } 134 | 135 | void signal_cb(evutil_socket_t sig, short events, void *user_data) { 136 | event_base *base = user_data; 137 | struct timeval delay = {1, 0}; 138 | 139 | log_d( 140 | "caught an interrupt signal; exiting cleanly in one " 141 | "seconds"); 142 | 143 | event_base_loopexit(base, &delay); 144 | } 145 | 146 | // todo this is stupid.. 147 | int main(int argc, const char *argv[]) { 148 | log_set_level(LOG_DEBUG); 149 | check(argc == 1 || argc == 2, "number of args error, required 0 or 1 arg"); 150 | log_d("lightsocks-local: starting..."); 151 | ss = calloc(1, sizeof(SecureSocket)); 152 | event *signal_event = NULL; 153 | evconnlistener *listener = NULL; 154 | 155 | int local_port, server_port; 156 | const char *server_addr = NULL; 157 | const char *password_str = NULL; 158 | 159 | JSON_Value *schema = json_parse_string( 160 | "{\"local_port\":0,\"server_addr\":\"\",\"server_" 161 | "port\":0,\"password\":\"\"}"); 162 | 163 | JSON_Value *data = NULL; 164 | data = (argc == 1) ? json_parse_file(".lightsocks-config.json") 165 | : json_parse_file(argv[1]); 166 | check(data, "null json"); 167 | check(json_validate(schema, data) == JSONSuccess, "schema not match"); 168 | 169 | local_port = json_object_get_number((json_object(data)), "local_port"); 170 | server_addr = json_object_get_string((json_object(data)), "server_addr"); 171 | server_port = json_object_get_number(json_object(data), "server_port"); 172 | password_str = json_object_get_string((json_object(data)), "password"); 173 | 174 | Password *password = 175 | gen_password_by_string(password_str, strlen(password_str)); 176 | ss->password = password; 177 | sockaddr_in local; // listen to local 178 | memset(&local, 0, sizeof(sockaddr_in)); 179 | local.sin_family = AF_INET; 180 | local.sin_port = htons(local_port); 181 | local.sin_addr.s_addr = htonl(INADDR_ANY); 182 | ss->local_addr = &local; 183 | 184 | sockaddr_in remote; // connect to remote 185 | memset(&remote, 0, sizeof(sockaddr_in)); 186 | remote.sin_family = AF_INET; 187 | remote.sin_port = htons(server_port); 188 | remote.sin_addr.s_addr = inet_addr(server_addr); 189 | ss->remote_addr = &remote; 190 | 191 | base = event_base_new(); 192 | check(base, "event base error"); 193 | listener = evconnlistener_new_bind( 194 | base, local_listener_cb, ss, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 195 | 16, (struct sockaddr *)ss->local_addr, sizeof(local)); 196 | evconnlistener_set_error_cb(listener, listener_errorcb); 197 | check(listener, "listen error"); 198 | 199 | log_d("\nListen on [::]:%d\nRemote:%s:%d\nPassword:\n%s", local_port, 200 | server_addr, server_port, password_string(password, NULL)); 201 | 202 | // now there's no reason to keep json string 203 | json_value_free(schema); 204 | json_value_free(data); 205 | // add Ctrl-C signal event 206 | signal_event = evsignal_new(base, SIGINT, signal_cb, base); 207 | check(signal_event && event_add(signal_event, NULL) == 0, 208 | "signal even error"); 209 | 210 | event_base_dispatch(base); 211 | 212 | securesocket_free(ss); 213 | if (listener) { 214 | evconnlistener_free(listener); 215 | } 216 | if (signal_event) { 217 | event_free(signal_event); 218 | } 219 | event_base_free(base); 220 | log_w("lightsocks-loacl: exit(0)"); 221 | return 0; 222 | 223 | error: // fallthrough 224 | log_w("lightsocks-loacl: exit(1)"); 225 | if (schema) { 226 | json_value_free(schema); 227 | } 228 | if (data) { 229 | json_value_free(data); 230 | } 231 | securesocket_free(ss); 232 | if (listener) { 233 | evconnlistener_free(listener); 234 | } 235 | if (signal_event) { 236 | event_free(signal_event); 237 | } 238 | event_base_free(base); 239 | return -1; 240 | } -------------------------------------------------------------------------------- /client/client.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLIENT_H__ 2 | #define __CLIENT_H__ 3 | #include 4 | #include 5 | typedef struct event_base event_base; 6 | typedef struct event event; 7 | typedef struct evconnlistener evconnlistener; 8 | 9 | #endif -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "local_port": 2333, 3 | "server_addr": "1.2.3.4", 4 | "server_port": 8080, 5 | "password": "ooccDJX8EwaTL5I1JY9B4k1cc52XTxoQWSRSKZmBuBfLoG76qip8tnXpfQVesPlbO4hMx82LbOEr84yYdKtnMLwRMRvkZp4yWgPo4K08hNUtYnb+09KAz6/Jo843oaUAfpphxgG3te/epycPOjPsw2D1g1UJf44IVLmGpq7acpsuBxVoRcL4iWOfCj6sqYpH3MHY0LPx64K9tFhAHxhLwIV7Rv8/kOfFV04S8HekkWq+NFAU48TfyvL0XxYO5hlKegTI1ybdzFZpRO731rEC1EKUb7sjbT2oIB44sihwItFdQ/vZ7WtJcVPqHf2/SLp4IQ3lLJbbOXlRjQucNmRl9g==" 6 | } -------------------------------------------------------------------------------- /lib/base64.c: -------------------------------------------------------------------------------- 1 | #include "base64.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef b64_USE_CUSTOM_MALLOC 9 | extern void *b64_malloc(size_t); 10 | #endif 11 | 12 | #ifdef b64_USE_CUSTOM_REALLOC 13 | extern void *b64_realloc(void *, size_t); 14 | #endif 15 | 16 | unsigned char *b64_decode(const char *src, size_t len) { 17 | return b64_decode_ex(src, len, NULL); 18 | } 19 | 20 | unsigned char *b64_decode_ex(const char *src, size_t len, size_t *decsize) { 21 | int i = 0; 22 | int j = 0; 23 | int l = 0; 24 | size_t size = 0; 25 | unsigned char *dec = NULL; 26 | unsigned char buf[3]; 27 | unsigned char tmp[4]; 28 | 29 | // alloc 30 | dec = (unsigned char *)b64_malloc(1); 31 | if (NULL == dec) { 32 | return NULL; 33 | } 34 | 35 | // parse until end of source 36 | while (len--) { 37 | // break if char is `=' or not base64 char 38 | if ('=' == src[j]) { 39 | break; 40 | } 41 | if (!(isalnum(src[j]) || '+' == src[j] || '/' == src[j])) { 42 | break; 43 | } 44 | 45 | // read up to 4 bytes at a time into `tmp' 46 | tmp[i++] = src[j++]; 47 | 48 | // if 4 bytes read then decode into `buf' 49 | if (4 == i) { 50 | // translate values in `tmp' from table 51 | for (i = 0; i < 4; ++i) { 52 | // find translation char in `b64_table' 53 | for (l = 0; l < 64; ++l) { 54 | if (tmp[i] == b64_table[l]) { 55 | tmp[i] = l; 56 | break; 57 | } 58 | } 59 | } 60 | 61 | // decode 62 | buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); 63 | buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); 64 | buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; 65 | 66 | // write decoded buffer to `dec' 67 | dec = (unsigned char *)b64_realloc(dec, size + 3); 68 | if (dec != NULL) { 69 | for (i = 0; i < 3; ++i) { 70 | dec[size++] = buf[i]; 71 | } 72 | } else { 73 | return NULL; 74 | } 75 | 76 | // reset 77 | i = 0; 78 | } 79 | } 80 | 81 | // remainder 82 | if (i > 0) { 83 | // fill `tmp' with `\0' at most 4 times 84 | for (j = i; j < 4; ++j) { 85 | tmp[j] = '\0'; 86 | } 87 | 88 | // translate remainder 89 | for (j = 0; j < 4; ++j) { 90 | // find translation char in `b64_table' 91 | for (l = 0; l < 64; ++l) { 92 | if (tmp[j] == b64_table[l]) { 93 | tmp[j] = l; 94 | break; 95 | } 96 | } 97 | } 98 | 99 | // decode remainder 100 | buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); 101 | buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); 102 | buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; 103 | 104 | // write remainer decoded buffer to `dec' 105 | dec = (unsigned char *)b64_realloc(dec, size + (i - 1)); 106 | if (dec != NULL) { 107 | for (j = 0; (j < i - 1); ++j) { 108 | dec[size++] = buf[j]; 109 | } 110 | } else { 111 | return NULL; 112 | } 113 | } 114 | 115 | // Make sure we have enough space to add '\0' character at end. 116 | dec = (unsigned char *)b64_realloc(dec, size + 1); 117 | if (dec != NULL) { 118 | dec[size] = '\0'; 119 | } else { 120 | return NULL; 121 | } 122 | 123 | // Return back the size of decoded string if demanded. 124 | if (decsize != NULL) { 125 | *decsize = size; 126 | } 127 | 128 | return dec; 129 | } 130 | 131 | char *b64_encode(const unsigned char *src, size_t len, size_t *encsize) { 132 | int i = 0; 133 | int j = 0; 134 | char *enc = NULL; 135 | size_t size = 0; 136 | unsigned char buf[4]; 137 | unsigned char tmp[3]; 138 | 139 | // alloc 140 | enc = (char *)b64_malloc(1); 141 | if (NULL == enc) { 142 | return NULL; 143 | } 144 | 145 | // parse until end of source 146 | while (len--) { 147 | // read up to 3 bytes at a time into `tmp' 148 | tmp[i++] = *(src++); 149 | 150 | // if 3 bytes read then encode into `buf' 151 | if (3 == i) { 152 | buf[0] = (tmp[0] & 0xfc) >> 2; 153 | buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); 154 | buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); 155 | buf[3] = tmp[2] & 0x3f; 156 | 157 | // allocate 4 new byts for `enc` and 158 | // then translate each encoded buffer 159 | // part by index from the base 64 index table 160 | // into `enc' unsigned char array 161 | enc = (char *)b64_realloc(enc, size + 4); 162 | for (i = 0; i < 4; ++i) { 163 | enc[size++] = b64_table[buf[i]]; 164 | } 165 | 166 | // reset index 167 | i = 0; 168 | } 169 | } 170 | 171 | // remainder 172 | if (i > 0) { 173 | // fill `tmp' with `\0' at most 3 times 174 | for (j = i; j < 3; ++j) { 175 | tmp[j] = '\0'; 176 | } 177 | 178 | // perform same codec as above 179 | buf[0] = (tmp[0] & 0xfc) >> 2; 180 | buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); 181 | buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); 182 | buf[3] = tmp[2] & 0x3f; 183 | 184 | // perform same write to `enc` with new allocation 185 | for (j = 0; (j < i + 1); ++j) { 186 | enc = (char *)b64_realloc(enc, size + 1); 187 | enc[size++] = b64_table[buf[j]]; 188 | } 189 | 190 | // while there is still a remainder 191 | // append `=' to `enc' 192 | while ((i++ < 3)) { 193 | enc = (char *)b64_realloc(enc, size + 1); 194 | enc[size++] = '='; 195 | } 196 | } 197 | 198 | // Make sure we have enough space to add '\0' character at end. 199 | enc = (char *)b64_realloc(enc, size + 1); 200 | enc[size] = '\0'; 201 | 202 | if (encsize != NULL) { 203 | *encsize = size; 204 | } 205 | return enc; 206 | } -------------------------------------------------------------------------------- /lib/base64.h: -------------------------------------------------------------------------------- 1 | #ifndef __BASE64_H__ 2 | #define __BASE64_H__ 3 | 4 | /** 5 | * `b64.h' - b64 6 | * 7 | * copyright (c) 2014 joseph werle 8 | * modify by leer 9 | */ 10 | #include 11 | #include 12 | /** 13 | * Memory allocation functions to use. You can define b64_malloc and 14 | * b64_realloc to custom functions if you want. 15 | */ 16 | 17 | #ifndef b64_malloc 18 | #define b64_malloc(ptr) malloc(ptr) 19 | #endif 20 | #ifndef b64_realloc 21 | #define b64_realloc(ptr, size) realloc(ptr, size) 22 | #endif 23 | 24 | /** 25 | * Base64 index table. 26 | */ 27 | 28 | static const char b64_table[] = { 29 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 30 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 31 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 32 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 33 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** 40 | * Encode `unsigned char *' source with `size_t' size. 41 | * Returns a `char *' base64 encoded string. 42 | */ 43 | 44 | char *b64_encode(const unsigned char *, size_t len, size_t *encsize); 45 | 46 | /** 47 | * Dencode `char *' source with `size_t' size. 48 | * Returns a `unsigned char *' base64 decoded string. 49 | */ 50 | unsigned char *b64_decode(const char *, size_t len); 51 | 52 | /** 53 | * Dencode `char *' source with `size_t' size. 54 | * Returns a `unsigned char *' base64 decoded string + size of decoded string. 55 | */ 56 | unsigned char *b64_decode_ex(const char *, size_t len, size_t *decsize); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | #endif -------------------------------------------------------------------------------- /lib/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 rxi 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "log.h" 30 | 31 | static struct { 32 | void *udata; 33 | log_LockFn lock; 34 | FILE *fp; 35 | int level; 36 | int quiet; 37 | } L; 38 | 39 | static const char *level_names[] = {"TRACE", "DEBUG", "INFO", 40 | "WARN", "ERROR", "FATAL"}; 41 | 42 | #ifdef LOG_USE_COLOR 43 | static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", 44 | "\x1b[33m", "\x1b[31m", "\x1b[35m"}; 45 | #endif 46 | 47 | static void lock(void) { 48 | if (L.lock) { 49 | L.lock(L.udata, 1); 50 | } 51 | } 52 | 53 | static void unlock(void) { 54 | if (L.lock) { 55 | L.lock(L.udata, 0); 56 | } 57 | } 58 | 59 | void log_set_udata(void *udata) { L.udata = udata; } 60 | 61 | void log_set_lock(log_LockFn fn) { L.lock = fn; } 62 | 63 | void log_set_fp(FILE *fp) { L.fp = fp; } 64 | 65 | void log_set_level(int level) { L.level = level; } 66 | 67 | void log_set_quiet(int enable) { L.quiet = enable ? 1 : 0; } 68 | 69 | void log_log(int level, const char *file, int line, const char *fmt, ...) { 70 | if (level < L.level) { 71 | return; 72 | } 73 | 74 | /* Acquire lock */ 75 | lock(); 76 | 77 | /* Get current time */ 78 | time_t t = time(NULL); 79 | struct tm *lt = localtime(&t); 80 | 81 | /* Log to stderr */ 82 | if (!L.quiet) { 83 | va_list args; 84 | char buf[16]; 85 | buf[strftime(buf, sizeof(buf), "%H:%M:%S", lt)] = '\0'; 86 | #ifdef LOG_USE_COLOR 87 | fprintf(stderr, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buf, 88 | level_colors[level], level_names[level], file, line); 89 | #else 90 | fprintf(stderr, "%s %-5s %s:%d: ", buf, level_names[level], file, line); 91 | #endif 92 | va_start(args, fmt); 93 | vfprintf(stderr, fmt, args); 94 | va_end(args); 95 | fprintf(stderr, "\n"); 96 | } 97 | 98 | /* Log to file */ 99 | if (L.fp) { 100 | va_list args; 101 | char buf[32]; 102 | buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0'; 103 | fprintf(L.fp, "%s %-5s %s:%d: ", buf, level_names[level], file, line); 104 | va_start(args, fmt); 105 | vfprintf(L.fp, fmt, args); 106 | va_end(args); 107 | fprintf(L.fp, "\n"); 108 | } 109 | 110 | /* Release lock */ 111 | unlock(); 112 | } 113 | -------------------------------------------------------------------------------- /lib/log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017 rxi 3 | * 4 | * This library is free software; you can redistribute it and/or modify it 5 | * under the terms of the MIT license. See `log.c` for details. 6 | */ 7 | 8 | #ifndef LOG_H 9 | #define LOG_H 10 | 11 | #include 12 | #include 13 | 14 | #define LOG_VERSION "0.1.0" 15 | 16 | typedef void (*log_LockFn)(void *udata, int lock); 17 | 18 | enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; 19 | 20 | #define log_t(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) 21 | #define log_d(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) 22 | #define log_i(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) 23 | #define log_w(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) 24 | #define log_e(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) 25 | #define log_f(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) 26 | #define check(A, ...) \ 27 | if (!(A)) { \ 28 | log_e(__VA_ARGS__); \ 29 | goto error; \ 30 | } 31 | 32 | void log_set_udata(void *udata); 33 | void log_set_lock(log_LockFn fn); 34 | void log_set_fp(FILE *fp); 35 | void log_set_level(int level); 36 | void log_set_quiet(int enable); 37 | 38 | void log_log(int level, const char *file, int line, const char *fmt, ...); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /lib/parson.c: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (c) 2012 - 2017 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | #ifdef _MSC_VER 24 | #ifndef _CRT_SECURE_NO_WARNINGS 25 | #define _CRT_SECURE_NO_WARNINGS 26 | #endif /* _CRT_SECURE_NO_WARNINGS */ 27 | #endif /* _MSC_VER */ 28 | 29 | #include "parson.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you 39 | * don't have to. */ 40 | #define sscanf THINK_TWICE_ABOUT_USING_SSCANF 41 | 42 | #define STARTING_CAPACITY 16 43 | #define MAX_NESTING 2048 44 | 45 | #define FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */ 46 | #define NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */ 47 | 48 | #define SIZEOF_TOKEN(a) (sizeof(a) - 1) 49 | #define SKIP_CHAR(str) ((*str)++) 50 | #define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); } 51 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 52 | 53 | #undef malloc 54 | #undef free 55 | 56 | static JSON_Malloc_Function parson_malloc = malloc; 57 | static JSON_Free_Function parson_free = free; 58 | 59 | #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ 60 | 61 | /* Type definitions */ 62 | typedef union json_value_value { 63 | char *string; 64 | double number; 65 | JSON_Object *object; 66 | JSON_Array *array; 67 | int boolean; 68 | int null; 69 | } JSON_Value_Value; 70 | 71 | struct json_value_t { 72 | JSON_Value *parent; 73 | JSON_Value_Type type; 74 | JSON_Value_Value value; 75 | }; 76 | 77 | struct json_object_t { 78 | JSON_Value *wrapping_value; 79 | char **names; 80 | JSON_Value **values; 81 | size_t count; 82 | size_t capacity; 83 | }; 84 | 85 | struct json_array_t { 86 | JSON_Value *wrapping_value; 87 | JSON_Value **items; 88 | size_t count; 89 | size_t capacity; 90 | }; 91 | 92 | /* Various */ 93 | static char * read_file(const char *filename); 94 | static void remove_comments(char *string, const char *start_token, const char *end_token); 95 | static char * parson_strndup(const char *string, size_t n); 96 | static char * parson_strdup(const char *string); 97 | static int hex_char_to_int(char c); 98 | static int parse_utf16_hex(const char *string, unsigned int *result); 99 | static int num_bytes_in_utf8_sequence(unsigned char c); 100 | static int verify_utf8_sequence(const unsigned char *string, int *len); 101 | static int is_valid_utf8(const char *string, size_t string_len); 102 | static int is_decimal(const char *string, size_t length); 103 | 104 | /* JSON Object */ 105 | static JSON_Object * json_object_init(JSON_Value *wrapping_value); 106 | static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value); 107 | static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity); 108 | static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n); 109 | static void json_object_free(JSON_Object *object); 110 | 111 | /* JSON Array */ 112 | static JSON_Array * json_array_init(JSON_Value *wrapping_value); 113 | static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value); 114 | static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity); 115 | static void json_array_free(JSON_Array *array); 116 | 117 | /* JSON Value */ 118 | static JSON_Value * json_value_init_string_no_copy(char *string); 119 | 120 | /* Parser */ 121 | static JSON_Status skip_quotes(const char **string); 122 | static int parse_utf16(const char **unprocessed, char **processed); 123 | static char * process_string(const char *input, size_t len); 124 | static char * get_quoted_string(const char **string); 125 | static JSON_Value * parse_object_value(const char **string, size_t nesting); 126 | static JSON_Value * parse_array_value(const char **string, size_t nesting); 127 | static JSON_Value * parse_string_value(const char **string); 128 | static JSON_Value * parse_boolean_value(const char **string); 129 | static JSON_Value * parse_number_value(const char **string); 130 | static JSON_Value * parse_null_value(const char **string); 131 | static JSON_Value * parse_value(const char **string, size_t nesting); 132 | 133 | /* Serialization */ 134 | static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); 135 | static int json_serialize_string(const char *string, char *buf); 136 | static int append_indent(char *buf, int level); 137 | static int append_string(char *buf, const char *string); 138 | 139 | /* Various */ 140 | static char * parson_strndup(const char *string, size_t n) { 141 | char *output_string = (char*)parson_malloc(n + 1); 142 | if (!output_string) { 143 | return NULL; 144 | } 145 | output_string[n] = '\0'; 146 | strncpy(output_string, string, n); 147 | return output_string; 148 | } 149 | 150 | static char * parson_strdup(const char *string) { 151 | return parson_strndup(string, strlen(string)); 152 | } 153 | 154 | static int hex_char_to_int(char c) { 155 | if (c >= '0' && c <= '9') { 156 | return c - '0'; 157 | } else if (c >= 'a' && c <= 'f') { 158 | return c - 'a' + 10; 159 | } else if (c >= 'A' && c <= 'F') { 160 | return c - 'A' + 10; 161 | } 162 | return -1; 163 | } 164 | 165 | static int parse_utf16_hex(const char *s, unsigned int *result) { 166 | int x1, x2, x3, x4; 167 | if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') { 168 | return 0; 169 | } 170 | x1 = hex_char_to_int(s[0]); 171 | x2 = hex_char_to_int(s[1]); 172 | x3 = hex_char_to_int(s[2]); 173 | x4 = hex_char_to_int(s[3]); 174 | if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) { 175 | return 0; 176 | } 177 | *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4); 178 | return 1; 179 | } 180 | 181 | static int num_bytes_in_utf8_sequence(unsigned char c) { 182 | if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) { 183 | return 0; 184 | } else if ((c & 0x80) == 0) { /* 0xxxxxxx */ 185 | return 1; 186 | } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */ 187 | return 2; 188 | } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */ 189 | return 3; 190 | } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */ 191 | return 4; 192 | } 193 | return 0; /* won't happen */ 194 | } 195 | 196 | static int verify_utf8_sequence(const unsigned char *string, int *len) { 197 | unsigned int cp = 0; 198 | *len = num_bytes_in_utf8_sequence(string[0]); 199 | 200 | if (*len == 1) { 201 | cp = string[0]; 202 | } else if (*len == 2 && IS_CONT(string[1])) { 203 | cp = string[0] & 0x1F; 204 | cp = (cp << 6) | (string[1] & 0x3F); 205 | } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) { 206 | cp = ((unsigned char)string[0]) & 0xF; 207 | cp = (cp << 6) | (string[1] & 0x3F); 208 | cp = (cp << 6) | (string[2] & 0x3F); 209 | } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) { 210 | cp = string[0] & 0x7; 211 | cp = (cp << 6) | (string[1] & 0x3F); 212 | cp = (cp << 6) | (string[2] & 0x3F); 213 | cp = (cp << 6) | (string[3] & 0x3F); 214 | } else { 215 | return 0; 216 | } 217 | 218 | /* overlong encodings */ 219 | if ((cp < 0x80 && *len > 1) || 220 | (cp < 0x800 && *len > 2) || 221 | (cp < 0x10000 && *len > 3)) { 222 | return 0; 223 | } 224 | 225 | /* invalid unicode */ 226 | if (cp > 0x10FFFF) { 227 | return 0; 228 | } 229 | 230 | /* surrogate halves */ 231 | if (cp >= 0xD800 && cp <= 0xDFFF) { 232 | return 0; 233 | } 234 | 235 | return 1; 236 | } 237 | 238 | static int is_valid_utf8(const char *string, size_t string_len) { 239 | int len = 0; 240 | const char *string_end = string + string_len; 241 | while (string < string_end) { 242 | if (!verify_utf8_sequence((const unsigned char*)string, &len)) { 243 | return 0; 244 | } 245 | string += len; 246 | } 247 | return 1; 248 | } 249 | 250 | static int is_decimal(const char *string, size_t length) { 251 | if (length > 1 && string[0] == '0' && string[1] != '.') { 252 | return 0; 253 | } 254 | if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') { 255 | return 0; 256 | } 257 | while (length--) { 258 | if (strchr("xX", string[length])) { 259 | return 0; 260 | } 261 | } 262 | return 1; 263 | } 264 | 265 | static char * read_file(const char * filename) { 266 | FILE *fp = fopen(filename, "r"); 267 | size_t size_to_read = 0; 268 | size_t size_read = 0; 269 | long pos; 270 | char *file_contents; 271 | if (!fp) { 272 | return NULL; 273 | } 274 | fseek(fp, 0L, SEEK_END); 275 | pos = ftell(fp); 276 | if (pos < 0) { 277 | fclose(fp); 278 | return NULL; 279 | } 280 | size_to_read = pos; 281 | rewind(fp); 282 | file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1)); 283 | if (!file_contents) { 284 | fclose(fp); 285 | return NULL; 286 | } 287 | size_read = fread(file_contents, 1, size_to_read, fp); 288 | if (size_read == 0 || ferror(fp)) { 289 | fclose(fp); 290 | parson_free(file_contents); 291 | return NULL; 292 | } 293 | fclose(fp); 294 | file_contents[size_read] = '\0'; 295 | return file_contents; 296 | } 297 | 298 | static void remove_comments(char *string, const char *start_token, const char *end_token) { 299 | int in_string = 0, escaped = 0; 300 | size_t i; 301 | char *ptr = NULL, current_char; 302 | size_t start_token_len = strlen(start_token); 303 | size_t end_token_len = strlen(end_token); 304 | if (start_token_len == 0 || end_token_len == 0) { 305 | return; 306 | } 307 | while ((current_char = *string) != '\0') { 308 | if (current_char == '\\' && !escaped) { 309 | escaped = 1; 310 | string++; 311 | continue; 312 | } else if (current_char == '\"' && !escaped) { 313 | in_string = !in_string; 314 | } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) { 315 | for(i = 0; i < start_token_len; i++) { 316 | string[i] = ' '; 317 | } 318 | string = string + start_token_len; 319 | ptr = strstr(string, end_token); 320 | if (!ptr) { 321 | return; 322 | } 323 | for (i = 0; i < (ptr - string) + end_token_len; i++) { 324 | string[i] = ' '; 325 | } 326 | string = ptr + end_token_len - 1; 327 | } 328 | escaped = 0; 329 | string++; 330 | } 331 | } 332 | 333 | /* JSON Object */ 334 | static JSON_Object * json_object_init(JSON_Value *wrapping_value) { 335 | JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object)); 336 | if (new_obj == NULL) { 337 | return NULL; 338 | } 339 | new_obj->wrapping_value = wrapping_value; 340 | new_obj->names = (char**)NULL; 341 | new_obj->values = (JSON_Value**)NULL; 342 | new_obj->capacity = 0; 343 | new_obj->count = 0; 344 | return new_obj; 345 | } 346 | 347 | static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) { 348 | size_t index = 0; 349 | if (object == NULL || name == NULL || value == NULL) { 350 | return JSONFailure; 351 | } 352 | if (json_object_get_value(object, name) != NULL) { 353 | return JSONFailure; 354 | } 355 | if (object->count >= object->capacity) { 356 | size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY); 357 | if (json_object_resize(object, new_capacity) == JSONFailure) { 358 | return JSONFailure; 359 | } 360 | } 361 | index = object->count; 362 | object->names[index] = parson_strdup(name); 363 | if (object->names[index] == NULL) { 364 | return JSONFailure; 365 | } 366 | value->parent = json_object_get_wrapping_value(object); 367 | object->values[index] = value; 368 | object->count++; 369 | return JSONSuccess; 370 | } 371 | 372 | static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) { 373 | char **temp_names = NULL; 374 | JSON_Value **temp_values = NULL; 375 | 376 | if ((object->names == NULL && object->values != NULL) || 377 | (object->names != NULL && object->values == NULL) || 378 | new_capacity == 0) { 379 | return JSONFailure; /* Shouldn't happen */ 380 | } 381 | temp_names = (char**)parson_malloc(new_capacity * sizeof(char*)); 382 | if (temp_names == NULL) { 383 | return JSONFailure; 384 | } 385 | temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); 386 | if (temp_values == NULL) { 387 | parson_free(temp_names); 388 | return JSONFailure; 389 | } 390 | if (object->names != NULL && object->values != NULL && object->count > 0) { 391 | memcpy(temp_names, object->names, object->count * sizeof(char*)); 392 | memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*)); 393 | } 394 | parson_free(object->names); 395 | parson_free(object->values); 396 | object->names = temp_names; 397 | object->values = temp_values; 398 | object->capacity = new_capacity; 399 | return JSONSuccess; 400 | } 401 | 402 | static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) { 403 | size_t i, name_length; 404 | for (i = 0; i < json_object_get_count(object); i++) { 405 | name_length = strlen(object->names[i]); 406 | if (name_length != n) { 407 | continue; 408 | } 409 | if (strncmp(object->names[i], name, n) == 0) { 410 | return object->values[i]; 411 | } 412 | } 413 | return NULL; 414 | } 415 | 416 | static void json_object_free(JSON_Object *object) { 417 | size_t i; 418 | for (i = 0; i < object->count; i++) { 419 | parson_free(object->names[i]); 420 | json_value_free(object->values[i]); 421 | } 422 | parson_free(object->names); 423 | parson_free(object->values); 424 | parson_free(object); 425 | } 426 | 427 | /* JSON Array */ 428 | static JSON_Array * json_array_init(JSON_Value *wrapping_value) { 429 | JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array)); 430 | if (new_array == NULL) { 431 | return NULL; 432 | } 433 | new_array->wrapping_value = wrapping_value; 434 | new_array->items = (JSON_Value**)NULL; 435 | new_array->capacity = 0; 436 | new_array->count = 0; 437 | return new_array; 438 | } 439 | 440 | static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) { 441 | if (array->count >= array->capacity) { 442 | size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY); 443 | if (json_array_resize(array, new_capacity) == JSONFailure) { 444 | return JSONFailure; 445 | } 446 | } 447 | value->parent = json_array_get_wrapping_value(array); 448 | array->items[array->count] = value; 449 | array->count++; 450 | return JSONSuccess; 451 | } 452 | 453 | static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) { 454 | JSON_Value **new_items = NULL; 455 | if (new_capacity == 0) { 456 | return JSONFailure; 457 | } 458 | new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*)); 459 | if (new_items == NULL) { 460 | return JSONFailure; 461 | } 462 | if (array->items != NULL && array->count > 0) { 463 | memcpy(new_items, array->items, array->count * sizeof(JSON_Value*)); 464 | } 465 | parson_free(array->items); 466 | array->items = new_items; 467 | array->capacity = new_capacity; 468 | return JSONSuccess; 469 | } 470 | 471 | static void json_array_free(JSON_Array *array) { 472 | size_t i; 473 | for (i = 0; i < array->count; i++) { 474 | json_value_free(array->items[i]); 475 | } 476 | parson_free(array->items); 477 | parson_free(array); 478 | } 479 | 480 | /* JSON Value */ 481 | static JSON_Value * json_value_init_string_no_copy(char *string) { 482 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 483 | if (!new_value) { 484 | return NULL; 485 | } 486 | new_value->parent = NULL; 487 | new_value->type = JSONString; 488 | new_value->value.string = string; 489 | return new_value; 490 | } 491 | 492 | /* Parser */ 493 | static JSON_Status skip_quotes(const char **string) { 494 | if (**string != '\"') { 495 | return JSONFailure; 496 | } 497 | SKIP_CHAR(string); 498 | while (**string != '\"') { 499 | if (**string == '\0') { 500 | return JSONFailure; 501 | } else if (**string == '\\') { 502 | SKIP_CHAR(string); 503 | if (**string == '\0') { 504 | return JSONFailure; 505 | } 506 | } 507 | SKIP_CHAR(string); 508 | } 509 | SKIP_CHAR(string); 510 | return JSONSuccess; 511 | } 512 | 513 | static int parse_utf16(const char **unprocessed, char **processed) { 514 | unsigned int cp, lead, trail; 515 | int parse_succeeded = 0; 516 | char *processed_ptr = *processed; 517 | const char *unprocessed_ptr = *unprocessed; 518 | unprocessed_ptr++; /* skips u */ 519 | parse_succeeded = parse_utf16_hex(unprocessed_ptr, &cp); 520 | if (!parse_succeeded) { 521 | return JSONFailure; 522 | } 523 | if (cp < 0x80) { 524 | processed_ptr[0] = (char)cp; /* 0xxxxxxx */ 525 | } else if (cp < 0x800) { 526 | processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */ 527 | processed_ptr[1] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */ 528 | processed_ptr += 1; 529 | } else if (cp < 0xD800 || cp > 0xDFFF) { 530 | processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */ 531 | processed_ptr[1] = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */ 532 | processed_ptr[2] = ((cp) & 0x3F) | 0x80; /* 10xxxxxx */ 533 | processed_ptr += 2; 534 | } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */ 535 | lead = cp; 536 | unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */ 537 | if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') { 538 | return JSONFailure; 539 | } 540 | parse_succeeded = parse_utf16_hex(unprocessed_ptr, &trail); 541 | if (!parse_succeeded || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */ 542 | return JSONFailure; 543 | } 544 | cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000; 545 | processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */ 546 | processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */ 547 | processed_ptr[2] = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */ 548 | processed_ptr[3] = (((cp) & 0x3F) | 0x80); /* 10xxxxxx */ 549 | processed_ptr += 3; 550 | } else { /* trail surrogate before lead surrogate */ 551 | return JSONFailure; 552 | } 553 | unprocessed_ptr += 3; 554 | *processed = processed_ptr; 555 | *unprocessed = unprocessed_ptr; 556 | return JSONSuccess; 557 | } 558 | 559 | 560 | /* Copies and processes passed string up to supplied length. 561 | Example: "\u006Corem ipsum" -> lorem ipsum */ 562 | static char* process_string(const char *input, size_t len) { 563 | const char *input_ptr = input; 564 | size_t initial_size = (len + 1) * sizeof(char); 565 | size_t final_size = 0; 566 | char *output = NULL, *output_ptr = NULL, *resized_output = NULL; 567 | output = (char*)parson_malloc(initial_size); 568 | if (output == NULL) { 569 | goto error; 570 | } 571 | output_ptr = output; 572 | while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) { 573 | if (*input_ptr == '\\') { 574 | input_ptr++; 575 | switch (*input_ptr) { 576 | case '\"': *output_ptr = '\"'; break; 577 | case '\\': *output_ptr = '\\'; break; 578 | case '/': *output_ptr = '/'; break; 579 | case 'b': *output_ptr = '\b'; break; 580 | case 'f': *output_ptr = '\f'; break; 581 | case 'n': *output_ptr = '\n'; break; 582 | case 'r': *output_ptr = '\r'; break; 583 | case 't': *output_ptr = '\t'; break; 584 | case 'u': 585 | if (parse_utf16(&input_ptr, &output_ptr) == JSONFailure) { 586 | goto error; 587 | } 588 | break; 589 | default: 590 | goto error; 591 | } 592 | } else if ((unsigned char)*input_ptr < 0x20) { 593 | goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */ 594 | } else { 595 | *output_ptr = *input_ptr; 596 | } 597 | output_ptr++; 598 | input_ptr++; 599 | } 600 | *output_ptr = '\0'; 601 | /* resize to new length */ 602 | final_size = (size_t)(output_ptr-output) + 1; 603 | /* todo: don't resize if final_size == initial_size */ 604 | resized_output = (char*)parson_malloc(final_size); 605 | if (resized_output == NULL) { 606 | goto error; 607 | } 608 | memcpy(resized_output, output, final_size); 609 | parson_free(output); 610 | return resized_output; 611 | error: 612 | parson_free(output); 613 | return NULL; 614 | } 615 | 616 | /* Return processed contents of a string between quotes and 617 | skips passed argument to a matching quote. */ 618 | static char * get_quoted_string(const char **string) { 619 | const char *string_start = *string; 620 | size_t string_len = 0; 621 | JSON_Status status = skip_quotes(string); 622 | if (status != JSONSuccess) { 623 | return NULL; 624 | } 625 | string_len = *string - string_start - 2; /* length without quotes */ 626 | return process_string(string_start + 1, string_len); 627 | } 628 | 629 | static JSON_Value * parse_value(const char **string, size_t nesting) { 630 | if (nesting > MAX_NESTING) { 631 | return NULL; 632 | } 633 | SKIP_WHITESPACES(string); 634 | switch (**string) { 635 | case '{': 636 | return parse_object_value(string, nesting + 1); 637 | case '[': 638 | return parse_array_value(string, nesting + 1); 639 | case '\"': 640 | return parse_string_value(string); 641 | case 'f': case 't': 642 | return parse_boolean_value(string); 643 | case '-': 644 | case '0': case '1': case '2': case '3': case '4': 645 | case '5': case '6': case '7': case '8': case '9': 646 | return parse_number_value(string); 647 | case 'n': 648 | return parse_null_value(string); 649 | default: 650 | return NULL; 651 | } 652 | } 653 | 654 | static JSON_Value * parse_object_value(const char **string, size_t nesting) { 655 | JSON_Value *output_value = json_value_init_object(), *new_value = NULL; 656 | JSON_Object *output_object = json_value_get_object(output_value); 657 | char *new_key = NULL; 658 | if (output_value == NULL || **string != '{') { 659 | return NULL; 660 | } 661 | SKIP_CHAR(string); 662 | SKIP_WHITESPACES(string); 663 | if (**string == '}') { /* empty object */ 664 | SKIP_CHAR(string); 665 | return output_value; 666 | } 667 | while (**string != '\0') { 668 | new_key = get_quoted_string(string); 669 | if (new_key == NULL) { 670 | json_value_free(output_value); 671 | return NULL; 672 | } 673 | SKIP_WHITESPACES(string); 674 | if (**string != ':') { 675 | parson_free(new_key); 676 | json_value_free(output_value); 677 | return NULL; 678 | } 679 | SKIP_CHAR(string); 680 | new_value = parse_value(string, nesting); 681 | if (new_value == NULL) { 682 | parson_free(new_key); 683 | json_value_free(output_value); 684 | return NULL; 685 | } 686 | if (json_object_add(output_object, new_key, new_value) == JSONFailure) { 687 | parson_free(new_key); 688 | json_value_free(new_value); 689 | json_value_free(output_value); 690 | return NULL; 691 | } 692 | parson_free(new_key); 693 | SKIP_WHITESPACES(string); 694 | if (**string != ',') { 695 | break; 696 | } 697 | SKIP_CHAR(string); 698 | SKIP_WHITESPACES(string); 699 | } 700 | SKIP_WHITESPACES(string); 701 | if (**string != '}' || /* Trim object after parsing is over */ 702 | json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) { 703 | json_value_free(output_value); 704 | return NULL; 705 | } 706 | SKIP_CHAR(string); 707 | return output_value; 708 | } 709 | 710 | static JSON_Value * parse_array_value(const char **string, size_t nesting) { 711 | JSON_Value *output_value = json_value_init_array(), *new_array_value = NULL; 712 | JSON_Array *output_array = json_value_get_array(output_value); 713 | if (!output_value || **string != '[') { 714 | return NULL; 715 | } 716 | SKIP_CHAR(string); 717 | SKIP_WHITESPACES(string); 718 | if (**string == ']') { /* empty array */ 719 | SKIP_CHAR(string); 720 | return output_value; 721 | } 722 | while (**string != '\0') { 723 | new_array_value = parse_value(string, nesting); 724 | if (new_array_value == NULL) { 725 | json_value_free(output_value); 726 | return NULL; 727 | } 728 | if (json_array_add(output_array, new_array_value) == JSONFailure) { 729 | json_value_free(new_array_value); 730 | json_value_free(output_value); 731 | return NULL; 732 | } 733 | SKIP_WHITESPACES(string); 734 | if (**string != ',') { 735 | break; 736 | } 737 | SKIP_CHAR(string); 738 | SKIP_WHITESPACES(string); 739 | } 740 | SKIP_WHITESPACES(string); 741 | if (**string != ']' || /* Trim array after parsing is over */ 742 | json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) { 743 | json_value_free(output_value); 744 | return NULL; 745 | } 746 | SKIP_CHAR(string); 747 | return output_value; 748 | } 749 | 750 | static JSON_Value * parse_string_value(const char **string) { 751 | JSON_Value *value = NULL; 752 | char *new_string = get_quoted_string(string); 753 | if (new_string == NULL) { 754 | return NULL; 755 | } 756 | value = json_value_init_string_no_copy(new_string); 757 | if (value == NULL) { 758 | parson_free(new_string); 759 | return NULL; 760 | } 761 | return value; 762 | } 763 | 764 | static JSON_Value * parse_boolean_value(const char **string) { 765 | size_t true_token_size = SIZEOF_TOKEN("true"); 766 | size_t false_token_size = SIZEOF_TOKEN("false"); 767 | if (strncmp("true", *string, true_token_size) == 0) { 768 | *string += true_token_size; 769 | return json_value_init_boolean(1); 770 | } else if (strncmp("false", *string, false_token_size) == 0) { 771 | *string += false_token_size; 772 | return json_value_init_boolean(0); 773 | } 774 | return NULL; 775 | } 776 | 777 | static JSON_Value * parse_number_value(const char **string) { 778 | char *end; 779 | double number = 0; 780 | errno = 0; 781 | number = strtod(*string, &end); 782 | if (errno || !is_decimal(*string, end - *string)) { 783 | return NULL; 784 | } 785 | *string = end; 786 | return json_value_init_number(number); 787 | } 788 | 789 | static JSON_Value * parse_null_value(const char **string) { 790 | size_t token_size = SIZEOF_TOKEN("null"); 791 | if (strncmp("null", *string, token_size) == 0) { 792 | *string += token_size; 793 | return json_value_init_null(); 794 | } 795 | return NULL; 796 | } 797 | 798 | /* Serialization */ 799 | #define APPEND_STRING(str) do { written = append_string(buf, (str));\ 800 | if (written < 0) { return -1; }\ 801 | if (buf != NULL) { buf += written; }\ 802 | written_total += written; } while(0) 803 | 804 | #define APPEND_INDENT(level) do { written = append_indent(buf, (level));\ 805 | if (written < 0) { return -1; }\ 806 | if (buf != NULL) { buf += written; }\ 807 | written_total += written; } while(0) 808 | 809 | static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) 810 | { 811 | const char *key = NULL, *string = NULL; 812 | JSON_Value *temp_value = NULL; 813 | JSON_Array *array = NULL; 814 | JSON_Object *object = NULL; 815 | size_t i = 0, count = 0; 816 | double num = 0.0; 817 | int written = -1, written_total = 0; 818 | 819 | switch (json_value_get_type(value)) { 820 | case JSONArray: 821 | array = json_value_get_array(value); 822 | count = json_array_get_count(array); 823 | APPEND_STRING("["); 824 | if (count > 0 && is_pretty) { 825 | APPEND_STRING("\n"); 826 | } 827 | for (i = 0; i < count; i++) { 828 | if (is_pretty) { 829 | APPEND_INDENT(level+1); 830 | } 831 | temp_value = json_array_get_value(array, i); 832 | written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); 833 | if (written < 0) { 834 | return -1; 835 | } 836 | if (buf != NULL) { 837 | buf += written; 838 | } 839 | written_total += written; 840 | if (i < (count - 1)) { 841 | APPEND_STRING(","); 842 | } 843 | if (is_pretty) { 844 | APPEND_STRING("\n"); 845 | } 846 | } 847 | if (count > 0 && is_pretty) { 848 | APPEND_INDENT(level); 849 | } 850 | APPEND_STRING("]"); 851 | return written_total; 852 | case JSONObject: 853 | object = json_value_get_object(value); 854 | count = json_object_get_count(object); 855 | APPEND_STRING("{"); 856 | if (count > 0 && is_pretty) { 857 | APPEND_STRING("\n"); 858 | } 859 | for (i = 0; i < count; i++) { 860 | key = json_object_get_name(object, i); 861 | if (key == NULL) { 862 | return -1; 863 | } 864 | if (is_pretty) { 865 | APPEND_INDENT(level+1); 866 | } 867 | written = json_serialize_string(key, buf); 868 | if (written < 0) { 869 | return -1; 870 | } 871 | if (buf != NULL) { 872 | buf += written; 873 | } 874 | written_total += written; 875 | APPEND_STRING(":"); 876 | if (is_pretty) { 877 | APPEND_STRING(" "); 878 | } 879 | temp_value = json_object_get_value(object, key); 880 | written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); 881 | if (written < 0) { 882 | return -1; 883 | } 884 | if (buf != NULL) { 885 | buf += written; 886 | } 887 | written_total += written; 888 | if (i < (count - 1)) { 889 | APPEND_STRING(","); 890 | } 891 | if (is_pretty) { 892 | APPEND_STRING("\n"); 893 | } 894 | } 895 | if (count > 0 && is_pretty) { 896 | APPEND_INDENT(level); 897 | } 898 | APPEND_STRING("}"); 899 | return written_total; 900 | case JSONString: 901 | string = json_value_get_string(value); 902 | if (string == NULL) { 903 | return -1; 904 | } 905 | written = json_serialize_string(string, buf); 906 | if (written < 0) { 907 | return -1; 908 | } 909 | if (buf != NULL) { 910 | buf += written; 911 | } 912 | written_total += written; 913 | return written_total; 914 | case JSONBoolean: 915 | if (json_value_get_boolean(value)) { 916 | APPEND_STRING("true"); 917 | } else { 918 | APPEND_STRING("false"); 919 | } 920 | return written_total; 921 | case JSONNumber: 922 | num = json_value_get_number(value); 923 | if (buf != NULL) { 924 | num_buf = buf; 925 | } 926 | written = sprintf(num_buf, FLOAT_FORMAT, num); 927 | if (written < 0) { 928 | return -1; 929 | } 930 | if (buf != NULL) { 931 | buf += written; 932 | } 933 | written_total += written; 934 | return written_total; 935 | case JSONNull: 936 | APPEND_STRING("null"); 937 | return written_total; 938 | case JSONError: 939 | return -1; 940 | default: 941 | return -1; 942 | } 943 | } 944 | 945 | static int json_serialize_string(const char *string, char *buf) { 946 | size_t i = 0, len = strlen(string); 947 | char c = '\0'; 948 | int written = -1, written_total = 0; 949 | APPEND_STRING("\""); 950 | for (i = 0; i < len; i++) { 951 | c = string[i]; 952 | switch (c) { 953 | case '\"': APPEND_STRING("\\\""); break; 954 | case '\\': APPEND_STRING("\\\\"); break; 955 | case '/': APPEND_STRING("\\/"); break; /* to make json embeddable in xml\/html */ 956 | case '\b': APPEND_STRING("\\b"); break; 957 | case '\f': APPEND_STRING("\\f"); break; 958 | case '\n': APPEND_STRING("\\n"); break; 959 | case '\r': APPEND_STRING("\\r"); break; 960 | case '\t': APPEND_STRING("\\t"); break; 961 | case '\x00': APPEND_STRING("\\u0000"); break; 962 | case '\x01': APPEND_STRING("\\u0001"); break; 963 | case '\x02': APPEND_STRING("\\u0002"); break; 964 | case '\x03': APPEND_STRING("\\u0003"); break; 965 | case '\x04': APPEND_STRING("\\u0004"); break; 966 | case '\x05': APPEND_STRING("\\u0005"); break; 967 | case '\x06': APPEND_STRING("\\u0006"); break; 968 | case '\x07': APPEND_STRING("\\u0007"); break; 969 | /* '\x08' duplicate: '\b' */ 970 | /* '\x09' duplicate: '\t' */ 971 | /* '\x0a' duplicate: '\n' */ 972 | case '\x0b': APPEND_STRING("\\u000b"); break; 973 | /* '\x0c' duplicate: '\f' */ 974 | /* '\x0d' duplicate: '\r' */ 975 | case '\x0e': APPEND_STRING("\\u000e"); break; 976 | case '\x0f': APPEND_STRING("\\u000f"); break; 977 | case '\x10': APPEND_STRING("\\u0010"); break; 978 | case '\x11': APPEND_STRING("\\u0011"); break; 979 | case '\x12': APPEND_STRING("\\u0012"); break; 980 | case '\x13': APPEND_STRING("\\u0013"); break; 981 | case '\x14': APPEND_STRING("\\u0014"); break; 982 | case '\x15': APPEND_STRING("\\u0015"); break; 983 | case '\x16': APPEND_STRING("\\u0016"); break; 984 | case '\x17': APPEND_STRING("\\u0017"); break; 985 | case '\x18': APPEND_STRING("\\u0018"); break; 986 | case '\x19': APPEND_STRING("\\u0019"); break; 987 | case '\x1a': APPEND_STRING("\\u001a"); break; 988 | case '\x1b': APPEND_STRING("\\u001b"); break; 989 | case '\x1c': APPEND_STRING("\\u001c"); break; 990 | case '\x1d': APPEND_STRING("\\u001d"); break; 991 | case '\x1e': APPEND_STRING("\\u001e"); break; 992 | case '\x1f': APPEND_STRING("\\u001f"); break; 993 | default: 994 | if (buf != NULL) { 995 | buf[0] = c; 996 | buf += 1; 997 | } 998 | written_total += 1; 999 | break; 1000 | } 1001 | } 1002 | APPEND_STRING("\""); 1003 | return written_total; 1004 | } 1005 | 1006 | static int append_indent(char *buf, int level) { 1007 | int i; 1008 | int written = -1, written_total = 0; 1009 | for (i = 0; i < level; i++) { 1010 | APPEND_STRING(" "); 1011 | } 1012 | return written_total; 1013 | } 1014 | 1015 | static int append_string(char *buf, const char *string) { 1016 | if (buf == NULL) { 1017 | return (int)strlen(string); 1018 | } 1019 | return sprintf(buf, "%s", string); 1020 | } 1021 | 1022 | #undef APPEND_STRING 1023 | #undef APPEND_INDENT 1024 | 1025 | /* Parser API */ 1026 | JSON_Value * json_parse_file(const char *filename) { 1027 | char *file_contents = read_file(filename); 1028 | JSON_Value *output_value = NULL; 1029 | if (file_contents == NULL) { 1030 | return NULL; 1031 | } 1032 | output_value = json_parse_string(file_contents); 1033 | parson_free(file_contents); 1034 | return output_value; 1035 | } 1036 | 1037 | JSON_Value * json_parse_file_with_comments(const char *filename) { 1038 | char *file_contents = read_file(filename); 1039 | JSON_Value *output_value = NULL; 1040 | if (file_contents == NULL) { 1041 | return NULL; 1042 | } 1043 | output_value = json_parse_string_with_comments(file_contents); 1044 | parson_free(file_contents); 1045 | return output_value; 1046 | } 1047 | 1048 | JSON_Value * json_parse_string(const char *string) { 1049 | if (string == NULL) { 1050 | return NULL; 1051 | } 1052 | if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') { 1053 | string = string + 3; /* Support for UTF-8 BOM */ 1054 | } 1055 | return parse_value((const char**)&string, 0); 1056 | } 1057 | 1058 | JSON_Value * json_parse_string_with_comments(const char *string) { 1059 | JSON_Value *result = NULL; 1060 | char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL; 1061 | string_mutable_copy = parson_strdup(string); 1062 | if (string_mutable_copy == NULL) { 1063 | return NULL; 1064 | } 1065 | remove_comments(string_mutable_copy, "/*", "*/"); 1066 | remove_comments(string_mutable_copy, "//", "\n"); 1067 | string_mutable_copy_ptr = string_mutable_copy; 1068 | result = parse_value((const char**)&string_mutable_copy_ptr, 0); 1069 | parson_free(string_mutable_copy); 1070 | return result; 1071 | } 1072 | 1073 | /* JSON Object API */ 1074 | 1075 | JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) { 1076 | if (object == NULL || name == NULL) { 1077 | return NULL; 1078 | } 1079 | return json_object_nget_value(object, name, strlen(name)); 1080 | } 1081 | 1082 | const char * json_object_get_string(const JSON_Object *object, const char *name) { 1083 | return json_value_get_string(json_object_get_value(object, name)); 1084 | } 1085 | 1086 | double json_object_get_number(const JSON_Object *object, const char *name) { 1087 | return json_value_get_number(json_object_get_value(object, name)); 1088 | } 1089 | 1090 | JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) { 1091 | return json_value_get_object(json_object_get_value(object, name)); 1092 | } 1093 | 1094 | JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) { 1095 | return json_value_get_array(json_object_get_value(object, name)); 1096 | } 1097 | 1098 | int json_object_get_boolean(const JSON_Object *object, const char *name) { 1099 | return json_value_get_boolean(json_object_get_value(object, name)); 1100 | } 1101 | 1102 | JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) { 1103 | const char *dot_position = strchr(name, '.'); 1104 | if (!dot_position) { 1105 | return json_object_get_value(object, name); 1106 | } 1107 | object = json_value_get_object(json_object_nget_value(object, name, dot_position - name)); 1108 | return json_object_dotget_value(object, dot_position + 1); 1109 | } 1110 | 1111 | const char * json_object_dotget_string(const JSON_Object *object, const char *name) { 1112 | return json_value_get_string(json_object_dotget_value(object, name)); 1113 | } 1114 | 1115 | double json_object_dotget_number(const JSON_Object *object, const char *name) { 1116 | return json_value_get_number(json_object_dotget_value(object, name)); 1117 | } 1118 | 1119 | JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) { 1120 | return json_value_get_object(json_object_dotget_value(object, name)); 1121 | } 1122 | 1123 | JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) { 1124 | return json_value_get_array(json_object_dotget_value(object, name)); 1125 | } 1126 | 1127 | int json_object_dotget_boolean(const JSON_Object *object, const char *name) { 1128 | return json_value_get_boolean(json_object_dotget_value(object, name)); 1129 | } 1130 | 1131 | size_t json_object_get_count(const JSON_Object *object) { 1132 | return object ? object->count : 0; 1133 | } 1134 | 1135 | const char * json_object_get_name(const JSON_Object *object, size_t index) { 1136 | if (object == NULL || index >= json_object_get_count(object)) { 1137 | return NULL; 1138 | } 1139 | return object->names[index]; 1140 | } 1141 | 1142 | JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) { 1143 | if (object == NULL || index >= json_object_get_count(object)) { 1144 | return NULL; 1145 | } 1146 | return object->values[index]; 1147 | } 1148 | 1149 | JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) { 1150 | return object->wrapping_value; 1151 | } 1152 | 1153 | int json_object_has_value (const JSON_Object *object, const char *name) { 1154 | return json_object_get_value(object, name) != NULL; 1155 | } 1156 | 1157 | int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { 1158 | JSON_Value *val = json_object_get_value(object, name); 1159 | return val != NULL && json_value_get_type(val) == type; 1160 | } 1161 | 1162 | int json_object_dothas_value (const JSON_Object *object, const char *name) { 1163 | return json_object_dotget_value(object, name) != NULL; 1164 | } 1165 | 1166 | int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) { 1167 | JSON_Value *val = json_object_dotget_value(object, name); 1168 | return val != NULL && json_value_get_type(val) == type; 1169 | } 1170 | 1171 | /* JSON Array API */ 1172 | JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) { 1173 | if (array == NULL || index >= json_array_get_count(array)) { 1174 | return NULL; 1175 | } 1176 | return array->items[index]; 1177 | } 1178 | 1179 | const char * json_array_get_string(const JSON_Array *array, size_t index) { 1180 | return json_value_get_string(json_array_get_value(array, index)); 1181 | } 1182 | 1183 | double json_array_get_number(const JSON_Array *array, size_t index) { 1184 | return json_value_get_number(json_array_get_value(array, index)); 1185 | } 1186 | 1187 | JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) { 1188 | return json_value_get_object(json_array_get_value(array, index)); 1189 | } 1190 | 1191 | JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) { 1192 | return json_value_get_array(json_array_get_value(array, index)); 1193 | } 1194 | 1195 | int json_array_get_boolean(const JSON_Array *array, size_t index) { 1196 | return json_value_get_boolean(json_array_get_value(array, index)); 1197 | } 1198 | 1199 | size_t json_array_get_count(const JSON_Array *array) { 1200 | return array ? array->count : 0; 1201 | } 1202 | 1203 | JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) { 1204 | return array->wrapping_value; 1205 | } 1206 | 1207 | /* JSON Value API */ 1208 | JSON_Value_Type json_value_get_type(const JSON_Value *value) { 1209 | return value ? value->type : JSONError; 1210 | } 1211 | 1212 | JSON_Object * json_value_get_object(const JSON_Value *value) { 1213 | return json_value_get_type(value) == JSONObject ? value->value.object : NULL; 1214 | } 1215 | 1216 | JSON_Array * json_value_get_array(const JSON_Value *value) { 1217 | return json_value_get_type(value) == JSONArray ? value->value.array : NULL; 1218 | } 1219 | 1220 | const char * json_value_get_string(const JSON_Value *value) { 1221 | return json_value_get_type(value) == JSONString ? value->value.string : NULL; 1222 | } 1223 | 1224 | double json_value_get_number(const JSON_Value *value) { 1225 | return json_value_get_type(value) == JSONNumber ? value->value.number : 0; 1226 | } 1227 | 1228 | int json_value_get_boolean(const JSON_Value *value) { 1229 | return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1; 1230 | } 1231 | 1232 | JSON_Value * json_value_get_parent (const JSON_Value *value) { 1233 | return value ? value->parent : NULL; 1234 | } 1235 | 1236 | void json_value_free(JSON_Value *value) { 1237 | switch (json_value_get_type(value)) { 1238 | case JSONObject: 1239 | json_object_free(value->value.object); 1240 | break; 1241 | case JSONString: 1242 | parson_free(value->value.string); 1243 | break; 1244 | case JSONArray: 1245 | json_array_free(value->value.array); 1246 | break; 1247 | default: 1248 | break; 1249 | } 1250 | parson_free(value); 1251 | } 1252 | 1253 | JSON_Value * json_value_init_object(void) { 1254 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 1255 | if (!new_value) { 1256 | return NULL; 1257 | } 1258 | new_value->parent = NULL; 1259 | new_value->type = JSONObject; 1260 | new_value->value.object = json_object_init(new_value); 1261 | if (!new_value->value.object) { 1262 | parson_free(new_value); 1263 | return NULL; 1264 | } 1265 | return new_value; 1266 | } 1267 | 1268 | JSON_Value * json_value_init_array(void) { 1269 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 1270 | if (!new_value) { 1271 | return NULL; 1272 | } 1273 | new_value->parent = NULL; 1274 | new_value->type = JSONArray; 1275 | new_value->value.array = json_array_init(new_value); 1276 | if (!new_value->value.array) { 1277 | parson_free(new_value); 1278 | return NULL; 1279 | } 1280 | return new_value; 1281 | } 1282 | 1283 | JSON_Value * json_value_init_string(const char *string) { 1284 | char *copy = NULL; 1285 | JSON_Value *value; 1286 | size_t string_len = 0; 1287 | if (string == NULL) { 1288 | return NULL; 1289 | } 1290 | string_len = strlen(string); 1291 | if (!is_valid_utf8(string, string_len)) { 1292 | return NULL; 1293 | } 1294 | copy = parson_strndup(string, string_len); 1295 | if (copy == NULL) { 1296 | return NULL; 1297 | } 1298 | value = json_value_init_string_no_copy(copy); 1299 | if (value == NULL) { 1300 | parson_free(copy); 1301 | } 1302 | return value; 1303 | } 1304 | 1305 | JSON_Value * json_value_init_number(double number) { 1306 | JSON_Value *new_value = NULL; 1307 | if ((number * 0.0) != 0.0) { /* nan and inf test */ 1308 | return NULL; 1309 | } 1310 | new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 1311 | if (new_value == NULL) { 1312 | return NULL; 1313 | } 1314 | new_value->parent = NULL; 1315 | new_value->type = JSONNumber; 1316 | new_value->value.number = number; 1317 | return new_value; 1318 | } 1319 | 1320 | JSON_Value * json_value_init_boolean(int boolean) { 1321 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 1322 | if (!new_value) { 1323 | return NULL; 1324 | } 1325 | new_value->parent = NULL; 1326 | new_value->type = JSONBoolean; 1327 | new_value->value.boolean = boolean ? 1 : 0; 1328 | return new_value; 1329 | } 1330 | 1331 | JSON_Value * json_value_init_null(void) { 1332 | JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value)); 1333 | if (!new_value) { 1334 | return NULL; 1335 | } 1336 | new_value->parent = NULL; 1337 | new_value->type = JSONNull; 1338 | return new_value; 1339 | } 1340 | 1341 | JSON_Value * json_value_deep_copy(const JSON_Value *value) { 1342 | size_t i = 0; 1343 | JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL; 1344 | const char *temp_string = NULL, *temp_key = NULL; 1345 | char *temp_string_copy = NULL; 1346 | JSON_Array *temp_array = NULL, *temp_array_copy = NULL; 1347 | JSON_Object *temp_object = NULL, *temp_object_copy = NULL; 1348 | 1349 | switch (json_value_get_type(value)) { 1350 | case JSONArray: 1351 | temp_array = json_value_get_array(value); 1352 | return_value = json_value_init_array(); 1353 | if (return_value == NULL) { 1354 | return NULL; 1355 | } 1356 | temp_array_copy = json_value_get_array(return_value); 1357 | for (i = 0; i < json_array_get_count(temp_array); i++) { 1358 | temp_value = json_array_get_value(temp_array, i); 1359 | temp_value_copy = json_value_deep_copy(temp_value); 1360 | if (temp_value_copy == NULL) { 1361 | json_value_free(return_value); 1362 | return NULL; 1363 | } 1364 | if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) { 1365 | json_value_free(return_value); 1366 | json_value_free(temp_value_copy); 1367 | return NULL; 1368 | } 1369 | } 1370 | return return_value; 1371 | case JSONObject: 1372 | temp_object = json_value_get_object(value); 1373 | return_value = json_value_init_object(); 1374 | if (return_value == NULL) { 1375 | return NULL; 1376 | } 1377 | temp_object_copy = json_value_get_object(return_value); 1378 | for (i = 0; i < json_object_get_count(temp_object); i++) { 1379 | temp_key = json_object_get_name(temp_object, i); 1380 | temp_value = json_object_get_value(temp_object, temp_key); 1381 | temp_value_copy = json_value_deep_copy(temp_value); 1382 | if (temp_value_copy == NULL) { 1383 | json_value_free(return_value); 1384 | return NULL; 1385 | } 1386 | if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) { 1387 | json_value_free(return_value); 1388 | json_value_free(temp_value_copy); 1389 | return NULL; 1390 | } 1391 | } 1392 | return return_value; 1393 | case JSONBoolean: 1394 | return json_value_init_boolean(json_value_get_boolean(value)); 1395 | case JSONNumber: 1396 | return json_value_init_number(json_value_get_number(value)); 1397 | case JSONString: 1398 | temp_string = json_value_get_string(value); 1399 | if (temp_string == NULL) { 1400 | return NULL; 1401 | } 1402 | temp_string_copy = parson_strdup(temp_string); 1403 | if (temp_string_copy == NULL) { 1404 | return NULL; 1405 | } 1406 | return_value = json_value_init_string_no_copy(temp_string_copy); 1407 | if (return_value == NULL) { 1408 | parson_free(temp_string_copy); 1409 | } 1410 | return return_value; 1411 | case JSONNull: 1412 | return json_value_init_null(); 1413 | case JSONError: 1414 | return NULL; 1415 | default: 1416 | return NULL; 1417 | } 1418 | } 1419 | 1420 | size_t json_serialization_size(const JSON_Value *value) { 1421 | char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ 1422 | int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf); 1423 | return res < 0 ? 0 : (size_t)(res + 1); 1424 | } 1425 | 1426 | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { 1427 | int written = -1; 1428 | size_t needed_size_in_bytes = json_serialization_size(value); 1429 | if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { 1430 | return JSONFailure; 1431 | } 1432 | written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL); 1433 | if (written < 0) { 1434 | return JSONFailure; 1435 | } 1436 | return JSONSuccess; 1437 | } 1438 | 1439 | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) { 1440 | JSON_Status return_code = JSONSuccess; 1441 | FILE *fp = NULL; 1442 | char *serialized_string = json_serialize_to_string(value); 1443 | if (serialized_string == NULL) { 1444 | return JSONFailure; 1445 | } 1446 | fp = fopen(filename, "w"); 1447 | if (fp == NULL) { 1448 | json_free_serialized_string(serialized_string); 1449 | return JSONFailure; 1450 | } 1451 | if (fputs(serialized_string, fp) == EOF) { 1452 | return_code = JSONFailure; 1453 | } 1454 | if (fclose(fp) == EOF) { 1455 | return_code = JSONFailure; 1456 | } 1457 | json_free_serialized_string(serialized_string); 1458 | return return_code; 1459 | } 1460 | 1461 | char * json_serialize_to_string(const JSON_Value *value) { 1462 | JSON_Status serialization_result = JSONFailure; 1463 | size_t buf_size_bytes = json_serialization_size(value); 1464 | char *buf = NULL; 1465 | if (buf_size_bytes == 0) { 1466 | return NULL; 1467 | } 1468 | buf = (char*)parson_malloc(buf_size_bytes); 1469 | if (buf == NULL) { 1470 | return NULL; 1471 | } 1472 | serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes); 1473 | if (serialization_result == JSONFailure) { 1474 | json_free_serialized_string(buf); 1475 | return NULL; 1476 | } 1477 | return buf; 1478 | } 1479 | 1480 | size_t json_serialization_size_pretty(const JSON_Value *value) { 1481 | char num_buf[NUM_BUF_SIZE]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ 1482 | int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf); 1483 | return res < 0 ? 0 : (size_t)(res + 1); 1484 | } 1485 | 1486 | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { 1487 | int written = -1; 1488 | size_t needed_size_in_bytes = json_serialization_size_pretty(value); 1489 | if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) { 1490 | return JSONFailure; 1491 | } 1492 | written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL); 1493 | if (written < 0) { 1494 | return JSONFailure; 1495 | } 1496 | return JSONSuccess; 1497 | } 1498 | 1499 | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) { 1500 | JSON_Status return_code = JSONSuccess; 1501 | FILE *fp = NULL; 1502 | char *serialized_string = json_serialize_to_string_pretty(value); 1503 | if (serialized_string == NULL) { 1504 | return JSONFailure; 1505 | } 1506 | fp = fopen(filename, "w"); 1507 | if (fp == NULL) { 1508 | json_free_serialized_string(serialized_string); 1509 | return JSONFailure; 1510 | } 1511 | if (fputs(serialized_string, fp) == EOF) { 1512 | return_code = JSONFailure; 1513 | } 1514 | if (fclose(fp) == EOF) { 1515 | return_code = JSONFailure; 1516 | } 1517 | json_free_serialized_string(serialized_string); 1518 | return return_code; 1519 | } 1520 | 1521 | char * json_serialize_to_string_pretty(const JSON_Value *value) { 1522 | JSON_Status serialization_result = JSONFailure; 1523 | size_t buf_size_bytes = json_serialization_size_pretty(value); 1524 | char *buf = NULL; 1525 | if (buf_size_bytes == 0) { 1526 | return NULL; 1527 | } 1528 | buf = (char*)parson_malloc(buf_size_bytes); 1529 | if (buf == NULL) { 1530 | return NULL; 1531 | } 1532 | serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes); 1533 | if (serialization_result == JSONFailure) { 1534 | json_free_serialized_string(buf); 1535 | return NULL; 1536 | } 1537 | return buf; 1538 | } 1539 | 1540 | void json_free_serialized_string(char *string) { 1541 | parson_free(string); 1542 | } 1543 | 1544 | JSON_Status json_array_remove(JSON_Array *array, size_t ix) { 1545 | size_t to_move_bytes = 0; 1546 | if (array == NULL || ix >= json_array_get_count(array)) { 1547 | return JSONFailure; 1548 | } 1549 | json_value_free(json_array_get_value(array, ix)); 1550 | to_move_bytes = (json_array_get_count(array) - 1 - ix) * sizeof(JSON_Value*); 1551 | memmove(array->items + ix, array->items + ix + 1, to_move_bytes); 1552 | array->count -= 1; 1553 | return JSONSuccess; 1554 | } 1555 | 1556 | JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) { 1557 | if (array == NULL || value == NULL || value->parent != NULL || ix >= json_array_get_count(array)) { 1558 | return JSONFailure; 1559 | } 1560 | json_value_free(json_array_get_value(array, ix)); 1561 | value->parent = json_array_get_wrapping_value(array); 1562 | array->items[ix] = value; 1563 | return JSONSuccess; 1564 | } 1565 | 1566 | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) { 1567 | JSON_Value *value = json_value_init_string(string); 1568 | if (value == NULL) { 1569 | return JSONFailure; 1570 | } 1571 | if (json_array_replace_value(array, i, value) == JSONFailure) { 1572 | json_value_free(value); 1573 | return JSONFailure; 1574 | } 1575 | return JSONSuccess; 1576 | } 1577 | 1578 | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) { 1579 | JSON_Value *value = json_value_init_number(number); 1580 | if (value == NULL) { 1581 | return JSONFailure; 1582 | } 1583 | if (json_array_replace_value(array, i, value) == JSONFailure) { 1584 | json_value_free(value); 1585 | return JSONFailure; 1586 | } 1587 | return JSONSuccess; 1588 | } 1589 | 1590 | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) { 1591 | JSON_Value *value = json_value_init_boolean(boolean); 1592 | if (value == NULL) { 1593 | return JSONFailure; 1594 | } 1595 | if (json_array_replace_value(array, i, value) == JSONFailure) { 1596 | json_value_free(value); 1597 | return JSONFailure; 1598 | } 1599 | return JSONSuccess; 1600 | } 1601 | 1602 | JSON_Status json_array_replace_null(JSON_Array *array, size_t i) { 1603 | JSON_Value *value = json_value_init_null(); 1604 | if (value == NULL) { 1605 | return JSONFailure; 1606 | } 1607 | if (json_array_replace_value(array, i, value) == JSONFailure) { 1608 | json_value_free(value); 1609 | return JSONFailure; 1610 | } 1611 | return JSONSuccess; 1612 | } 1613 | 1614 | JSON_Status json_array_clear(JSON_Array *array) { 1615 | size_t i = 0; 1616 | if (array == NULL) { 1617 | return JSONFailure; 1618 | } 1619 | for (i = 0; i < json_array_get_count(array); i++) { 1620 | json_value_free(json_array_get_value(array, i)); 1621 | } 1622 | array->count = 0; 1623 | return JSONSuccess; 1624 | } 1625 | 1626 | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) { 1627 | if (array == NULL || value == NULL || value->parent != NULL) { 1628 | return JSONFailure; 1629 | } 1630 | return json_array_add(array, value); 1631 | } 1632 | 1633 | JSON_Status json_array_append_string(JSON_Array *array, const char *string) { 1634 | JSON_Value *value = json_value_init_string(string); 1635 | if (value == NULL) { 1636 | return JSONFailure; 1637 | } 1638 | if (json_array_append_value(array, value) == JSONFailure) { 1639 | json_value_free(value); 1640 | return JSONFailure; 1641 | } 1642 | return JSONSuccess; 1643 | } 1644 | 1645 | JSON_Status json_array_append_number(JSON_Array *array, double number) { 1646 | JSON_Value *value = json_value_init_number(number); 1647 | if (value == NULL) { 1648 | return JSONFailure; 1649 | } 1650 | if (json_array_append_value(array, value) == JSONFailure) { 1651 | json_value_free(value); 1652 | return JSONFailure; 1653 | } 1654 | return JSONSuccess; 1655 | } 1656 | 1657 | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) { 1658 | JSON_Value *value = json_value_init_boolean(boolean); 1659 | if (value == NULL) { 1660 | return JSONFailure; 1661 | } 1662 | if (json_array_append_value(array, value) == JSONFailure) { 1663 | json_value_free(value); 1664 | return JSONFailure; 1665 | } 1666 | return JSONSuccess; 1667 | } 1668 | 1669 | JSON_Status json_array_append_null(JSON_Array *array) { 1670 | JSON_Value *value = json_value_init_null(); 1671 | if (value == NULL) { 1672 | return JSONFailure; 1673 | } 1674 | if (json_array_append_value(array, value) == JSONFailure) { 1675 | json_value_free(value); 1676 | return JSONFailure; 1677 | } 1678 | return JSONSuccess; 1679 | } 1680 | 1681 | JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) { 1682 | size_t i = 0; 1683 | JSON_Value *old_value; 1684 | if (object == NULL || name == NULL || value == NULL || value->parent != NULL) { 1685 | return JSONFailure; 1686 | } 1687 | old_value = json_object_get_value(object, name); 1688 | if (old_value != NULL) { /* free and overwrite old value */ 1689 | json_value_free(old_value); 1690 | for (i = 0; i < json_object_get_count(object); i++) { 1691 | if (strcmp(object->names[i], name) == 0) { 1692 | value->parent = json_object_get_wrapping_value(object); 1693 | object->values[i] = value; 1694 | return JSONSuccess; 1695 | } 1696 | } 1697 | } 1698 | /* add new key value pair */ 1699 | return json_object_add(object, name, value); 1700 | } 1701 | 1702 | JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) { 1703 | return json_object_set_value(object, name, json_value_init_string(string)); 1704 | } 1705 | 1706 | JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) { 1707 | return json_object_set_value(object, name, json_value_init_number(number)); 1708 | } 1709 | 1710 | JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) { 1711 | return json_object_set_value(object, name, json_value_init_boolean(boolean)); 1712 | } 1713 | 1714 | JSON_Status json_object_set_null(JSON_Object *object, const char *name) { 1715 | return json_object_set_value(object, name, json_value_init_null()); 1716 | } 1717 | 1718 | JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) { 1719 | const char *dot_pos = NULL; 1720 | char *current_name = NULL; 1721 | JSON_Object *temp_obj = NULL; 1722 | JSON_Value *new_value = NULL; 1723 | if (object == NULL || name == NULL || value == NULL) { 1724 | return JSONFailure; 1725 | } 1726 | dot_pos = strchr(name, '.'); 1727 | if (dot_pos == NULL) { 1728 | return json_object_set_value(object, name, value); 1729 | } else { 1730 | current_name = parson_strndup(name, dot_pos - name); 1731 | temp_obj = json_object_get_object(object, current_name); 1732 | if (temp_obj == NULL) { 1733 | new_value = json_value_init_object(); 1734 | if (new_value == NULL) { 1735 | parson_free(current_name); 1736 | return JSONFailure; 1737 | } 1738 | if (json_object_add(object, current_name, new_value) == JSONFailure) { 1739 | json_value_free(new_value); 1740 | parson_free(current_name); 1741 | return JSONFailure; 1742 | } 1743 | temp_obj = json_object_get_object(object, current_name); 1744 | } 1745 | parson_free(current_name); 1746 | return json_object_dotset_value(temp_obj, dot_pos + 1, value); 1747 | } 1748 | } 1749 | 1750 | JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) { 1751 | JSON_Value *value = json_value_init_string(string); 1752 | if (value == NULL) { 1753 | return JSONFailure; 1754 | } 1755 | if (json_object_dotset_value(object, name, value) == JSONFailure) { 1756 | json_value_free(value); 1757 | return JSONFailure; 1758 | } 1759 | return JSONSuccess; 1760 | } 1761 | 1762 | JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) { 1763 | JSON_Value *value = json_value_init_number(number); 1764 | if (value == NULL) { 1765 | return JSONFailure; 1766 | } 1767 | if (json_object_dotset_value(object, name, value) == JSONFailure) { 1768 | json_value_free(value); 1769 | return JSONFailure; 1770 | } 1771 | return JSONSuccess; 1772 | } 1773 | 1774 | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) { 1775 | JSON_Value *value = json_value_init_boolean(boolean); 1776 | if (value == NULL) { 1777 | return JSONFailure; 1778 | } 1779 | if (json_object_dotset_value(object, name, value) == JSONFailure) { 1780 | json_value_free(value); 1781 | return JSONFailure; 1782 | } 1783 | return JSONSuccess; 1784 | } 1785 | 1786 | JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) { 1787 | JSON_Value *value = json_value_init_null(); 1788 | if (value == NULL) { 1789 | return JSONFailure; 1790 | } 1791 | if (json_object_dotset_value(object, name, value) == JSONFailure) { 1792 | json_value_free(value); 1793 | return JSONFailure; 1794 | } 1795 | return JSONSuccess; 1796 | } 1797 | 1798 | JSON_Status json_object_remove(JSON_Object *object, const char *name) { 1799 | size_t i = 0, last_item_index = 0; 1800 | if (object == NULL || json_object_get_value(object, name) == NULL) { 1801 | return JSONFailure; 1802 | } 1803 | last_item_index = json_object_get_count(object) - 1; 1804 | for (i = 0; i < json_object_get_count(object); i++) { 1805 | if (strcmp(object->names[i], name) == 0) { 1806 | parson_free(object->names[i]); 1807 | json_value_free(object->values[i]); 1808 | if (i != last_item_index) { /* Replace key value pair with one from the end */ 1809 | object->names[i] = object->names[last_item_index]; 1810 | object->values[i] = object->values[last_item_index]; 1811 | } 1812 | object->count -= 1; 1813 | return JSONSuccess; 1814 | } 1815 | } 1816 | return JSONFailure; /* No execution path should end here */ 1817 | } 1818 | 1819 | JSON_Status json_object_dotremove(JSON_Object *object, const char *name) { 1820 | const char *dot_pos = strchr(name, '.'); 1821 | char *current_name = NULL; 1822 | JSON_Object *temp_obj = NULL; 1823 | if (dot_pos == NULL) { 1824 | return json_object_remove(object, name); 1825 | } else { 1826 | current_name = parson_strndup(name, dot_pos - name); 1827 | temp_obj = json_object_get_object(object, current_name); 1828 | parson_free(current_name); 1829 | if (temp_obj == NULL) { 1830 | return JSONFailure; 1831 | } 1832 | return json_object_dotremove(temp_obj, dot_pos + 1); 1833 | } 1834 | } 1835 | 1836 | JSON_Status json_object_clear(JSON_Object *object) { 1837 | size_t i = 0; 1838 | if (object == NULL) { 1839 | return JSONFailure; 1840 | } 1841 | for (i = 0; i < json_object_get_count(object); i++) { 1842 | parson_free(object->names[i]); 1843 | json_value_free(object->values[i]); 1844 | } 1845 | object->count = 0; 1846 | return JSONSuccess; 1847 | } 1848 | 1849 | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) { 1850 | JSON_Value *temp_schema_value = NULL, *temp_value = NULL; 1851 | JSON_Array *schema_array = NULL, *value_array = NULL; 1852 | JSON_Object *schema_object = NULL, *value_object = NULL; 1853 | JSON_Value_Type schema_type = JSONError, value_type = JSONError; 1854 | const char *key = NULL; 1855 | size_t i = 0, count = 0; 1856 | if (schema == NULL || value == NULL) { 1857 | return JSONFailure; 1858 | } 1859 | schema_type = json_value_get_type(schema); 1860 | value_type = json_value_get_type(value); 1861 | if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */ 1862 | return JSONFailure; 1863 | } 1864 | switch (schema_type) { 1865 | case JSONArray: 1866 | schema_array = json_value_get_array(schema); 1867 | value_array = json_value_get_array(value); 1868 | count = json_array_get_count(schema_array); 1869 | if (count == 0) { 1870 | return JSONSuccess; /* Empty array allows all types */ 1871 | } 1872 | /* Get first value from array, rest is ignored */ 1873 | temp_schema_value = json_array_get_value(schema_array, 0); 1874 | for (i = 0; i < json_array_get_count(value_array); i++) { 1875 | temp_value = json_array_get_value(value_array, i); 1876 | if (json_validate(temp_schema_value, temp_value) == JSONFailure) { 1877 | return JSONFailure; 1878 | } 1879 | } 1880 | return JSONSuccess; 1881 | case JSONObject: 1882 | schema_object = json_value_get_object(schema); 1883 | value_object = json_value_get_object(value); 1884 | count = json_object_get_count(schema_object); 1885 | if (count == 0) { 1886 | return JSONSuccess; /* Empty object allows all objects */ 1887 | } else if (json_object_get_count(value_object) < count) { 1888 | return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */ 1889 | } 1890 | for (i = 0; i < count; i++) { 1891 | key = json_object_get_name(schema_object, i); 1892 | temp_schema_value = json_object_get_value(schema_object, key); 1893 | temp_value = json_object_get_value(value_object, key); 1894 | if (temp_value == NULL) { 1895 | return JSONFailure; 1896 | } 1897 | if (json_validate(temp_schema_value, temp_value) == JSONFailure) { 1898 | return JSONFailure; 1899 | } 1900 | } 1901 | return JSONSuccess; 1902 | case JSONString: case JSONNumber: case JSONBoolean: case JSONNull: 1903 | return JSONSuccess; /* equality already tested before switch */ 1904 | case JSONError: default: 1905 | return JSONFailure; 1906 | } 1907 | } 1908 | 1909 | int json_value_equals(const JSON_Value *a, const JSON_Value *b) { 1910 | JSON_Object *a_object = NULL, *b_object = NULL; 1911 | JSON_Array *a_array = NULL, *b_array = NULL; 1912 | const char *a_string = NULL, *b_string = NULL; 1913 | const char *key = NULL; 1914 | size_t a_count = 0, b_count = 0, i = 0; 1915 | JSON_Value_Type a_type, b_type; 1916 | a_type = json_value_get_type(a); 1917 | b_type = json_value_get_type(b); 1918 | if (a_type != b_type) { 1919 | return 0; 1920 | } 1921 | switch (a_type) { 1922 | case JSONArray: 1923 | a_array = json_value_get_array(a); 1924 | b_array = json_value_get_array(b); 1925 | a_count = json_array_get_count(a_array); 1926 | b_count = json_array_get_count(b_array); 1927 | if (a_count != b_count) { 1928 | return 0; 1929 | } 1930 | for (i = 0; i < a_count; i++) { 1931 | if (!json_value_equals(json_array_get_value(a_array, i), 1932 | json_array_get_value(b_array, i))) { 1933 | return 0; 1934 | } 1935 | } 1936 | return 1; 1937 | case JSONObject: 1938 | a_object = json_value_get_object(a); 1939 | b_object = json_value_get_object(b); 1940 | a_count = json_object_get_count(a_object); 1941 | b_count = json_object_get_count(b_object); 1942 | if (a_count != b_count) { 1943 | return 0; 1944 | } 1945 | for (i = 0; i < a_count; i++) { 1946 | key = json_object_get_name(a_object, i); 1947 | if (!json_value_equals(json_object_get_value(a_object, key), 1948 | json_object_get_value(b_object, key))) { 1949 | return 0; 1950 | } 1951 | } 1952 | return 1; 1953 | case JSONString: 1954 | a_string = json_value_get_string(a); 1955 | b_string = json_value_get_string(b); 1956 | if (a_string == NULL || b_string == NULL) { 1957 | return 0; /* shouldn't happen */ 1958 | } 1959 | return strcmp(a_string, b_string) == 0; 1960 | case JSONBoolean: 1961 | return json_value_get_boolean(a) == json_value_get_boolean(b); 1962 | case JSONNumber: 1963 | return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */ 1964 | case JSONError: 1965 | return 1; 1966 | case JSONNull: 1967 | return 1; 1968 | default: 1969 | return 1; 1970 | } 1971 | } 1972 | 1973 | JSON_Value_Type json_type(const JSON_Value *value) { 1974 | return json_value_get_type(value); 1975 | } 1976 | 1977 | JSON_Object * json_object (const JSON_Value *value) { 1978 | return json_value_get_object(value); 1979 | } 1980 | 1981 | JSON_Array * json_array (const JSON_Value *value) { 1982 | return json_value_get_array(value); 1983 | } 1984 | 1985 | const char * json_string (const JSON_Value *value) { 1986 | return json_value_get_string(value); 1987 | } 1988 | 1989 | double json_number (const JSON_Value *value) { 1990 | return json_value_get_number(value); 1991 | } 1992 | 1993 | int json_boolean(const JSON_Value *value) { 1994 | return json_value_get_boolean(value); 1995 | } 1996 | 1997 | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) { 1998 | parson_malloc = malloc_fun; 1999 | parson_free = free_fun; 2000 | } 2001 | -------------------------------------------------------------------------------- /lib/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (c) 2012 - 2017 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | /* Types and enums */ 35 | typedef struct json_object_t JSON_Object; 36 | typedef struct json_array_t JSON_Array; 37 | typedef struct json_value_t JSON_Value; 38 | 39 | enum json_value_type { 40 | JSONError = -1, 41 | JSONNull = 1, 42 | JSONString = 2, 43 | JSONNumber = 3, 44 | JSONObject = 4, 45 | JSONArray = 5, 46 | JSONBoolean = 6 47 | }; 48 | typedef int JSON_Value_Type; 49 | 50 | enum json_result_t { 51 | JSONSuccess = 0, 52 | JSONFailure = -1 53 | }; 54 | typedef int JSON_Status; 55 | 56 | typedef void * (*JSON_Malloc_Function)(size_t); 57 | typedef void (*JSON_Free_Function)(void *); 58 | 59 | /* Call only once, before calling any other function from parson API. If not called, malloc and free 60 | from stdlib will be used for all allocations */ 61 | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun); 62 | 63 | /* Parses first JSON value in a file, returns NULL in case of error */ 64 | JSON_Value * json_parse_file(const char *filename); 65 | 66 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 67 | returns NULL in case of error */ 68 | JSON_Value * json_parse_file_with_comments(const char *filename); 69 | 70 | /* Parses first JSON value in a string, returns NULL in case of error */ 71 | JSON_Value * json_parse_string(const char *string); 72 | 73 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 74 | returns NULL in case of error */ 75 | JSON_Value * json_parse_string_with_comments(const char *string); 76 | 77 | /* Serialization */ 78 | size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ 79 | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); 80 | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); 81 | char * json_serialize_to_string(const JSON_Value *value); 82 | 83 | /* Pretty serialization */ 84 | size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ 85 | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); 86 | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); 87 | char * json_serialize_to_string_pretty(const JSON_Value *value); 88 | 89 | void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ 90 | 91 | /* Comparing */ 92 | int json_value_equals(const JSON_Value *a, const JSON_Value *b); 93 | 94 | /* Validation 95 | This is *NOT* JSON Schema. It validates json by checking if object have identically 96 | named fields with matching types. 97 | For example schema {"name":"", "age":0} will validate 98 | {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"}, 99 | but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}. 100 | In case of arrays, only first value in schema is checked against all values in tested array. 101 | Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays, 102 | null validates values of every type. 103 | */ 104 | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value); 105 | 106 | /* 107 | * JSON Object 108 | */ 109 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 110 | const char * json_object_get_string (const JSON_Object *object, const char *name); 111 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 112 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 113 | double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ 114 | int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ 115 | 116 | /* dotget functions enable addressing values with dot notation in nested objects, 117 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 118 | Because valid names in JSON can contain dots, some values may be inaccessible 119 | this way. */ 120 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 121 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 122 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 123 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 124 | double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ 125 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ 126 | 127 | /* Functions to get available names */ 128 | size_t json_object_get_count (const JSON_Object *object); 129 | const char * json_object_get_name (const JSON_Object *object, size_t index); 130 | JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index); 131 | JSON_Value * json_object_get_wrapping_value(const JSON_Object *object); 132 | 133 | /* Functions to check if object has a value with a specific name. Returned value is 1 if object has 134 | * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ 135 | int json_object_has_value (const JSON_Object *object, const char *name); 136 | int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); 137 | 138 | int json_object_dothas_value (const JSON_Object *object, const char *name); 139 | int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); 140 | 141 | /* Creates new name-value pair or frees and replaces old value with a new one. 142 | * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ 143 | JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); 144 | JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); 145 | JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); 146 | JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); 147 | JSON_Status json_object_set_null(JSON_Object *object, const char *name); 148 | 149 | /* Works like dotget functions, but creates whole hierarchy if necessary. 150 | * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */ 151 | JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value); 152 | JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string); 153 | JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number); 154 | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean); 155 | JSON_Status json_object_dotset_null(JSON_Object *object, const char *name); 156 | 157 | /* Frees and removes name-value pair */ 158 | JSON_Status json_object_remove(JSON_Object *object, const char *name); 159 | 160 | /* Works like dotget function, but removes name-value pair only on exact match. */ 161 | JSON_Status json_object_dotremove(JSON_Object *object, const char *key); 162 | 163 | /* Removes all name-value pairs in object */ 164 | JSON_Status json_object_clear(JSON_Object *object); 165 | 166 | /* 167 | *JSON Array 168 | */ 169 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 170 | const char * json_array_get_string (const JSON_Array *array, size_t index); 171 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 172 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 173 | double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ 174 | int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ 175 | size_t json_array_get_count (const JSON_Array *array); 176 | JSON_Value * json_array_get_wrapping_value(const JSON_Array *array); 177 | 178 | /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. 179 | * Order of values in array may change during execution. */ 180 | JSON_Status json_array_remove(JSON_Array *array, size_t i); 181 | 182 | /* Frees and removes from array value at given index and replaces it with given one. 183 | * Does nothing and returns JSONFailure if index doesn't exist. 184 | * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ 185 | JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); 186 | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); 187 | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); 188 | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); 189 | JSON_Status json_array_replace_null(JSON_Array *array, size_t i); 190 | 191 | /* Frees and removes all values from array */ 192 | JSON_Status json_array_clear(JSON_Array *array); 193 | 194 | /* Appends new value at the end of array. 195 | * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */ 196 | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value); 197 | JSON_Status json_array_append_string(JSON_Array *array, const char *string); 198 | JSON_Status json_array_append_number(JSON_Array *array, double number); 199 | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean); 200 | JSON_Status json_array_append_null(JSON_Array *array); 201 | 202 | /* 203 | *JSON Value 204 | */ 205 | JSON_Value * json_value_init_object (void); 206 | JSON_Value * json_value_init_array (void); 207 | JSON_Value * json_value_init_string (const char *string); /* copies passed string */ 208 | JSON_Value * json_value_init_number (double number); 209 | JSON_Value * json_value_init_boolean(int boolean); 210 | JSON_Value * json_value_init_null (void); 211 | JSON_Value * json_value_deep_copy (const JSON_Value *value); 212 | void json_value_free (JSON_Value *value); 213 | 214 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 215 | JSON_Object * json_value_get_object (const JSON_Value *value); 216 | JSON_Array * json_value_get_array (const JSON_Value *value); 217 | const char * json_value_get_string (const JSON_Value *value); 218 | double json_value_get_number (const JSON_Value *value); 219 | int json_value_get_boolean(const JSON_Value *value); 220 | JSON_Value * json_value_get_parent (const JSON_Value *value); 221 | 222 | /* Same as above, but shorter */ 223 | JSON_Value_Type json_type (const JSON_Value *value); 224 | JSON_Object * json_object (const JSON_Value *value); 225 | JSON_Array * json_array (const JSON_Value *value); 226 | const char * json_string (const JSON_Value *value); 227 | double json_number (const JSON_Value *value); 228 | int json_boolean(const JSON_Value *value); 229 | 230 | #ifdef __cplusplus 231 | } 232 | #endif 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /lib/parson_test.c: -------------------------------------------------------------------------------- 1 | #include "parson.h" 2 | #include 3 | #include 4 | 5 | void test_parse_file() { 6 | JSON_Value *schema = 7 | json_parse_string("{\"local_port\":0,\"server_addr\":\"\",\"server_" 8 | "port\":0,\"password\":\"\"}"); 9 | JSON_Value *data = json_parse_file("test.json"); 10 | char buf[256]; 11 | int local_port, server_port; 12 | const char *server_addr, *password; 13 | if (data == NULL || json_validate(schema, data) != JSONSuccess) { 14 | printf("ERROR\n"); 15 | } 16 | 17 | local_port = json_object_get_number((json_object(data)), "local_port"); 18 | server_addr = json_object_get_string((json_object(data)), "server_addr"); 19 | server_port = json_object_get_number(json_object(data), "server_port"); 20 | password = json_object_get_string((json_object(data)), "password"); 21 | 22 | printf("%d\n", local_port); 23 | puts(server_addr); 24 | printf("%d\n", server_port); 25 | puts(password); 26 | 27 | json_value_free(schema); 28 | json_value_free(data); 29 | } 30 | 31 | void test_serialize_to_file() { 32 | JSON_Value *root_val = json_value_init_object(); 33 | JSON_Object *root_obj = json_value_get_object(root_val); 34 | json_object_set_number(root_obj, "local_port", 2333); 35 | json_object_set_string(root_obj, "server_addr", "1.1.1.1"); 36 | json_object_set_number(root_obj, "server_port", 42619); 37 | json_object_set_string( 38 | root_obj, "password", 39 | "ooccDJX8EwaTL5I1JY9B4k1cc52XTxoQWSRSKZmBuBfLoG76qip8tnXpfQVesPlbO4hMx82L" 40 | "bOEr84yYdKtnMLwRMRvkZp4yWgPo4K08hNUtYnb+09KAz6/Jo843oaUAfpphxgG3te/" 41 | "epycPOjPsw2D1g1UJf44IVLmGpq7acpsuBxVoRcL4iWOfCj6sqYpH3MHY0LPx64K9tFhAHxh" 42 | "LwIV7Rv8/" 43 | "kOfFV04S8HekkWq+" 44 | "NFAU48TfyvL0XxYO5hlKegTI1ybdzFZpRO731rEC1EKUb7sjbT2oIB44sihwItFdQ/" 45 | "vZ7WtJcVPqHf2/SLp4IQ3lLJbbOXlRjQucNmRl9g=="); 46 | json_serialize_to_file_pretty(root_val, "out.json"); 47 | 48 | json_value_free(root_val); 49 | } 50 | 51 | int main() { 52 | test_serialize_to_file(); 53 | test_parse_file(); 54 | return 0; 55 | } -------------------------------------------------------------------------------- /lib/password.c: -------------------------------------------------------------------------------- 1 | #include "password.h" 2 | #include "base64.h" 3 | #include "log.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* private function */ 11 | 12 | static void swap(byte *a, byte *b) { 13 | byte t = *a; 14 | *a = *b; 15 | *b = t; 16 | } 17 | 18 | /* private function end*/ 19 | 20 | // represent password as string encode in base64 21 | char *password_string(Password *pass, size_t *outsize) { 22 | return b64_encode(pass->x, PASS_LENGTH, outsize); 23 | } 24 | 25 | // generate password by string encode in base64 26 | Password *gen_password_by_string(char *string, size_t len) { 27 | Password *pass = calloc(1, sizeof(Password)); 28 | size_t decsize; 29 | unsigned char *decoded = b64_decode_ex(string, len, &decsize); 30 | log_d("password size: %ld", decsize); 31 | check(decsize == PASS_LENGTH, "can't generate password!"); 32 | // strncpy(pass->x, decoded, PASS_LENGTH); 33 | // copy data 34 | // wtf: don't use strncpy... 35 | for (int i = 0; i < PASS_LENGTH; i++) { 36 | pass->x[i] = decoded[i]; 37 | } 38 | free(decoded); 39 | 40 | return pass; 41 | 42 | error: 43 | free(pass); 44 | free(decoded); 45 | return NULL; 46 | } 47 | 48 | Password *rand_password() { 49 | Password *password = calloc(1, sizeof(Password)); 50 | srand(time(NULL)); 51 | int i; 52 | for (i = 0; i < 256; i++) { 53 | password->x[i] = i; 54 | } 55 | 56 | // kruth's shuffle 57 | // bug: index i's value can be i. 58 | for (i = 0; i < 256; i++) { 59 | int v = rand() % 256; // 0 ~255 60 | swap(&password->x[i], &password->x[v]); 61 | } 62 | return password; 63 | } 64 | 65 | // encode 66 | void encode_data(byte bytes[], int size, Password *encode_pass) { 67 | for (int i = 0; i < size; i++) { 68 | bytes[i] = encode_pass->x[bytes[i]]; 69 | } 70 | } 71 | 72 | // decode 73 | void decode_data(byte bytes[], int size, Password *encode_pass) { 74 | Password decode_pass = {}; 75 | int i; 76 | for (i = 0; i < PASS_LENGTH; i++) { 77 | decode_pass.x[encode_pass->x[i]] = i; 78 | } 79 | for (i = 0; i < size; i++) { 80 | bytes[i] = decode_pass.x[bytes[i]]; 81 | } 82 | } -------------------------------------------------------------------------------- /lib/password.h: -------------------------------------------------------------------------------- 1 | #ifndef __PASSWORD_H__ 2 | #define __PASSWORD_H__ 3 | 4 | #include 5 | #define PASS_LENGTH 256 6 | // 0 ~255 7 | #define byte unsigned char 8 | /** 9 | * Password is a 256 length array, 10 | * use index and value as a table. 11 | **/ 12 | typedef struct { 13 | byte x[PASS_LENGTH]; 14 | } Password; 15 | 16 | // represent password as string encode in base64 17 | char *password_string(Password *pass, size_t *outsize); 18 | 19 | // generate password by string encode in base64 20 | Password *gen_password_by_string(char *string, size_t len); 21 | 22 | Password *rand_password(); 23 | 24 | // encode 25 | void encode_data(byte bytes[], int size, Password *pass); 26 | 27 | // decode 28 | void decode_data(byte bytes[], int size, Password *pass); 29 | 30 | #endif // MACRO -------------------------------------------------------------------------------- /lib/password_test.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "password.h" 3 | #include 4 | #include 5 | 6 | void test_generate_password_by_string() { 7 | char string[] = 8 | "ooccDJX8EwaTL5I1JY9B4k1cc52XTxoQWSRSKZmBuBfLoG76qip8tnXpfQVesPlbO4hMx82L" 9 | "bOEr84yYdKtnMLwRMRvkZp4yWgPo4K08hNUtYnb+09KAz6/Jo843oaUAfpphxgG3te/" 10 | "epycPOjPsw2D1g1UJf44IVLmGpq7acpsuBxVoRcL4iWOfCj6sqYpH3MHY0LPx64K9tFhAHxh" 11 | "LwIV7Rv8/" 12 | "kOfFV04S8HekkWq+" 13 | "NFAU48TfyvL0XxYO5hlKegTI1ybdzFZpRO731rEC1EKUb7sjbT2oIB44sihwItFdQ/" 14 | "vZ7WtJcVPqHf2/SLp4IQ3lLJbbOXlRjQucNmRl9g=="; 15 | log_d("Generate password by string:\n"); 16 | 17 | Password *gen_pass = gen_password_by_string(string, strlen(string)); 18 | for (int i = 0; i < PASS_LENGTH; i++) { 19 | printf("%d ", gen_pass->x[i]); 20 | } 21 | free(gen_pass); 22 | } 23 | 24 | void test_rand_password(Password *pass) { 25 | log_d("Base64 string: \n"); 26 | size_t size; 27 | char *base64 = password_string(pass, &size); 28 | printf("%s\n", base64); 29 | 30 | log_d("Generate password by string:\n"); 31 | Password *gen_pass = gen_password_by_string(base64, size); 32 | for (int i = 0; i < PASS_LENGTH; i++) { 33 | printf("%d ", gen_pass->x[i]); 34 | } 35 | for (int i = 0; i < PASS_LENGTH; i++) { 36 | check(gen_pass->x[i] == pass->x[i], "password not match") 37 | } 38 | printf("\n"); 39 | 40 | error: 41 | free(gen_pass); 42 | free(base64); 43 | } 44 | 45 | void test_encode_decode(Password *pass) { 46 | log_d("encode and decode data:"); 47 | byte a[] = "hello"; 48 | encode_data(a, sizeof(a), pass); 49 | puts(a); 50 | decode_data(a, sizeof(a), pass); 51 | puts(a); 52 | } 53 | 54 | // unit test 55 | // gcc password_test.c password.o log.o base64.o -o test 56 | int main() { 57 | Password *pass = rand_password(); 58 | for (int i = 0; i < PASS_LENGTH; i++) { 59 | printf("%d ", pass->x[i]); 60 | } 61 | printf("\n"); 62 | test_generate_password_by_string(); 63 | test_rand_password(pass); 64 | test_encode_decode(pass); 65 | 66 | free(pass); 67 | 68 | log_d("All test pass"); 69 | return 0; 70 | } -------------------------------------------------------------------------------- /lib/securesocket.c: -------------------------------------------------------------------------------- 1 | #include "securesocket.h" 2 | #include "log.h" 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | /**For portable socket on windows**/ 9 | #include 10 | 11 | // static Password *password = NULL; 12 | 13 | // void set_password(Password *this_password) { 14 | // if (password) { 15 | // free(password); 16 | // } 17 | // password = this_password; 18 | // } 19 | 20 | int decode_read(Password *password, bufferevent *bufev, byte bytes[], 21 | size_t size) { 22 | int n = bufferevent_read(bufev, bytes, size); 23 | // check(n > 0, "read error: %d", n); 24 | decode_data(bytes, n, password); 25 | 26 | error: // fallthrogh 27 | return n; 28 | } 29 | 30 | int encode_write(Password *password, bufferevent *bufev, byte bytes[], 31 | size_t size) { 32 | encode_data(bytes, size, password); 33 | int n = bufferevent_write(bufev, bytes, size); 34 | // check(n > 0, "write error: %d", n); 35 | 36 | error: 37 | return n; 38 | } 39 | 40 | int decode_copy_pass(Password *pass, bufferevent *dst, bufferevent *src) { 41 | size_t n = 0; 42 | int first_time = 1; 43 | while (1) { 44 | byte buf[BUFFER_SIZE] = {0}; 45 | n = decode_read(pass, src, buf, BUFFER_SIZE); 46 | log_t("read %d bytes", n); 47 | if (n <= 0) { 48 | log_t("no more data"); 49 | if (first_time) { 50 | // close all 51 | return -1; 52 | } 53 | break; 54 | } 55 | first_time = 0; 56 | n = bufferevent_write(dst, buf, n); 57 | log_t("write %d bytes", n); 58 | } 59 | return 0; 60 | } 61 | 62 | int decode_copy(SecureSocket *ss, bufferevent *dst, bufferevent *src) { 63 | if (!ss || !ss->password) { 64 | return -1; 65 | } 66 | return decode_copy_pass(ss->password, dst, src); 67 | } 68 | 69 | int encode_copy_pass(Password *pass, bufferevent *dst, bufferevent *src) { 70 | size_t n = 0; 71 | int first_time = 1; 72 | while (1) { 73 | byte buf[BUFFER_SIZE] = {0}; 74 | n = bufferevent_read(src, buf, BUFFER_SIZE); 75 | log_t("read %d bytes", n); 76 | if (n <= 0) { 77 | log_t("no more data"); 78 | if (first_time) { 79 | // close all 80 | return -1; 81 | } 82 | break; 83 | } 84 | first_time = 0; 85 | n = encode_write(pass, dst, buf, n); // write encode data 86 | log_t("write %d bytes", n); 87 | } 88 | return 0; 89 | } 90 | 91 | int encode_copy(SecureSocket *ss, bufferevent *dst, bufferevent *src) { 92 | if (!ss || !ss->password) { 93 | return -1; 94 | } 95 | return encode_copy_pass(ss->password, dst, src); 96 | } 97 | 98 | void bufferevent_clear_free(bufferevent *bev) { 99 | bufferevent_setcb(bev, NULL, NULL, NULL, NULL); 100 | bufferevent_free(bev); 101 | } 102 | 103 | void securesocket_free(SecureSocket *ss) { 104 | if (ss->password) { 105 | free(ss->password); 106 | } 107 | free(ss); 108 | } -------------------------------------------------------------------------------- /lib/securesocket.h: -------------------------------------------------------------------------------- 1 | #ifndef __SECURESOCKET_H__ 2 | #define __SECURESOCKET_H__ 3 | #include "password.h" 4 | #include 5 | /**For portable socket on windows**/ 6 | #include 7 | 8 | #define BUFFER_SIZE 1024 9 | typedef struct bufferevent bufferevent; 10 | typedef struct sockaddr_in sockaddr_in; 11 | 12 | typedef struct { 13 | Password *password; 14 | // bufferevent *local_bufev; 15 | // bufferevent *remote_bufev; 16 | sockaddr_in *local_addr; // local server's addr 17 | sockaddr_in *remote_addr; // remote proxy server's addr 18 | } SecureSocket; 19 | 20 | // void set_password(Password *password); 21 | 22 | /** 23 | * @brief Read encoded data from buffevent, 24 | * and write decode data to bytes 25 | * @retval n bytes read 26 | */ 27 | int decode_read(Password *pass, bufferevent *bufev, byte bytes[], size_t size); 28 | 29 | /** 30 | * @brief Encode data in bytes, then write to bufev 31 | * @retval n bytes writed 32 | */ 33 | int encode_write(Password *pass, bufferevent *bufev, byte bytes[], size_t size); 34 | 35 | /** 36 | * @brief Read encoded data from src, then write decoded to dst. 37 | * @param *dst: dst bufferevent to write 38 | * @param *src: read from src 39 | * @retval -1 if there is no data to read 40 | */ 41 | int decode_copy(SecureSocket *ss, bufferevent *dst, bufferevent *src); 42 | 43 | int decode_copy_pass(Password *pass, bufferevent *dst, bufferevent *src); 44 | 45 | /** 46 | * @brief Read data from src, encode it and write into dst 47 | * @param *dst: dst bufferevent to write 48 | * @param *src: read from src 49 | * @retval -1 if there is no data to read 50 | */ 51 | int encode_copy(SecureSocket *ss, bufferevent *dst, bufferevent *src); 52 | 53 | int encode_copy_pass(Password *pass, bufferevent *dst, bufferevent *src); 54 | 55 | /** 56 | * @brief CLear buffferevent callback adn free it. 57 | */ 58 | void bufferevent_clear_free(bufferevent *bev); 59 | 60 | void securesocket_free(SecureSocket *ss); 61 | 62 | #endif // __SECURESOCKET__ -------------------------------------------------------------------------------- /server/server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by leer on 6/22/18. 3 | **/ 4 | #include "server.h" 5 | #include "../lib/log.h" 6 | #include "../lib/password.h" 7 | #include "../lib/securesocket.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #ifdef _WIN32 18 | #include 19 | #include 20 | #else 21 | // For inet_addr 22 | #include 23 | #include 24 | #include 25 | // For gethostbyname 26 | #include 27 | #endif 28 | 29 | #define SOCKS_BUF 257 30 | 31 | typedef struct { 32 | // SecureSocket *ss; 33 | bufferevent *remote_bev; // what you really want 34 | bufferevent *local_bev; // listen to lightsocks local 35 | } LsServer; 36 | 37 | static event_base *base; 38 | static Password *global_password; 39 | 40 | /** 41 | * @brief parse SOCKS5 to get remote addr, and response. 42 | * @param *bev: bufferevent to read 43 | * @param *remote_addr: sockaddr_in must has been alloc 44 | * @see example: parse SOCKS4 45 | * http://www.wangafu.net/~nickm/libevent-book/Ref7_evbuffer.html 46 | * https://www.ietf.org/rfc/rfc1928.txt 47 | * @see evbuffer_pullup() 48 | * @retval None 49 | */ 50 | static int parse_socks5(bufferevent *bev, sockaddr_in *remote_addr) { 51 | 52 | // +----+----------+----------+ 53 | // |VER | NMETHODS | METHODS | 54 | // +----+----------+----------+ 55 | // | 1 | 1 | 1 to 255 | 56 | // +----+----------+----------+ 57 | byte buf[SOCKS_BUF] = {0}; 58 | int n = decode_read(global_password, bev, buf, SOCKS_BUF); 59 | log_d("read %d bytes", n); 60 | 61 | if (buf[0] != 0x05) { 62 | log_e("SOCKS5 only!"); 63 | return -1; 64 | } 65 | // +----+--------+ 66 | // |VER | METHOD | 67 | // +----+--------+ 68 | // | 1 | 1 | 69 | // +----+--------+ 70 | byte reply_auth[2] = {0x05, 0x00}; 71 | encode_data(reply_auth, 2, global_password); 72 | n = bufferevent_write(bev, reply_auth, 2); 73 | // n = encode_write(global_password, bev, reply_auth, 2); 74 | log_d("write %d bytes", n); 75 | // sub-negotiation 76 | // 77 | // * +----+-----+-------+------+----------+----------+ 78 | // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | 79 | // +----+-----+-------+------+----------+----------+ 80 | // | 1 | 1 | X'00' | 1 | Variable | 2 | 81 | // +----+-----+-------+------+----------+----------+ 82 | n = decode_read(global_password, bev, buf, SOCKS_BUF); 83 | log_d("read %d bytes", n); 84 | 85 | if (buf[1] != 0x01) { 86 | log_e("CONNECT only"); 87 | return -1; 88 | } 89 | 90 | // ATYP address type of following address 91 | // IP V4 address: X'01' 92 | // DOMAINNAME: X'03' 93 | // IP V6 address: X'04' 94 | remote_addr->sin_family = AF_INET; 95 | remote_addr->sin_port = htons(buf[n - 2] << 8 | buf[n - 1]); 96 | 97 | int name_len = n - 4 - 2; 98 | char domain[name_len]; 99 | switch (buf[3]) { 100 | case 0x01: 101 | log_w("IP v4"); 102 | in_addr_t ipv4 = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; 103 | remote_addr->sin_addr.s_addr = htonl(ipv4); 104 | // remote_addr->sin_port = htons(buf[8] << 8 | buf[9]); 105 | break; 106 | case 0x03: 107 | log_w("domain name"); 108 | for (int i = 0; i < name_len; i++) { 109 | domain[i] = buf[i + 4]; 110 | } 111 | // remote_addr->sin_port = htons(buf[n - 2] << 8 | buf[n - 1]); 112 | log_d("resolve domain: %s", domain); 113 | struct hostent *host = gethostbyname(domain); 114 | remote_addr->sin_addr.s_addr = ((struct in_addr *)host->h_name)->s_addr; 115 | // struct addrinfo hints, *res; 116 | // memset(&hints, 0, sizeof hints); 117 | // hints.ai_family = AF_INET; // IPv4 118 | // hints.ai_socktype = SOCK_STREAM; 119 | // // hints.ai_flags = AI_PASSIVE; 120 | // status = getaddrinfo(domain, ntohs(remote_addr->sin_port), &hints, &res); 121 | return -1; 122 | break; 123 | case 0x04: 124 | log_w("IP v4 only"); 125 | return -1; 126 | break; 127 | default: 128 | log_e("ATYP error"); 129 | return -1; 130 | break; 131 | } 132 | return 0; 133 | // byte auth_buf[] = evbuffer_pullup(bufferevent_get_input(bev), 3); 134 | } 135 | 136 | // read from remote, then encode data send to Lslocal 137 | void remote_readcb(bufferevent *remote_bev, void *arg) { 138 | LsServer *server = arg; 139 | check(server, "null context"); 140 | 141 | check(encode_copy_pass(global_password, server->local_bev, remote_bev) != -1, 142 | "read error"); 143 | return; 144 | error: 145 | bufferevent_clear_free(server->local_bev); 146 | bufferevent_clear_free(remote_bev); 147 | } 148 | 149 | // read from Lslocal, prase SOCKS5, dial real remote addr. 150 | void local_readcb(bufferevent *bev, void *arg) { 151 | LsServer *server = arg; 152 | check(server, "null context"); 153 | 154 | bufferevent *remote_bev; 155 | sockaddr_in remote_addr; // connect to remote 156 | memset(&remote_addr, 0, sizeof(sockaddr_in)); 157 | 158 | // parse socks5 159 | check(parse_socks5(bev, &remote_addr) != -1, "parse socks5 error"); 160 | 161 | remote_bev = bufferevent_socket_new( 162 | base, -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 163 | 164 | int rc = bufferevent_socket_connect( 165 | remote_bev, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr_in)); 166 | check(rc != -1, "can't connect remote server"); 167 | log_d("connected to remote server"); 168 | 169 | // disable linger 170 | int remotefd = bufferevent_getfd(remote_bev); 171 | struct linger linger; 172 | memset(&linger, 0, sizeof(struct linger)); 173 | check(setsockopt(remotefd, SOL_SOCKET, SO_LINGER, (const void *)&linger, 174 | sizeof(struct linger)) == 0, 175 | "can't disable linger"); 176 | 177 | server->remote_bev = remote_bev; 178 | 179 | bufferevent_setcb(remote_bev, remote_readcb, NULL, NULL, server); 180 | bufferevent_enable(remote_bev, EV_READ | EV_WRITE); 181 | 182 | //+----+-----+-------+------+----------+----------+ 183 | //|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | 184 | //+----+-----+-------+------+----------+----------+ 185 | //| 1 | 1 | X'00' | 1 | Variable | 2 | 186 | //+----+-----+-------+------+----------+----------+ 187 | // concted to remote server , send socks5 reply to Lslocal 188 | byte socks5_reply[] = {0x05, 0x00, 0x00, 0x01, 0x00, 189 | 0x00, 0x00, 0x00, 0x00, 0x00}; 190 | encode_write(global_password, bev, socks5_reply, 10); 191 | 192 | // SOCKS5 FINISH, START TRANSMIT 193 | // read data from local bev, then decode data and send to remote server 194 | check(decode_copy_pass(global_password, remote_bev, bev) != -1, "read error"); 195 | 196 | return; 197 | error: 198 | bufferevent_clear_free(bev); 199 | bufferevent_clear_free(remote_bev); 200 | } 201 | 202 | void local_eventcb(bufferevent *bev, short events, void *arg) { 203 | if (events && (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { 204 | // event_base *base = arg; 205 | LsServer *server = arg; 206 | if (bev) { 207 | bufferevent_clear_free(bev); // client->local_bev 208 | if (server) { 209 | bufferevent_clear_free(server->remote_bev); 210 | free(server); 211 | } 212 | } 213 | if (events & BEV_EVENT_EOF) { 214 | log_d("connection %d closed", bufferevent_getfd(bev)); 215 | } else if (events & BEV_EVENT_ERROR) { 216 | log_e("got an error on the connection"); 217 | } 218 | } 219 | } 220 | 221 | void local_listener_cb(evconnlistener *listener, evutil_socket_t fd, 222 | struct sockaddr *sa, int socklen, void *arg) { 223 | // set nonblocking 224 | check(evutil_make_socket_nonblocking(fd) == 0, "can't make no blocking"); 225 | // no waiting for unsent data before closing socketing 226 | struct linger linger; 227 | memset(&linger, 0, sizeof(struct linger)); 228 | check(setsockopt(fd, SOL_SOCKET, SO_LINGER, (const void *)&linger, 229 | sizeof(struct linger)) == 0, 230 | "can't disable linger"); 231 | 232 | Password *pass = arg; 233 | LsServer *ls_server = calloc(1, sizeof(LsServer)); 234 | 235 | bufferevent *local_bev, *remote_bev; 236 | local_bev = bufferevent_socket_new( 237 | base, fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 238 | log_d("new client conncted"); 239 | 240 | ls_server->local_bev = local_bev; 241 | 242 | bufferevent_setcb(local_bev, local_readcb, NULL, local_eventcb, ls_server); 243 | bufferevent_enable(local_bev, EV_READ | EV_WRITE); 244 | 245 | return; 246 | error: 247 | bufferevent_clear_free(local_bev); 248 | free(ls_server); 249 | } 250 | 251 | void listener_errorcb(evconnlistener *listener, void *arg) { 252 | log_e("listen error, exit"); 253 | event_base_loopbreak(base); 254 | } 255 | 256 | void signal_cb(evutil_socket_t sig, short events, void *user_data) { 257 | event_base *base = user_data; 258 | struct timeval delay = {1, 0}; 259 | 260 | log_d("caught an interrupt signal; exiting cleanly in one " 261 | "seconds"); 262 | 263 | event_base_loopexit(base, &delay); 264 | } 265 | 266 | int main() { 267 | log_d("lightsocks-server: starting..."); 268 | // todo read password form json 269 | // ss->password = rand_password(); 270 | global_password = calloc(1, sizeof(Password)); 271 | byte table[] = { 272 | 162, 135, 28, 12, 149, 252, 19, 6, 147, 47, 146, 53, 37, 143, 65, 273 | 226, 77, 92, 115, 157, 151, 79, 26, 16, 89, 36, 82, 41, 153, 129, 274 | 184, 23, 203, 160, 110, 250, 170, 42, 124, 182, 117, 233, 125, 5, 94, 275 | 176, 249, 91, 59, 136, 76, 199, 205, 139, 108, 225, 43, 243, 140, 152, 276 | 116, 171, 103, 48, 188, 17, 49, 27, 228, 102, 158, 50, 90, 3, 232, 277 | 224, 173, 60, 132, 213, 45, 98, 118, 254, 211, 210, 128, 207, 175, 201, 278 | 163, 206, 55, 161, 165, 0, 126, 154, 97, 198, 1, 183, 181, 239, 222, 279 | 167, 39, 15, 58, 51, 236, 195, 96, 245, 131, 85, 9, 127, 142, 8, 280 | 84, 185, 134, 166, 174, 218, 114, 155, 46, 7, 21, 104, 69, 194, 248, 281 | 137, 99, 159, 10, 62, 172, 169, 138, 71, 220, 193, 216, 208, 179, 241, 282 | 235, 130, 189, 180, 88, 64, 31, 24, 75, 192, 133, 123, 70, 255, 63, 283 | 144, 231, 197, 87, 78, 18, 240, 119, 164, 145, 106, 190, 52, 80, 20, 284 | 227, 196, 223, 202, 242, 244, 95, 22, 14, 230, 25, 74, 122, 4, 200, 285 | 215, 38, 221, 204, 86, 105, 68, 238, 247, 214, 177, 2, 212, 66, 148, 286 | 111, 187, 35, 109, 61, 168, 32, 30, 56, 178, 40, 112, 34, 209, 93, 287 | 67, 251, 217, 237, 107, 73, 113, 83, 234, 29, 253, 191, 72, 186, 120, 288 | 33, 13, 229, 44, 150, 219, 57, 121, 81, 141, 11, 156, 54, 100, 101, 289 | 246}; 290 | for (int i = 0; i < PASS_LENGTH; i++) { 291 | global_password->x[i] = table[i]; 292 | } 293 | 294 | event *signal_event; 295 | evconnlistener *listener; 296 | 297 | sockaddr_in local; // listen to local 298 | memset(&local, 0, sizeof(sockaddr_in)); 299 | local.sin_family = AF_INET; 300 | int local_port = 42619; 301 | local.sin_port = htons(local_port); 302 | local.sin_addr.s_addr = htonl(INADDR_ANY); 303 | 304 | base = event_base_new(); 305 | listener = 306 | evconnlistener_new_bind(base, local_listener_cb, global_password, 307 | LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 16, 308 | (struct sockaddr *)&local, sizeof(local)); 309 | check(listener, "listen error"); 310 | evconnlistener_set_error_cb(listener, listener_errorcb); 311 | 312 | log_d("\nListen on [::]:%d\nPassword:\n%s", local_port, 313 | password_string(global_password, NULL)); 314 | 315 | // add Ctrl-C signal event 316 | signal_event = evsignal_new(base, SIGINT, signal_cb, base); 317 | event_add(signal_event, NULL); 318 | 319 | event_base_dispatch(base); 320 | 321 | error: // fall 322 | free(global_password); 323 | event_base_free(base); 324 | evconnlistener_free(listener); 325 | event_free(signal_event); 326 | return 0; 327 | } 328 | -------------------------------------------------------------------------------- /server/server.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERVER_H__ 2 | #define __SERVER_H__ 3 | 4 | typedef struct event_base event_base; 5 | typedef struct event event; 6 | typedef struct evconnlistener evconnlistener; 7 | 8 | #endif --------------------------------------------------------------------------------