iodine 0.1.21 → 0.2.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.travis.yml +23 -2
  4. data/CHANGELOG.md +9 -2
  5. data/README.md +232 -179
  6. data/Rakefile +13 -1
  7. data/bin/config.ru +63 -0
  8. data/bin/console +6 -0
  9. data/bin/echo +42 -32
  10. data/bin/http-hello +62 -0
  11. data/bin/http-playground +124 -0
  12. data/bin/playground +62 -0
  13. data/bin/poc/Gemfile.lock +23 -0
  14. data/bin/poc/README.md +37 -0
  15. data/bin/poc/config.ru +66 -0
  16. data/bin/poc/gemfile +1 -0
  17. data/bin/poc/www/index.html +57 -0
  18. data/bin/raw-rbhttp +35 -0
  19. data/bin/raw_broadcast +66 -0
  20. data/bin/test_with_faye +40 -0
  21. data/bin/ws-broadcast +108 -0
  22. data/bin/ws-echo +108 -0
  23. data/exe/iodine +59 -0
  24. data/ext/iodine/base64.c +264 -0
  25. data/ext/iodine/base64.h +72 -0
  26. data/ext/iodine/bscrypt-common.h +109 -0
  27. data/ext/iodine/bscrypt.h +49 -0
  28. data/ext/iodine/extconf.rb +41 -0
  29. data/ext/iodine/hex.c +123 -0
  30. data/ext/iodine/hex.h +70 -0
  31. data/ext/iodine/http.c +200 -0
  32. data/ext/iodine/http.h +128 -0
  33. data/ext/iodine/http1.c +402 -0
  34. data/ext/iodine/http1.h +56 -0
  35. data/ext/iodine/http1_simple_parser.c +473 -0
  36. data/ext/iodine/http1_simple_parser.h +59 -0
  37. data/ext/iodine/http_request.h +128 -0
  38. data/ext/iodine/http_response.c +1606 -0
  39. data/ext/iodine/http_response.h +393 -0
  40. data/ext/iodine/http_response_http1.h +374 -0
  41. data/ext/iodine/iodine_core.c +641 -0
  42. data/ext/iodine/iodine_core.h +70 -0
  43. data/ext/iodine/iodine_http.c +615 -0
  44. data/ext/iodine/iodine_http.h +19 -0
  45. data/ext/iodine/iodine_websocket.c +430 -0
  46. data/ext/iodine/iodine_websocket.h +21 -0
  47. data/ext/iodine/libasync.c +552 -0
  48. data/ext/iodine/libasync.h +117 -0
  49. data/ext/iodine/libreact.c +347 -0
  50. data/ext/iodine/libreact.h +244 -0
  51. data/ext/iodine/libserver.c +912 -0
  52. data/ext/iodine/libserver.h +435 -0
  53. data/ext/iodine/libsock.c +950 -0
  54. data/ext/iodine/libsock.h +478 -0
  55. data/ext/iodine/misc.c +181 -0
  56. data/ext/iodine/misc.h +76 -0
  57. data/ext/iodine/random.c +193 -0
  58. data/ext/iodine/random.h +48 -0
  59. data/ext/iodine/rb-call.c +127 -0
  60. data/ext/iodine/rb-call.h +60 -0
  61. data/ext/iodine/rb-libasync.h +79 -0
  62. data/ext/iodine/rb-rack-io.c +389 -0
  63. data/ext/iodine/rb-rack-io.h +17 -0
  64. data/ext/iodine/rb-registry.c +213 -0
  65. data/ext/iodine/rb-registry.h +33 -0
  66. data/ext/iodine/sha1.c +359 -0
  67. data/ext/iodine/sha1.h +85 -0
  68. data/ext/iodine/sha2.c +825 -0
  69. data/ext/iodine/sha2.h +138 -0
  70. data/ext/iodine/siphash.c +136 -0
  71. data/ext/iodine/siphash.h +15 -0
  72. data/ext/iodine/spnlock.h +235 -0
  73. data/ext/iodine/websockets.c +696 -0
  74. data/ext/iodine/websockets.h +120 -0
  75. data/ext/iodine/xor-crypt.c +189 -0
  76. data/ext/iodine/xor-crypt.h +107 -0
  77. data/iodine.gemspec +25 -18
  78. data/lib/iodine.rb +57 -58
  79. data/lib/iodine/http.rb +0 -189
  80. data/lib/iodine/protocol.rb +36 -245
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/rack/handler/iodine.rb +145 -2
  83. metadata +115 -37
  84. data/bin/core_http_test +0 -51
  85. data/bin/em playground +0 -56
  86. data/bin/hello_world +0 -75
  87. data/bin/setup +0 -7
  88. data/lib/iodine/client.rb +0 -5
  89. data/lib/iodine/core.rb +0 -102
  90. data/lib/iodine/core_init.rb +0 -143
  91. data/lib/iodine/http/hpack.rb +0 -553
  92. data/lib/iodine/http/http1.rb +0 -251
  93. data/lib/iodine/http/http2.rb +0 -507
  94. data/lib/iodine/http/rack_support.rb +0 -108
  95. data/lib/iodine/http/request.rb +0 -462
  96. data/lib/iodine/http/response.rb +0 -474
  97. data/lib/iodine/http/session.rb +0 -143
  98. data/lib/iodine/http/websocket_client.rb +0 -335
  99. data/lib/iodine/http/websocket_handler.rb +0 -101
  100. data/lib/iodine/http/websockets.rb +0 -336
  101. data/lib/iodine/io.rb +0 -56
  102. data/lib/iodine/logging.rb +0 -46
  103. data/lib/iodine/settings.rb +0 -158
  104. data/lib/iodine/ssl_connector.rb +0 -48
  105. data/lib/iodine/timers.rb +0 -95
