iodine 0.4.19 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +22 -0
  4. data/LIMITS.md +19 -9
  5. data/README.md +92 -77
  6. data/SPEC-PubSub-Draft.md +113 -0
  7. data/SPEC-Websocket-Draft.md +127 -143
  8. data/bin/http-hello +0 -1
  9. data/bin/raw-rbhttp +1 -1
  10. data/bin/raw_broadcast +8 -10
  11. data/bin/updated api +2 -2
  12. data/bin/ws-broadcast +2 -4
  13. data/bin/ws-echo +2 -2
  14. data/examples/config.ru +13 -13
  15. data/examples/echo.ru +5 -6
  16. data/examples/hello.ru +2 -3
  17. data/examples/info.md +316 -0
  18. data/examples/pubsub_engine.ru +81 -0
  19. data/examples/redis.ru +9 -9
  20. data/examples/shootout.ru +45 -11
  21. data/ext/iodine/defer.c +194 -297
  22. data/ext/iodine/defer.h +61 -53
  23. data/ext/iodine/evio.c +0 -260
  24. data/ext/iodine/evio.h +50 -22
  25. data/ext/iodine/evio_callbacks.c +26 -0
  26. data/ext/iodine/evio_epoll.c +251 -0
  27. data/ext/iodine/evio_kqueue.c +193 -0
  28. data/ext/iodine/extconf.rb +1 -1
  29. data/ext/iodine/facil.c +1420 -542
  30. data/ext/iodine/facil.h +151 -64
  31. data/ext/iodine/fio_ary.h +418 -0
  32. data/ext/iodine/{base64.c → fio_base64.c} +33 -24
  33. data/ext/iodine/{base64.h → fio_base64.h} +6 -7
  34. data/ext/iodine/{fio_cli_helper.c → fio_cli.c} +77 -58
  35. data/ext/iodine/{fio_cli_helper.h → fio_cli.h} +9 -4
  36. data/ext/iodine/fio_hashmap.h +759 -0
  37. data/ext/iodine/fio_json_parser.h +651 -0
  38. data/ext/iodine/fio_llist.h +257 -0
  39. data/ext/iodine/fio_mem.c +672 -0
  40. data/ext/iodine/fio_mem.h +140 -0
  41. data/ext/iodine/fio_random.c +248 -0
  42. data/ext/iodine/{random.h → fio_random.h} +11 -14
  43. data/ext/iodine/{sha1.c → fio_sha1.c} +28 -24
  44. data/ext/iodine/{sha1.h → fio_sha1.h} +38 -16
  45. data/ext/iodine/{sha2.c → fio_sha2.c} +66 -49
  46. data/ext/iodine/{sha2.h → fio_sha2.h} +57 -26
  47. data/ext/iodine/{fiobj_internal.c → fio_siphash.c} +9 -90
  48. data/ext/iodine/fio_siphash.h +18 -0
  49. data/ext/iodine/fio_tmpfile.h +38 -0
  50. data/ext/iodine/fiobj.h +24 -7
  51. data/ext/iodine/fiobj4sock.h +23 -0
  52. data/ext/iodine/fiobj_ary.c +143 -226
  53. data/ext/iodine/fiobj_ary.h +17 -16
  54. data/ext/iodine/fiobj_data.c +1160 -0
  55. data/ext/iodine/fiobj_data.h +164 -0
  56. data/ext/iodine/fiobj_hash.c +298 -406
  57. data/ext/iodine/fiobj_hash.h +101 -54
  58. data/ext/iodine/fiobj_json.c +478 -601
  59. data/ext/iodine/fiobj_json.h +34 -9
  60. data/ext/iodine/fiobj_numbers.c +383 -51
  61. data/ext/iodine/fiobj_numbers.h +87 -11
  62. data/ext/iodine/fiobj_str.c +423 -184
  63. data/ext/iodine/fiobj_str.h +81 -32
  64. data/ext/iodine/fiobject.c +273 -522
  65. data/ext/iodine/fiobject.h +477 -112
  66. data/ext/iodine/http.c +2243 -83
  67. data/ext/iodine/http.h +842 -121
  68. data/ext/iodine/http1.c +810 -385
  69. data/ext/iodine/http1.h +16 -39
  70. data/ext/iodine/http1_parser.c +146 -74
  71. data/ext/iodine/http1_parser.h +15 -4
  72. data/ext/iodine/http_internal.c +1258 -0
  73. data/ext/iodine/http_internal.h +226 -0
  74. data/ext/iodine/http_mime_parser.h +341 -0
  75. data/ext/iodine/iodine.c +86 -68
  76. data/ext/iodine/iodine.h +26 -11
  77. data/ext/iodine/iodine_helpers.c +8 -7
  78. data/ext/iodine/iodine_http.c +487 -324
  79. data/ext/iodine/iodine_json.c +304 -0
  80. data/ext/iodine/iodine_json.h +6 -0
  81. data/ext/iodine/iodine_protocol.c +107 -45
  82. data/ext/iodine/iodine_pubsub.c +526 -225
  83. data/ext/iodine/iodine_pubsub.h +10 -0
  84. data/ext/iodine/iodine_websockets.c +268 -510
  85. data/ext/iodine/iodine_websockets.h +2 -4
  86. data/ext/iodine/pubsub.c +726 -432
  87. data/ext/iodine/pubsub.h +85 -103
  88. data/ext/iodine/rb-call.c +4 -4
  89. data/ext/iodine/rb-defer.c +46 -22
  90. data/ext/iodine/rb-fiobj2rb.h +117 -0
  91. data/ext/iodine/rb-rack-io.c +73 -238
  92. data/ext/iodine/rb-rack-io.h +2 -2
  93. data/ext/iodine/rb-registry.c +35 -93
  94. data/ext/iodine/rb-registry.h +1 -0
  95. data/ext/iodine/redis_engine.c +742 -304
  96. data/ext/iodine/redis_engine.h +42 -39
  97. data/ext/iodine/resp_parser.h +311 -0
  98. data/ext/iodine/sock.c +627 -490
  99. data/ext/iodine/sock.h +345 -297
  100. data/ext/iodine/spnlock.inc +15 -4
  101. data/ext/iodine/websocket_parser.h +16 -20
  102. data/ext/iodine/websockets.c +188 -257
  103. data/ext/iodine/websockets.h +24 -133
  104. data/lib/iodine.rb +52 -7
  105. data/lib/iodine/cli.rb +6 -24
  106. data/lib/iodine/json.rb +40 -0
  107. data/lib/iodine/version.rb +1 -1
  108. data/lib/iodine/websocket.rb +5 -3
  109. data/lib/rack/handler/iodine.rb +58 -13
  110. metadata +38 -48
  111. data/bin/ws-shootout +0 -107
  112. data/examples/broadcast.ru +0 -56
  113. data/ext/iodine/bscrypt-common.h +0 -116
  114. data/ext/iodine/bscrypt.h +0 -49
  115. data/ext/iodine/fio2resp.c +0 -60
  116. data/ext/iodine/fio2resp.h +0 -51
  117. data/ext/iodine/fio_dict.c +0 -446
  118. data/ext/iodine/fio_dict.h +0 -99
  119. data/ext/iodine/fio_hash_table.h +0 -370
  120. data/ext/iodine/fio_list.h +0 -111
  121. data/ext/iodine/fiobj_internal.h +0 -280
  122. data/ext/iodine/fiobj_primitives.c +0 -131
  123. data/ext/iodine/fiobj_primitives.h +0 -55
  124. data/ext/iodine/fiobj_sym.c +0 -135
  125. data/ext/iodine/fiobj_sym.h +0 -60
  126. data/ext/iodine/hex.c +0 -124
  127. data/ext/iodine/hex.h +0 -70
  128. data/ext/iodine/http1_request.c +0 -81
  129. data/ext/iodine/http1_request.h +0 -58
  130. data/ext/iodine/http1_response.c +0 -417
  131. data/ext/iodine/http1_response.h +0 -95
  132. data/ext/iodine/http_request.c +0 -111
  133. data/ext/iodine/http_request.h +0 -102
  134. data/ext/iodine/http_response.c +0 -1703
  135. data/ext/iodine/http_response.h +0 -250
  136. data/ext/iodine/misc.c +0 -182
  137. data/ext/iodine/misc.h +0 -74
  138. data/ext/iodine/random.c +0 -208
  139. data/ext/iodine/redis_connection.c +0 -278
  140. data/ext/iodine/redis_connection.h +0 -86
  141. data/ext/iodine/resp.c +0 -842
  142. data/ext/iodine/resp.h +0 -261
  143. data/ext/iodine/siphash.c +0 -154
  144. data/ext/iodine/siphash.h +0 -22
  145. data/ext/iodine/xor-crypt.c +0 -193
  146. data/ext/iodine/xor-crypt.h +0 -107