@@ -0,0 +1,120 @@
1
+ #ifndef WEBSOCKETS_H
2
+ #define WEBSOCKETS_H
3
+
4
+ #include "http_request.h"
5
+ #include "http_response.h"
6
+
7
+ /**
8
+ The Websocket type is an opaque type used by the websocket API to provide
9
+ identify a specific Websocket connection and manage it's internal state.
10
+ */
11
+ typedef struct Websocket ws_s;
12
+
13
+ /**
14
+ The protocol / service identifier for `libserver`.
15
+ */
16
+ extern char* WEBSOCKET_ID_STR;
17
+ /**
18
+ The Websocket Handler contains all the settings required for new websocket
19
+ connections.
20
+
21
+ This struct is used for the named agruments in the `websocket_upgrade`
22
+ macro.
23
+ */
24
+ typedef struct {
25
+ /**
26
+ The (optional) on_message callback will be called whenever a websocket message
27
+ is
28
+ received for this connection.
29
+
30
+ The data received points to the websocket's message buffer and it will be
31
+ overwritten once the function exits (it cannot be saved for later, but it can
32
+ be copied).
33
+ */
34
+ void (*on_message)(ws_s* ws, char* data, size_t size, uint8_t is_text);
35
+ /**
36
+ The (optional) on_open callback will be called once the websocket connection
37
+ is
38
+ established.
39
+ */
40
+ void (*on_open)(ws_s* ws);
41
+ /**
42
+ The (optional) on_shutdown callback will be called if a websocket connection
43
+ is still open while the server is shutting down (called before `on_close`).
44
+ */
45
+ void (*on_shutdown)(ws_s* ws);
46
+ /**
47
+ The (optional) on_close callback will be called once a websocket connection is
48
+ terminated or failed to be established.
49
+ */
50
+ void (*on_close)(ws_s* ws);
51
+ /** The `http_request_s` to be converted ("upgraded") to a websocket
52
+ * connection. Either a request or a response object is required.*/
53
+ http_request_s* request;
54
+ /**
55
+ The (optional) HttpResponse to be used for sending the upgrade response.
56
+
57
+ Using this object allows cookies to be set before "upgrading" the connection.
58
+
59
+ The ownership of the response object will remain unchanged - so if you have
60
+ created the response object, you should free it.
61
+ */
62
+ http_response_s* response;
63
+ /**
64
+ The maximum websocket message size/buffer (in bytes) for this connection.
65
+ */
66
+ size_t max_msg_size;
67
+ /** Opaque user data. */
68
+ void* udata;
69
+ /**
70
+ Timeout for the websocket connections, a ping will be sent
71
+ whenever the timeout is reached. Connections are only closed when a ping
72
+ cannot be sent (the network layer fails). Pongs aren't reviewed.
73
+ */
74
+ uint8_t timeout;
75
+ } websocket_settings_s;
76
+
77
+ /** This macro allows easy access to the `websocket_upgrade` function. The macro
78
+ * allows the use of named arguments, using the `websocket_settings_s` struct
79
+ * members. i.e.:
80
+ *
81
+ * on_message(ws_s * ws, char * data, size_t size, int is_text) {
82
+ * ; // ... this is the websocket on_message callback
83
+ * websocket_write(ws, data, size, is_text); // a simple echo example
84
+ * }
85
+ *
86
+ * on_request(http_request_s* request) {
87
+ * websocket_upgrade( .request = request, .on_message = on_message);
88
+ * }
89
+ *
90
+ * Returns 0 on sucess and -1 on failure. A response is always sent.
91
+ */
92
+ ssize_t websocket_upgrade(websocket_settings_s settings);
93
+ #define websocket_upgrade(...) \
94
+ websocket_upgrade((websocket_settings_s){__VA_ARGS__})
95
+
96
+ /** Returns the opaque user data associated with the websocket. */
97
+ void* websocket_get_udata(ws_s* ws);
98
+ /** Returns the the process specific connection's UUID (see `libsock`). */
99
+ intptr_t websocket_get_fduuid(ws_s* ws);
100
+ /** Sets the opaque user data associated with the websocket.
101
+ * Returns the old value, if any. */
102
+ void* websocket_set_udata(ws_s* ws, void* udata);
103
+ /** Writes data to the websocket. Returns -1 on failure (0 on success). */
104
+ int websocket_write(ws_s* ws, void* data, size_t size, uint8_t is_text);
105
+ /** Closes a websocket connection. */
106
+ void websocket_close(ws_s* ws);
107
+ /**
108
+ Performs a task on each websocket connection that shares the same process
109
+ (except the originating `ws_s` connection which is allowed to be NULL).
110
+ */
111
+ void websocket_each(ws_s* ws_originator,
112
+ void (*task)(ws_s* ws_target, void* arg),
113
+ void* arg,
114
+ void (*on_finish)(ws_s* ws_originator, void* arg));
115
+ /**
116
+ Counts the number of websocket connections.
117
+ */
118
+ size_t websocket_count(ws_s* ws);
119
+
120
+ #endif
@@ -0,0 +1,189 @@
1
+ /*
2
+ (un)copyright: Boaz segev, 2016
3
+ License: Public Domain except for any non-public-domain algorithms, which are
4
+ 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 "xor-crypt.h"
12
+ /*****************************************************************************
13
+ Useful Macros
14
+ */
15
+
16
+ /** 32Bit left rotation, inlined. */
17
+ #define left_rotate32(i, bits) \
18
+ (((uint32_t)(i) << (bits)) | ((uint32_t)(i) >> (32 - (bits))))
19
+ /** 32Bit right rotation, inlined. */
20
+ #define right_rotate32(i, bits) \
21
+ (((uint32_t)(i) >> (bits)) | ((uint32_t)(i) << (32 - (bits))))
22
+ /** 64Bit left rotation, inlined. */
23
+ #define left_rotate64(i, bits) \
24
+ (((uint64_t)(i) << (bits)) | ((uint64_t)(i) >> (64 - (bits))))
25
+ /** 64Bit right rotation, inlined. */
26
+ #define right_rotate64(i, bits) \
27
+ (((uint64_t)(i) >> (bits)) | ((uint64_t)(i) << (64 - (bits))))
28
+ /** unknown size element - left rotation, inlined. */
29
+ #define left_rotate(i, bits) (((i) << (bits)) | ((i) >> (sizeof((i)) - (bits))))
30
+ /** unknown size element - right rotation, inlined. */
31
+ #define right_rotate(i, bits) \
32
+ (((i) >> (bits)) | ((i) << (sizeof((i)) - (bits))))
33
+ /** inplace byte swap 16 bit integer */
34
+ #define bswap16(i) \
35
+ do { \
36
+ (i) = (((i)&0xFFU) << 8) | (((i)&0xFF00U) >> 8); \
37
+ } while (0);
38
+ /** inplace byte swap 32 bit integer */
39
+ #define bswap32(i) \
40
+ do { \
41
+ (i) = (((i)&0xFFUL) << 24) | (((i)&0xFF00UL) << 8) | \
42
+ (((i)&0xFF0000UL) >> 8) | (((i)&0xFF000000UL) >> 24); \
43
+ } while (0);
44
+ /** inplace byte swap 64 bit integer */
45
+ #define bswap64(i) \
46
+ do { \
47
+ (i) = (((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \
48
+ (((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \
49
+ (((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \
50
+ (((i)&0xFF000000000000ULL) >> 40) | \
51
+ (((i)&0xFF00000000000000ULL) >> 56); \
52
+ } while (0);
53
+
54
+ #ifdef HAVE_X86Intrin
55
+ #undef bswap64
56
+ #define bswap64(i) \
57
+ { __asm__("bswapq %0" : "+r"(i) :); }
58
+
59
+ // shadow sched_yield as _mm_pause for spinwait
60
+ #define sched_yield() _mm_pause()
61
+ #endif
62
+
63
+ /* ***************************************************************************
64
+ XOR encryption
65
+ */
66
+
67
+ /**
68
+ Uses an XOR key `xor_key_s` to encrypt / decrypt the data provided.
69
+
70
+ Encryption/decryption can be destructive (the target and the source can point
71
+ to the same object).
72
+
73
+ The key's `on_cycle` callback option should be utilized to er-calculate the
74
+ key every cycle. Otherwise, XOR encryption should be avoided.
75
+
76
+ A more secure encryption would be easier to implement using seperate
77
+ `xor_key_s` objects for encryption and decription.
78
+
79
+ If `target` is NULL, the source will be used as the target (destructive mode).
80
+
81
+ Returns -1 on error and 0 on success.
82
+ */
83
+ int bscrypt_xor_crypt(xor_key_s *key, void *target, const void *source,
84
+ size_t length) {
85
+ if (!source || !key)
86
+ return -1;
87
+ if (!length)
88
+ return 0;
89
+ if (!target)
90
+ target = (void *)source;
91
+ if (key->on_cycle) {
92
+ /* loop to provide vector initialization when needed. */
93
+ while (key->position >= key->length) {
94
+ if (key->on_cycle(key))
95
+ return -1;
96
+ key->position -= key->length;
97
+ }
98
+ } else if (key->position >= key->length)
99
+ key->position = 0; /* no callback? no need for vector alterations. */
100
+ size_t i = 0;
101
+
102
+ /* start decryption */
103
+ while (length > i) {
104
+ while ((key->length - key->position >= 8) // we have 8 bytes for key.
105
+ && ((i + 8) <= length) // we have 8 bytes for stream.
106
+ && (((uintptr_t)(target + i)) & 7) == 0 // target memory is aligned.
107
+ && (((uintptr_t)(source + i)) & 7) == 0 // source memory is aligned.
108
+ && ((uintptr_t)(key->key + key->position) & 7) == 0 // key aligned.
109
+ ) {
110
+ // fprintf(stderr, "XOR optimization used i= %lu, key pos = %lu.\n", i,
111
+ // key->position);
112
+ *((uint64_t *)(target + i)) = *((uint64_t *)(source + i)) ^
113
+ *((uint64_t *)(key->key + key->position));
114
+ key->position += 8;
115
+ i += 8;
116
+ if (key->position < key->length)
117
+ continue;
118
+ if (key->on_cycle && key->on_cycle(key))
119
+ return -1;
120
+ key->position = 0;
121
+ }
122
+
123
+ if (i < length) {
124
+ // fprintf(stderr, "XOR single byte.\n");
125
+ *((uint8_t *)(target + i)) =
126
+ *((uint8_t *)(source + i)) ^ *((uint8_t *)(key->key + key->position));
127
+ ++i;
128
+ ++key->position;
129
+ if (key->position == key->length) {
130
+ if (key->on_cycle && key->on_cycle(key))
131
+ return -1;
132
+ key->position = 0;
133
+ }
134
+ }
135
+ }
136
+ return 0;
137
+ }
138
+
139
+ /**
140
+ Similar to the bscrypt_xor_crypt except with a fixed key size of 128bits.
141
+ */
142
+ int bscrypt_xor128_crypt(uint64_t *key, void *target, const void *source,
143
+ size_t length, int (*on_cycle)(uint64_t *key)) {
144
+ length = length & 31;
145
+ uint8_t pos = 0;
146
+ for (size_t i = 0; i < (length >> 3); i++) {
147
+ ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[pos++];
148
+ target += 8;
149
+ source += 8;
150
+ if (pos < 2)
151
+ continue;
152
+ if (on_cycle && on_cycle(key))
153
+ return -1;
154
+ pos = 0;
155
+ }
156
+ length = length & 7;
157
+ for (size_t i = 0; i < length; i++) {
158
+ ((uint64_t *)target)[i] = ((uint64_t *)source)[i] ^ key[pos];
159
+ }
160
+ return 0;
161
+ }
162
+ /**
163
+ Similar to the bscrypt_xor_crypt except with a fixed key size of 256bits.
164
+ */
165
+ int bscrypt_xor256_crypt(uint64_t *key, void *target, const void *source,
166
+ size_t length, int (*on_cycle)(uint64_t *key)) {
167
+ for (size_t i = 0; i < (length >> 5); i++) {
168
+ ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[0];
169
+ ((uint64_t *)target)[1] = ((uint64_t *)source)[1] ^ key[1];
170
+ ((uint64_t *)target)[2] = ((uint64_t *)source)[2] ^ key[2];
171
+ ((uint64_t *)target)[3] = ((uint64_t *)source)[3] ^ key[3];
172
+ target += 32;
173
+ source += 32;
174
+ if (on_cycle && on_cycle(key))
175
+ return -1;
176
+ }
177
+ length = length & 31;
178
+ uint8_t pos = 0;
179
+ for (size_t i = 0; i < (length >> 3); i++) {
180
+ ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[pos++];
181
+ target += 8;
182
+ source += 8;
183
+ }
184
+ length = length & 7;
185
+ for (size_t i = 0; i < length; i++) {
186
+ ((uint64_t *)target)[i] = ((uint64_t *)source)[i] ^ key[pos];
187
+ }
188
+ return 0;
189
+ }
@@ -0,0 +1,107 @@
1
+ /*
2
+ (un)copyright: Boaz segev, 2016
3
+ License: Public Domain except for any non-public-domain algorithms, which are
4
+ subject to their own licenses.
5
+
6
+ Feel free to copy, use and enjoy in accordance with to the license(s).
7
+ */
8
+ #ifndef bscrypt_XOR_CRYPT_H
9
+ #define bscrypt_XOR_CRYPT_H
10
+ #include "bscrypt-common.h"
11
+ /* *****************************************************************************
12
+ C++ extern
13
+ */
14
+ #if defined(__cplusplus)
15
+ extern "C" {
16
+ #endif
17
+
18
+ /* ***************************************************************************
19
+ XOR encryption
20
+ */
21
+
22
+ typedef struct xor_key_s xor_key_s;
23
+ /**
24
+ The `xor_key_s` type is a struct containing XOR key data. This will be used for
25
+ all the encryption/decription functions that use XOR key data, such as the
26
+ `bscrypt_xor_crypt` function.
27
+ */
28
+ struct xor_key_s {
29
+ /** A pointer to a string containing the key. */
30
+ uint8_t *key;
31
+ /** The length of the key string */
32
+ size_t length;
33
+ /**
34
+ The vector / position from which to start the next encryption/decryption.
35
+
36
+ This value is automatically advanced when encrypting / decrypting data.
37
+ */
38
+ size_t position;
39
+ /**
40
+ An optional callback to be called whenever the XOR key finished a cycle and
41
+ the `position` is being reset to 0.
42
+
43
+ The function should return 0 on sucess and -1 on failure. Failue will cause
44
+ endryption/decryption to fail.
45
+ */
46
+ int (*on_cycle)(xor_key_s *key);
47
+ };
48
+
49
+ typedef struct xor_key_128bit_s xor_key_128bit_s;
50
+ /**
51
+ The `xor_key_128bit_s` type is a struct containing an XOR key data. This will be
52
+ used
53
+ for
54
+ all the encryption/decription functions that use XOR key data, such as the
55
+ `bscrypt.xor_crypt` function.
56
+ */
57
+ struct xor_key_128bit_s {
58
+ /** A pointer to a string containing the key. */
59
+ uint64_t key[2];
60
+ /**
61
+ An optional callback to be called whenever the XOR key finished a cycle and
62
+ the `position` is being reset to 0.
63
+
64
+ The function should return 0 on sucess and -1 on failure. Failue will cause
65
+ endryption/decryption to fail.
66
+ */
67
+ int (*on_cycle)(xor_key_128bit_s *key);
68
+ };
69
+
70
+ /**
71
+ Uses an XOR key `xor_key_s` to encrypt / decrypt the data provided.
72
+
73
+ Encryption/decryption can be destructive (the target and the source can point
74
+ to the same object).
75
+
76
+ The key's `on_cycle` callback option should be utilized to re-calculate the
77
+ key every cycle. Otherwise, XOR encryption should be avoided.
78
+
79
+ A more secure encryption would be easier to implement using seperate
80
+ `xor_key_s` objects for encryption and decription.
81
+
82
+ If `target` is NULL, the source will be used as the target (destructive mode).
83
+
84
+ Returns -1 on error and 0 on success.
85
+ */
86
+ int bscrypt_xor_crypt(xor_key_s *key, void *target, const void *source,
87
+ size_t length);
88
+
89
+ /**
90
+ Similar to the bscrypt_xor_crypt except with a fixed key size of 128bits.
91
+ */
92
+ int bscrypt_xor128_crypt(uint64_t *key, void *target, const void *source,
93
+ size_t length, int (*on_cycle)(uint64_t *key));
94
+ /**
95
+ Similar to the bscrypt_xor_crypt except with a fixed key size of 256bits.
96
+ */
97
+ int bscrypt_xor256_crypt(uint64_t *key, void *target, const void *source,
98
+ size_t length, int (*on_cycle)(uint64_t *key));
99
+
100
+ /* *****************************************************************************
101
+ C++ extern finish
102
+ */
103
+ #if defined(__cplusplus)
104
+ }
105
+ #endif
106
+
107
+ #endif
data/iodine.gemspec CHANGED
@@ -4,38 +4,45 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'iodine/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "iodine"
7
+ spec.name = 'iodine'
8
8
  spec.version = Iodine::VERSION
9
- spec.authors = ["Boaz Segev"]
10
- spec.email = ["Boaz@2be.co.il"]
9
+ spec.authors = ['Boaz Segev']
10
+ spec.email = ['Boaz@2be.co.il']
11
11
 
12
- spec.summary = %q{ The Iodine v.0.1.X line and API is deprecated and will not be supported after v. 0.2.0 is released. }
13
- spec.description = %q{ The Iodine v.0.1.X line and API is deprecated and will not be supported after v. 0.2.0 is released. }
14
- spec.homepage = "https://github.com/boazsegev/iodine"
15
- spec.license = "MIT"
12
+ spec.summary = ' Iodine - writing C servers in Ruby.'
13
+ spec.description = ' Iodine - writing C servers in Ruby.'
14
+ spec.homepage = 'https://github.com/boazsegev/iodine'
15
+ spec.license = 'MIT'
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
18
  # delete this section to allow pushing this gem to any host.
19
19
  if spec.respond_to?(:metadata)
20
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
21
  else
22
- raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
23
  end
24
24
 
25
25
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
- spec.bindir = "exe"
26
+ spec.bindir = 'exe'
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
28
+ spec.require_paths = %w(lib ext)
29
29
 
30
- spec.add_development_dependency "bundler", "~> 1.10"
31
- spec.add_development_dependency "rake", "~> 10.0"
32
- spec.add_development_dependency "minitest"
30
+ spec.extensions = %w(ext/iodine/extconf.rb)
33
31
 
32
+ spec.required_ruby_version = '>= 2.2.2' # for Rack
34
33
 
34
+ spec.add_dependency 'rack'
35
+ spec.add_dependency 'rake-compiler'
35
36
 
36
- spec.post_install_message = "The Iodine 0.1.x API is now deprecated.\n"+
37
- "Version 0.2.x will include a drastic change and it WILL break existing code.\n" +
38
- "DON'T UPGRADE BEYOND THIS POINT UNLESS YOU'RE PREPARED FOR A HUGE CANGE.\n" +
39
- "Future version of Iodine will be written in C and require a Linux/Unix machine."
37
+ spec.requirements << 'A Unix based system, i.e.: Linux / OS X / BSD.'
38
+ spec.requirements << 'An updated C compiler, with support for C11 (i.e. gcc 4.9 or later).'
39
+ spec.requirements << 'Ruby >= 2.2.2'
40
40
 
41
+ spec.add_development_dependency 'bundler', '~> 1.10'
42
+ spec.add_development_dependency 'rake', '~> 10.0'
43
+ spec.add_development_dependency 'minitest'
44
+
45
+ spec.post_install_message = "** WARNING!\n" \
46
+ "Iodine 0.2.0 is NOT an upgrade - it's a total rewrite, it's written in C specifically for Ruby MRI.\n\n" \
47
+ 'If your application was using Iodine 0.1.x, it might not work after this "upgrade".'
41
48
  end