data/ext/iodine/random.c DELETED
@@ -1,208 +0,0 @@
1
- /*
2
- Copyright: Boaz segev, 2016-2017
3
- License: MIT except for any non-public-domain algorithms (none that I'm aware
4
- of), which might be subject to their own licenses.
5
-
6
- Feel free to copy, use and enjoy in accordance with to the license(s).
7
- */
8
- #ifndef _GNU_SOURCE
9
- #define _GNU_SOURCE
10
- #endif
11
- #include "random.h"
12
-
13
- #if defined(USE_ALT_RANDOM) || !defined(HAS_UNIX_FEATURES)
14
- #include "sha2.h"
15
- #include <time.h>
16
-
17
- #ifdef RUSAGE_SELF
18
- static size_t get_clock_mili(void) {
19
- struct rusage rusage;
20
- getrusage(RUSAGE_SELF, &rusage);
21
- return ((rusage.ru_utime.tv_sec + rusage.ru_stime.tv_sec) * 1000000) +
22
- (rusage.ru_utime.tv_usec + rusage.ru_stime.tv_usec);
23
- }
24
- #elif defined CLOCKS_PER_SEC
25
- #define get_clock_mili() (size_t) clock()
26
- #else
27
- #define get_clock_mili() 0
28
- #error Random alternative failed to find access to the CPU clock state.
29
- #endif
30
-
31
- uint32_t bscrypt_rand32(void) {
32
- bits256_u pseudo = bscrypt_rand256();
33
- return pseudo.ints[3];
34
- }
35
-
36
- uint64_t bscrypt_rand64(void) {
37
- bits256_u pseudo = bscrypt_rand256();
38
- return pseudo.words[3];
39
- }
40
-
41
- bits128_u bscrypt_rand128(void) {
42
- bits256_u pseudo = bscrypt_rand256();
43
- bits128_u ret;
44
- ret.words[0] = pseudo.words[0];
45
- ret.words[1] = pseudo.words[1];
46
- return ret;
47
- }
48
-
49
- bits256_u bscrypt_rand256(void) {
50
- size_t cpu_state = get_clock_mili();
51
- time_t the_time;
52
- time(&the_time);
53
- bits256_u pseudo;
54
- sha2_s sha2 = bscrypt_sha2_init(SHA_256);
55
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
56
- bscrypt_sha2_write(&sha2, &the_time, sizeof(the_time));
57
- bscrypt_sha2_write(&sha2, ((char *)&cpu_state) - 64, 64); /* the stack */
58
- bscrypt_sha2_result(&sha2);
59
- pseudo.words[0] = sha2.digest.i64[0];
60
- pseudo.words[1] = sha2.digest.i64[1];
61
- pseudo.words[2] = sha2.digest.i64[2];
62
- pseudo.words[3] = sha2.digest.i64[3];
63
- return pseudo;
64
- }
65
-
66
- void bscrypt_rand_bytes(void *target, size_t length) {
67
- clock_t cpu_state = clock();
68
- time_t the_time;
69
- time(&the_time);
70
- sha2_s sha2 = bscrypt_sha2_init(SHA_512);
71
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
72
- bscrypt_sha2_write(&sha2, &the_time, sizeof(the_time));
73
- bscrypt_sha2_write(&sha2, &cpu_state - 2, 64); /* whatever's on the stack */
74
- bscrypt_sha2_result(&sha2);
75
- while (length > 64) {
76
- memcpy(target, sha2.digest.str, 64);
77
- length -= 64;
78
- target = (void *)((uintptr_t)target + 64);
79
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
80
- bscrypt_sha2_result(&sha2);
81
- }
82
- if (length > 32) {
83
- memcpy(target, sha2.digest.str, 32);
84
- length -= 32;
85
- target = (void *)((uintptr_t)target + 32);
86
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
87
- bscrypt_sha2_result(&sha2);
88
- }
89
- if (length > 16) {
90
- memcpy(target, sha2.digest.str, 16);
91
- length -= 16;
92
- target = (void *)((uintptr_t)target + 16);
93
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
94
- bscrypt_sha2_result(&sha2);
95
- }
96
- if (length > 8) {
97
- memcpy(target, sha2.digest.str, 8);
98
- length -= 8;
99
- target = (void *)((uintptr_t)target + 8);
100
- bscrypt_sha2_write(&sha2, &cpu_state, sizeof(cpu_state));
101
- bscrypt_sha2_result(&sha2);
102
- }
103
- while (length) {
104
- *((uint8_t *)target) = sha2.digest.str[length];
105
- target = (void *)((uintptr_t)target + 1);
106
- --length;
107
- }
108
- }
109
-
110
- #else
111
- /* ***************************************************************************
112
- Unix Random Engine (use built in machine)
113
- */
114
- #include <errno.h>
115
- #include <fcntl.h>
116
- #include <pthread.h>
117
- #include <unistd.h>
118
-
119
- /* ***************************************************************************
120
- Machine specific changes
121
- */
122
- // #ifdef __linux__
123
- // #undef bswap16
124
- // #undef bswap32
125
- // #undef bswap64
126
- // #include <machine/bswap.h>
127
- // #endif
128
- #ifdef HAVE_X86Intrin
129
- // #undef bswap16
130
- /*
131
- #undef bswap32
132
- #define bswap32(i) \
133
- { __asm__("bswap %k0" : "+r"(i) :); }
134
- */
135
- #undef bswap64
136
- #define bswap64(i) \
137
- { __asm__("bswapq %0" : "+r"(i) :); }
138
-
139
- // shadow sched_yield as _mm_pause for spinwait
140
- #define sched_yield() _mm_pause()
141
- #endif
142
-
143
- /* ***************************************************************************
144
- Random ... (why is this not a system call?)
145
- */
146
-
147
- /* rand generator management */
148
- static int _rand_fd_ = -1;
149
- static void close_rand_fd(void) {
150
- if (_rand_fd_ >= 0)
151
- close(_rand_fd_);
152
- _rand_fd_ = -1;
153
- }
154
- static void init_rand_fd(void) {
155
- if (_rand_fd_ < 0) {
156
- while ((_rand_fd_ = open("/dev/urandom", O_RDONLY)) == -1) {
157
- if (errno == ENXIO)
158
- perror("bscrypt fatal error, caanot initiate random generator"),
159
- exit(-1);
160
- sched_yield();
161
- }
162
- }
163
- atexit(close_rand_fd);
164
- }
165
- /* rand function template */
166
- #define MAKE_RAND_FUNC(type, func_name) \
167
- type func_name(void) { \
168
- if (_rand_fd_ < 0) \
169
- init_rand_fd(); \
170
- type ret; \
171
- while (read(_rand_fd_, &ret, sizeof(type)) < 0) \
172
- sched_yield(); \
173
- return ret; \
174
- }
175
- /* rand functions */
176
- MAKE_RAND_FUNC(uint32_t, bscrypt_rand32)
177
- MAKE_RAND_FUNC(uint64_t, bscrypt_rand64)
178
- MAKE_RAND_FUNC(bits128_u, bscrypt_rand128)
179
- MAKE_RAND_FUNC(bits256_u, bscrypt_rand256)
180
- /* clear template */
181
- #undef MAKE_RAND_FUNC
182
-
183
- void bscrypt_rand_bytes(void *target, size_t length) {
184
- if (_rand_fd_ < 0)
185
- init_rand_fd();
186
- while (read(_rand_fd_, target, length) < 0)
187
- sched_yield();
188
- }
189
- #endif /* Unix Random */
190
-
191
- /*******************************************************************************
192
- Random
193
- */
194
- #if defined(DEBUG) && DEBUG == 1
195
- void bscrypt_test_random(void) {
196
- clock_t start, end;
197
- bscrypt_rand256();
198
- start = clock();
199
- for (size_t i = 0; i < 100000; i++) {
200
- bscrypt_rand256();
201
- }
202
- end = clock();
203
- fprintf(stderr,
204
- "+ bscrypt Random generator available\n+ bscrypt 100K X 256bit "
205
- "Random %lu CPU clock count\n",
206
- end - start);
207
- }
208
- #endif
@@ -1,278 +0,0 @@
1
- /*
2
- Copyright: Boaz segev, 2017
3
- License: MIT except for any non-public-domain algorithms (none that I'm aware
4
- of), which might be subject to their own licenses.
5
-
6
- Feel free to copy, use and enjoy in accordance with to the license(s).
7
- */
8
- #include "spnlock.inc"
9
-
10
- #include "fio_list.h"
11
- #include "redis_connection.h"
12
- #include <errno.h>
13
- #include <math.h>
14
- #include <signal.h>
15
- #include <string.h>
16
- #include <strings.h>
17
-
18
- /* *****************************************************************************
19
- Memory and Data structures - The protocol object.
20
- ***************************************************************************** */
21
- #ifndef REDIS_POOL_SIZES /* per protocol */
22
- #define REDIS_POOL_SIZES 256
23
- #endif
24
-
25
- #ifndef REDIS_READ_BUFFER /* during network data events */
26
- #define REDIS_READ_BUFFER 2048
27
- #endif
28
-
29
- /* a protocol ID string */
30
- static const char *REDIS_PROTOCOL_ID =
31
- "Redis Protocol for the facil.io framework";
32
- /* Pings */
33
- #define REDIS_PING_LEN 24
34
- static const char REDIS_PING_STR[] = "*2\r\n"
35
- "$4\r\nPING\r\n"
36
- "$24\r\nfacil.io connection PING\r\n";
37
- static const char REDIS_PING_PAYLOAD[] = "facil.io connection PING";
38
-
39
- typedef struct {
40
- protocol_s protocol;
41
- struct redis_context_args *settings;
42
- unsigned authenticated : 1;
43
- } redis_protocol_s;
44
-
45
- static inline size_t ul2a(char *dest, size_t num) {
46
- uint8_t digits = 1;
47
- size_t tmp = num;
48
- while ((tmp /= 10))
49
- ++digits;
50
-
51
- if (dest) {
52
- dest += digits;
53
- *(dest--) = 0;
54
- }
55
- for (size_t i = 0; i < digits; i++) {
56
- num = num - (10 * (tmp = (num / 10)));
57
- if (dest)
58
- *(dest--) = '0' + num;
59
- num = tmp;
60
- }
61
- return digits;
62
- }
63
-
64
- /* *****************************************************************************
65
- The Protocol Context
66
- ***************************************************************************** */
67
- #undef redis_create_context
68
- void *redis_create_context(struct redis_context_args args) {
69
- if (!args.on_message || !args.parser) {
70
- fprintf(stderr, "A Redix connection context requires both an `on_message` "
71
- "callback and a parser.\n");
72
- exit(EINVAL);
73
- }
74
- if (args.auth) {
75
- if (!args.auth_len)
76
- args.auth_len = strlen(args.auth);
77
- args.auth_len++;
78
- }
79
- struct redis_context_args *c = malloc(sizeof(*c) + args.auth_len);
80
- *c = args;
81
- if (args.auth) {
82
- c->auth_len--;
83
- c->auth = (char *)(c + 1);
84
- memcpy(c->auth, args.auth, c->auth_len);
85
- c->auth[c->auth_len] = 0;
86
- }
87
- return c;
88
- }
89
-
90
- /* *****************************************************************************
91
- The Protocol Callbacks
92
- ***************************************************************************** */
93
-
94
- void redis_protocol_cleanup(intptr_t uuid, void *settings) {
95
- struct redis_context_args *s = settings;
96
- if (s->on_close)
97
- s->on_close(uuid, s->udata);
98
- if (s->autodestruct)
99
- free(settings);
100
- }
101
-
102
- static void redis_on_close_client(intptr_t uuid, protocol_s *pr) {
103
- redis_protocol_s *r = (redis_protocol_s *)pr;
104
- // if (r->settings->on_close)
105
- // r->settings->on_close(uuid, r->settings->udata);
106
- redis_protocol_cleanup(uuid, r->settings);
107
- free(r);
108
- }
109
-
110
- static void redis_on_close_server(intptr_t uuid, protocol_s *pr) {
111
- redis_protocol_s *r = (redis_protocol_s *)pr;
112
- if (r->settings->on_close)
113
- r->settings->on_close(uuid, r->settings->udata);
114
- free(r);
115
- }
116
-
117
- /** called when a connection's timeout was reached */
118
- static void redis_ping(intptr_t uuid, protocol_s *pr) {
119
- /* We cannow write directly to the socket in case `redis_send` has scheduled
120
- * callbacks. */
121
- sock_write2(.uuid = uuid, .buffer = REDIS_PING_STR,
122
- .length = sizeof(REDIS_PING_STR) - 1, .move = 1,
123
- .dealloc = SOCK_DEALLOC_NOOP);
124
- (void)pr;
125
- }
126
-
127
- /** called when a data is available, but will not run concurrently */
128
- static void redis_on_data_deferred(intptr_t uuid, protocol_s *pr, void *d);
129
- static void redis_on_data(intptr_t uuid, protocol_s *pr) {
130
- redis_protocol_s *r = (redis_protocol_s *)pr;
131
- uint8_t buffer[REDIS_READ_BUFFER];
132
- ssize_t len, limit, pos;
133
- resp_object_s *msg;
134
- limit = len = sock_read(uuid, buffer, REDIS_READ_BUFFER);
135
- if (len <= 0)
136
- return;
137
- pos = 0;
138
- while (len) {
139
- msg = resp_parser_feed(r->settings->parser, buffer + pos, (size_t *)&len);
140
- if (!len && !msg) {
141
- fprintf(stderr, "ERROR: (RESP Parser) Bad input (%lu):\n%s\n", limit,
142
- buffer);
143
- /* we'll simply ignore bad input. skip a line. */
144
- for (; pos < limit; pos++) {
145
- len++;
146
- if (buffer[pos] == '\n') {
147
- pos++;
148
- len++;
149
- break; /* from `for` loop */
150
- }
151
- }
152
- continue; /* while loop */
153
- }
154
- if (msg) {
155
- if (r->authenticated) {
156
- r->authenticated--;
157
- if (msg->type != RESP_OK) {
158
- if (msg->type == RESP_ERR) {
159
- fprintf(stderr,
160
- "ERROR: (RedisConnection) Authentication FAILED.\n"
161
- " %s\n",
162
- resp_obj2str(msg)->string);
163
- } else {
164
- fprintf(stderr,
165
- "ERROR: (RedisConnection) Authentication FAILED "
166
- "(unexpected response %d).\n",
167
- msg->type);
168
- }
169
- }
170
- } else if ((msg->type == RESP_STRING &&
171
- resp_obj2str(msg)->len == REDIS_PING_LEN &&
172
- !memcmp(resp_obj2str(msg)->string, REDIS_PING_PAYLOAD,
173
- REDIS_PING_LEN)) ||
174
- (msg->type == RESP_ARRAY &&
175
- resp_obj2arr(msg)->array[0]->type == RESP_STRING &&
176
- resp_obj2str(resp_obj2arr(msg)->array[0])->len == 4 &&
177
- resp_obj2arr(msg)->array[1]->type == RESP_STRING &&
178
- resp_obj2str(resp_obj2arr(msg)->array[1])->len ==
179
- REDIS_PING_LEN &&
180
- !strncasecmp(
181
- (char *)resp_obj2str(resp_obj2arr(msg)->array[0])->string,
182
- "pong", 4) &&
183
- !memcmp(
184
- (char *)resp_obj2str(resp_obj2arr(msg)->array[0])->string,
185
- REDIS_PING_PAYLOAD, REDIS_PING_LEN))) {
186
- /* an internal ping, do not forward. */
187
- } else
188
- r->settings->on_message(uuid, msg, r->settings->udata);
189
- resp_free_object(msg);
190
- msg = NULL;
191
- }
192
- if (len == limit) {
193
- /* fragment events, it's edge polling, so we need to read everything */
194
- facil_defer(.uuid = uuid, .task = redis_on_data_deferred,
195
- .task_type = FIO_PR_LOCK_TASK);
196
- return;
197
- }
198
- pos += len;
199
- limit = len = limit - len;
200
- }
201
- }
202
- static void redis_on_data_deferred(intptr_t uuid, protocol_s *pr, void *d) {
203
- if (!pr || pr->service != REDIS_PROTOCOL_ID)
204
- return;
205
- redis_on_data(uuid, pr);
206
- (void)d;
207
- }
208
-
209
- static void redis_on_open(intptr_t uuid, protocol_s *pr, void *d) {
210
- redis_protocol_s *r = (void *)pr;
211
- facil_set_timeout(uuid, r->settings->ping);
212
- if (r->settings->auth) {
213
- r->authenticated = 1;
214
- size_t n_len = ul2a(NULL, r->settings->auth_len);
215
- char *t =
216
- malloc(r->settings->auth_len + 20 + n_len); /* 19 is probably enough */
217
- memcpy(t, "*2\r\n$4\r\nAUTH\r\n$", 15);
218
- ul2a(t + 15, r->settings->auth_len);
219
- t[15 + n_len] = '\r';
220
- t[16 + n_len] = '\n';
221
- memcpy(t + 17 + n_len, r->settings->auth, r->settings->auth_len);
222
- t[17 + n_len + r->settings->auth_len] = '\r';
223
- t[18 + n_len + r->settings->auth_len] = '\n';
224
- t[19 + n_len + r->settings->auth_len] = 0; /* we don't need it, but nice */
225
- sock_write2(.uuid = uuid, .buffer = t,
226
- .length = (19 + n_len + r->settings->auth_len), .move = 1);
227
-
228
- } else
229
- r->authenticated = 0;
230
- r->settings->on_open(uuid, r->settings->udata);
231
- (void)d;
232
- }
233
-
234
- /**
235
- * This function is used as a function pointer for the `facil_connect` and
236
- * calls (the `on_connect` callback).
237
- */
238
- protocol_s *redis_create_client_protocol(intptr_t uuid, void *settings) {
239
- redis_protocol_s *r = malloc(sizeof(*r));
240
- *r = (redis_protocol_s){
241
- .protocol =
242
- {
243
- .service = REDIS_PROTOCOL_ID,
244
- .on_data = redis_on_data,
245
- .on_close = redis_on_close_client,
246
- .ping = redis_ping,
247
- },
248
- .settings = settings,
249
- };
250
- facil_set_timeout(uuid, r->settings->ping);
251
- if (r->settings->on_open)
252
- facil_defer(.task = redis_on_open, .uuid = uuid);
253
- return &r->protocol;
254
- (void)uuid;
255
- }
256
-
257
- /**
258
- * This function is used as a function pointer for the `facil_listen` calls (the
259
- * `on_open` callbacks).
260
- */
261
- protocol_s *redis_create_server_protocol(intptr_t uuid, void *settings) {
262
- redis_protocol_s *r = malloc(sizeof(*r));
263
- *r = (redis_protocol_s){
264
- .protocol =
265
- {
266
- .service = REDIS_PROTOCOL_ID,
267
- .on_data = redis_on_data,
268
- .on_close = redis_on_close_server,
269
- .ping = redis_ping,
270
- },
271
- .settings = settings,
272
- };
273
- facil_set_timeout(uuid, r->settings->ping);
274
- if (r->settings->on_open)
275
- facil_defer(.task = redis_on_open, .uuid = uuid);
276
- return &r->protocol;
277
- (void)uuid;
278
- }