oversip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/AUTHORS.txt +11 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +16 -0
  4. data/Rakefile +55 -0
  5. data/bin/oversip +182 -0
  6. data/ext/common/c_util.h +74 -0
  7. data/ext/common/ruby_c_util.h +88 -0
  8. data/ext/sip_parser/common_headers.h +209 -0
  9. data/ext/sip_parser/ext_help.h +18 -0
  10. data/ext/sip_parser/extconf.rb +3 -0
  11. data/ext/sip_parser/sip_parser.c +29649 -0
  12. data/ext/sip_parser/sip_parser.h +227 -0
  13. data/ext/sip_parser/sip_parser_ruby.c +1292 -0
  14. data/ext/stud/extconf.rb +27 -0
  15. data/ext/stud/stud.tar.gz +0 -0
  16. data/ext/stun/ext_help.h +16 -0
  17. data/ext/stun/extconf.rb +3 -0
  18. data/ext/stun/stun_ruby.c +391 -0
  19. data/ext/utils/ext_help.h +14 -0
  20. data/ext/utils/extconf.rb +3 -0
  21. data/ext/utils/haproxy_protocol.c +6163 -0
  22. data/ext/utils/haproxy_protocol.h +27 -0
  23. data/ext/utils/ip_utils.c +5952 -0
  24. data/ext/utils/ip_utils.h +61 -0
  25. data/ext/utils/outbound_utils.c +3227 -0
  26. data/ext/utils/outbound_utils.h +27 -0
  27. data/ext/utils/utils_ruby.c +384 -0
  28. data/ext/utils/utils_ruby.h +75 -0
  29. data/ext/websocket_framing_utils/ext_help.h +18 -0
  30. data/ext/websocket_framing_utils/extconf.rb +3 -0
  31. data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
  32. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  33. data/ext/websocket_http_parser/ext_help.h +18 -0
  34. data/ext/websocket_http_parser/extconf.rb +3 -0
  35. data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
  36. data/ext/websocket_http_parser/ws_http_parser.h +86 -0
  37. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  38. data/lib/oversip/config.rb +541 -0
  39. data/lib/oversip/config_validators.rb +126 -0
  40. data/lib/oversip/errors.rb +7 -0
  41. data/lib/oversip/fiber_pool.rb +56 -0
  42. data/lib/oversip/launcher.rb +507 -0
  43. data/lib/oversip/logger.rb +170 -0
  44. data/lib/oversip/master_process.rb +67 -0
  45. data/lib/oversip/posix_mq.rb +121 -0
  46. data/lib/oversip/proxies_config.rb +169 -0
  47. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  48. data/lib/oversip/sip/client_transaction.rb +587 -0
  49. data/lib/oversip/sip/constants.rb +87 -0
  50. data/lib/oversip/sip/grammar/name_addr.rb +27 -0
  51. data/lib/oversip/sip/grammar/uri.rb +116 -0
  52. data/lib/oversip/sip/launcher.rb +180 -0
  53. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  54. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
  55. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  56. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
  57. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
  58. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
  59. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  60. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
  61. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  62. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
  63. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
  64. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
  65. data/lib/oversip/sip/listeners/reactor.rb +39 -0
  66. data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
  67. data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
  68. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  69. data/lib/oversip/sip/listeners/tls_client.rb +117 -0
  70. data/lib/oversip/sip/listeners/tls_server.rb +70 -0
  71. data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
  72. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  73. data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
  74. data/lib/oversip/sip/listeners.rb +28 -0
  75. data/lib/oversip/sip/logic.rb +14 -0
  76. data/lib/oversip/sip/message.rb +168 -0
  77. data/lib/oversip/sip/message_processor.rb +202 -0
  78. data/lib/oversip/sip/modules/core.rb +200 -0
  79. data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
  80. data/lib/oversip/sip/modules/user_assertion.rb +123 -0
  81. data/lib/oversip/sip/proxy.rb +460 -0
  82. data/lib/oversip/sip/request.rb +128 -0
  83. data/lib/oversip/sip/response.rb +30 -0
  84. data/lib/oversip/sip/rfc3263.rb +646 -0
  85. data/lib/oversip/sip/server_transaction.rb +295 -0
  86. data/lib/oversip/sip/sip.rb +74 -0
  87. data/lib/oversip/sip/tags.rb +39 -0
  88. data/lib/oversip/sip/timers.rb +55 -0
  89. data/lib/oversip/sip/transport_manager.rb +129 -0
  90. data/lib/oversip/syslogger_process.rb +119 -0
  91. data/lib/oversip/tls.rb +179 -0
  92. data/lib/oversip/utils.rb +25 -0
  93. data/lib/oversip/version.rb +23 -0
  94. data/lib/oversip/websocket/constants.rb +56 -0
  95. data/lib/oversip/websocket/default_policy.rb +19 -0
  96. data/lib/oversip/websocket/http_request.rb +63 -0
  97. data/lib/oversip/websocket/launcher.rb +207 -0
  98. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
  99. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
  100. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
  101. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
  102. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
  103. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
  104. data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
  105. data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
  106. data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
  107. data/lib/oversip/websocket/listeners.rb +12 -0
  108. data/lib/oversip/websocket/ws_app.rb +75 -0
  109. data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
  110. data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
  111. data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
  112. data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
  113. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
  114. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
  115. data/lib/oversip/websocket/ws_apps.rb +9 -0
  116. data/lib/oversip/websocket/ws_framing.rb +597 -0
  117. data/lib/oversip.rb +59 -0
  118. data/test/oversip_test_helper.rb +20 -0
  119. data/test/test_http_parser.rb +73 -0
  120. data/test/test_sip_parser.rb +139 -0
  121. metadata +256 -0
@@ -0,0 +1,27 @@
1
+ require "mkmf"
2
+ require "fileutils"
3
+
4
+
5
+ def sys(cmd)
6
+ puts "system command: #{cmd}"
7
+ unless ret = xsystem(cmd)
8
+ raise "system command `#{cmd}' failed"
9
+ end
10
+ ret
11
+ end
12
+
13
+
14
+ here = File.expand_path(File.dirname(__FILE__))
15
+ stud_tarball = "#{here}/stud.tar.gz"
16
+
17
+ Dir.chdir(here) do
18
+ sys("tar -zxf #{stud_tarball}")
19
+ Dir.chdir("stud") do
20
+ sys("make")
21
+ FileUtils.mv "stud", "../../../bin/oversip_stud"
22
+ end
23
+
24
+ FileUtils.remove_dir("stud", force = true)
25
+ end
26
+
27
+ create_makefile("stud")
Binary file
@@ -0,0 +1,16 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ /* Uncomment for enabling TRACE() function. */
5
+ /*#define DEBUG*/
6
+
7
+ #ifdef DEBUG
8
+ #define TRACE() fprintf(stderr, "TRACE: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
9
+ #define LOG(string) fprintf(stderr, "LOG: %s:%d:%s: %s\n", __FILE__, __LINE__, __FUNCTION__, string)
10
+ #else
11
+ #define TRACE()
12
+ #define LOG(string)
13
+ #endif
14
+
15
+ #endif
16
+
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("oversip/stun")
@@ -0,0 +1,391 @@
1
+ #include <ruby.h>
2
+ #include <netinet/in.h>
3
+ #include <arpa/inet.h>
4
+ #include "ext_help.h"
5
+
6
+
7
+ #define STUN_MESSAGE_MIN_SIZE 20
8
+ #define STUN_MAGIC_COOKIE_LEN 4
9
+ #define STUN_TRANSACTION_ID_LEN 12
10
+ #define STUN_BINDING_SUCCESS_RESPONSE_IPV4_SIZE 32
11
+ #define STUN_BINDING_SUCCESS_RESPONSE_IPV6_SIZE 44
12
+
13
+
14
+ static VALUE mOverSIP;
15
+ static VALUE mStun;
16
+
17
+
18
+ /*
19
+ * Ruby functions.
20
+ */
21
+
22
+
23
+ /*
24
+ * RFC 5389.
25
+ *
26
+ * 6. STUN Message Structure
27
+ *
28
+ * 0 1 2 3
29
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
30
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
+ * |0 0| STUN Message Type | Message Length |
32
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
+ * | Magic Cookie |
34
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35
+ * | |
36
+ * | Transaction ID (96 bits) |
37
+ * | |
38
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39
+ *
40
+ */
41
+
42
+
43
+ /*
44
+ * Expects 3 arguments:
45
+ * - String containing a STUN Binding Request (MUST not be empty!!).
46
+ * - String containing the source IP of the request.
47
+ * - Fxinum containing the source port of the request.
48
+ * Return value:
49
+ * - If it's a valid STUN Binding Request, returns a Ruby String representing the
50
+ * STUN Binding Response.
51
+ * - If it seems a valid STUN message but not a valid STUN Binding Request, returns _false_.
52
+ * - Otherwise returns _nil_ (so it could be a SIP message).
53
+ */
54
+ VALUE Stun_parse_request(VALUE self, VALUE rb_stun_request, VALUE rb_source_ip, VALUE rb_source_port)
55
+ {
56
+ TRACE();
57
+
58
+ char *request = NULL;
59
+ size_t request_len = 0;
60
+ char *source_ip = NULL;
61
+ short source_ip_is_ipv6 = 0;
62
+ uint16_t source_port;
63
+
64
+ char *transaction_id;
65
+ uint16_t message_length;
66
+ char *magic_cookie;
67
+ short is_rfc3489_client = 0;
68
+
69
+ struct in_addr in_addr_ipv4;
70
+ struct in6_addr in_addr_ipv6;
71
+ uint16_t xor_port;
72
+ uint32_t xor_ipv4;
73
+ unsigned char xor_ipv6[16];
74
+
75
+ /* The size of our STUN Binding Response is the sum of:
76
+ * - STUN message header: 20 bytes.
77
+ * - One attribute (XOR-MAPPED-ADDRESS or MAPPED-ADDRESS).
78
+ * - Type + Length: 4 bytes.
79
+ * - XOR-MAPPED-ADDRESS or MAPPED-ADDRESS for IPv4: 4 + 4 = 8 bytes.
80
+ * - XOR-MAPPED-ADDRESS or MAPPED-ADDRESS for IPv6: 4 + 16 = 20 bytes.
81
+ * - Size for a response with IPv4: 20 + 4 + 8 = 32 bytes.
82
+ * - Size for a response with IPv6: 20 + 4 + 20 = 44 bytes.
83
+ */
84
+ char response[STUN_BINDING_SUCCESS_RESPONSE_IPV6_SIZE];
85
+
86
+ if (TYPE(rb_stun_request) != T_STRING)
87
+ rb_raise(rb_eTypeError, "First argument must be a String containing the STUN Binding Request");
88
+
89
+ request = RSTRING_PTR(rb_stun_request);
90
+
91
+ /* First octet of any STUN *request* must be 0. Return false otherwise. */
92
+ if (request[0]) {
93
+ LOG("first octet is not 0, so it's not a STUN request\n");
94
+ return Qnil;
95
+ }
96
+
97
+ /* Any STUN message must contain, at least, 20 bytes. Return false otherwise. */
98
+ if ((request_len = RSTRING_LEN(rb_stun_request)) < STUN_MESSAGE_MIN_SIZE) {
99
+ LOG("ERROR: request length less than 20 bytes, invalid STUN message\n");
100
+ return Qfalse;
101
+ }
102
+
103
+ if (TYPE(rb_source_ip) != T_STRING)
104
+ rb_raise(rb_eTypeError, "Third argument must be a String containing the source IP");
105
+
106
+ if (TYPE(rb_source_port) != T_FIXNUM)
107
+ rb_raise(rb_eTypeError, "Fourth argument must be a Fixnum containing the source port");
108
+
109
+ /*
110
+ * RFC 5389 section 6.
111
+ *
112
+ * a Binding request has class=0b00 (request) and method=0b000000000001 (Binding)
113
+ * and is encoded into the first 16 bits as 0x0001.
114
+ *
115
+ * So let's check the second byte which must be 0x1.
116
+ */
117
+ if ( request[1] != 0b00000001 ) {
118
+ LOG("ERROR: not a valid STUN Binding Request, maybe an STUN Indication (so ignore it)\n");
119
+ return Qfalse;
120
+ }
121
+
122
+ /*
123
+ * RFC 5389 section 6.
124
+ *
125
+ * The magic cookie field MUST contain the fixed value 0x2112A442 in network byte order.
126
+ *
127
+ * 0x21 = 33, 0x12 = 18, 0xA4 = -92, 0x42=66.
128
+ */
129
+ if (! (request[4] == 33 && request[5] == 18 && request[6] == -92 && request[7] == 66) ) {
130
+ LOG("WARN: STUN magic cookie does not match, using backward compatibility with RFC 3489\n");
131
+
132
+ /*
133
+ * RFC 5389 section 12.2.
134
+ *
135
+ * A STUN server can detect when a given Binding request message was
136
+ * sent from an RFC 3489 [RFC3489] client by the absence of the correct
137
+ * value in the magic cookie field. When the server detects an RFC 3489
138
+ * client, it SHOULD copy the value seen in the magic cookie field in
139
+ * the Binding request to the magic cookie field in the Binding response
140
+ * message, and insert a MAPPED-ADDRESS attribute instead of an
141
+ * XOR-MAPPED-ADDRESS attribute.
142
+ *
143
+ */
144
+ is_rfc3489_client = 1;
145
+ }
146
+
147
+ /* Get the Magic Cookie. */
148
+ magic_cookie = ((char *)request)+4;
149
+
150
+ /* Get the Transaction ID. */
151
+ transaction_id = ((char *)request)+8;
152
+
153
+ /*
154
+ * RFC 5389 section 6.
155
+ * "The message length MUST contain the size, in bytes, of the message
156
+ * not including the 20-byte STUN header. Since all STUN attributes are
157
+ * padded to a multiple of 4 bytes, the last 2 bits of this field are
158
+ * always zero. This provides another way to distinguish STUN packets
159
+ * from packets of other protocols."
160
+ *
161
+ */
162
+ message_length = ntohs(*(uint16_t *)(request+2));
163
+
164
+
165
+
166
+ /*
167
+ * Create the STUN Binding Response.
168
+ */
169
+
170
+ /* A Binding response has class=0b10 (success response) and method=*0b000000000001,
171
+ * and is encoded into the first 16 bits as 0x0101. */
172
+ response[0] = 1;
173
+ response[1] = 1;
174
+
175
+ /* Add the received Magic Cookie (for RFC 3489 backward compatibility). */
176
+ memcpy(response+4, magic_cookie, STUN_MAGIC_COOKIE_LEN);
177
+
178
+ /* Add the received Transaction Id. */
179
+ memcpy(response+8, transaction_id, STUN_TRANSACTION_ID_LEN);
180
+
181
+ /*
182
+ * Add an attribute XOR-MAPPED-ADDRESS (or MAPPED-ADDRESS if it's a RFC 3489 client).
183
+ */
184
+
185
+ /*
186
+ * STUN Attribute.
187
+ *
188
+ * 0 1 2 3
189
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
190
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
191
+ * | Type | Length |
192
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
193
+ * | Value (variable) ....
194
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
195
+ *
196
+ *
197
+ * XOR-MAPPED-ADDRESS.
198
+ *
199
+ * 0 1 2 3
200
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
201
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202
+ * |x x x x x x x x| Family | X-Port |
203
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204
+ * | X-Address (Variable)
205
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206
+ *
207
+ *
208
+ * MAPPED-ADDRESS.
209
+ *
210
+ * 0 1 2 3
211
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
212
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213
+ * |0 0 0 0 0 0 0 0| Family | Port |
214
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215
+ * | |
216
+ * | Address (32 bits or 128 bits) |
217
+ * | |
218
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219
+ *
220
+ */
221
+
222
+ source_ip = StringValueCStr(rb_source_ip);
223
+
224
+ /* Check the IP and its type (IPv4 or IPv6). */
225
+ switch(inet_pton(AF_INET, source_ip, &in_addr_ipv4)) {
226
+ /* It's valid IPv4. */
227
+ case 1:
228
+ break;
229
+ /* Not valid INET family, hummmm. */
230
+ case -1:
231
+ rb_raise(rb_eTypeError, "Family AF_INET (IPv4) not supported");
232
+ break;
233
+ /* Let's check with IPv6. */
234
+ case 0:
235
+ switch(inet_pton(AF_INET6, source_ip, &in_addr_ipv6)) {
236
+ /* It's valid IPv6. */
237
+ case 1:
238
+ source_ip_is_ipv6 = 1;
239
+ break;
240
+ /* Not valid INET family, hummmm. */
241
+ case -1:
242
+ rb_raise(rb_eTypeError, "Family AF_INET6 (IPv6) not supported");
243
+ break;
244
+ /* The string is neither an IPv4 or IPv6. */
245
+ case 0:
246
+ rb_raise(rb_eTypeError, "Given IP string is neither IPv4 or IPv6");
247
+ break;
248
+ }
249
+ }
250
+
251
+ /* Get the port in an integer (two bytes) */
252
+ source_port = (uint16_t)(FIX2INT(rb_source_port));
253
+
254
+ /* It's a RFC 5389 compliant client, so add XOR-MAPPED-ADDRESS. */
255
+ if (! is_rfc3489_client) {
256
+ /* STUN attribute type: 0x0020: XOR-MAPPED-ADDRESS */
257
+ response[20] = 0x00;
258
+ response[21] = 0x20;
259
+
260
+ /*
261
+ * XOR-MAPPED-ADDRESS fields.
262
+ */
263
+
264
+ /* First byte must be 0x00. */
265
+ response[24] = 0x00;
266
+
267
+ /* Second byte is the IP Family (0x01:IPv4, 0x02:IPv6). */
268
+ if (source_ip_is_ipv6)
269
+ response[25] = 0x02;
270
+ else
271
+ response[25] = 0x01;
272
+
273
+ /* Bytes 3 and 4 are the X-Port. X-Port is computed by taking the mapped port in
274
+ * host byte order, XOR'ing it with the most significant 16 bits of the magic cookie,
275
+ * and then the converting the result to network byte order. */
276
+ xor_port = htons(source_port ^ *(uint16_t *)(magic_cookie));
277
+
278
+ memcpy(response+26, &xor_port, 2);
279
+
280
+ /* Next bytes are the IP in network byte order with XOR stuff. */
281
+
282
+ /* IPv4. */
283
+ if (! source_ip_is_ipv6) {
284
+ /* If the IP address family is IPv4, X-Address is computed by taking the mapped IP
285
+ * address in host byte order, XOR'ing it with the magic cookie, and converting the
286
+ * result to network byte order. */
287
+ xor_ipv4 = htons((uint32_t)(in_addr_ipv4.s_addr) ^ *(uint32_t *)(magic_cookie));
288
+
289
+ memcpy(response+28, &xor_ipv4, 4);
290
+ /* So set the attribute Length to 8. */
291
+ response[22] = 0;
292
+ response[23] = 8;
293
+ /* So set the STUN Response Message Length to 12 bytes. */
294
+ response[2] = 0;
295
+ response[3] = 12;
296
+
297
+ /* Return the Ruby string containing the response. */
298
+ return rb_str_new(response, STUN_BINDING_SUCCESS_RESPONSE_IPV4_SIZE);
299
+ }
300
+ /* IPv6. */
301
+ else {
302
+ /* If the IP address family is IPv6, X-Address is computed by taking the
303
+ * mapped IP address in host byte order, XOR'ing it with the concatenation
304
+ * of the magic cookie and the 96-bit transaction ID, and converting the result
305
+ * to network byte order. */
306
+ /* NOTE: struct in_addr.s6_addr is an array of 16 char in network byte order (big-endian). */
307
+ /* TODO: So do I need to convert in_addr_ipv6.s6_addr to host byte order and later the
308
+ * whole result to network byte order? */
309
+ int i;
310
+ for(i=0; i<16; i++)
311
+ xor_ipv6[i] = in_addr_ipv6.s6_addr[i] ^ magic_cookie[i];
312
+
313
+ memcpy(response+28, xor_ipv6, 16);
314
+
315
+ /* So set the attribute Length to 20. */
316
+ response[22] = 0;
317
+ response[23] = 20;
318
+ /* So set the STUN Response Message Length to 24 bytes. */
319
+ response[2] = 0;
320
+ response[3] = 24;
321
+
322
+ /* Return the Ruby string containing the response. */
323
+ return rb_str_new(response, STUN_BINDING_SUCCESS_RESPONSE_IPV6_SIZE);
324
+ }
325
+ }
326
+
327
+ /* It's a RFC 3489 compliant client, so add MAPPED-ADDRESS. */
328
+ else {
329
+ /* STUN attribute type: 0x0001: MAPPED-ADDRESS */
330
+ response[20] = 0x00;
331
+ response[21] = 0x01;
332
+
333
+ /*
334
+ * MAPPED-ADDRESS fields.
335
+ */
336
+
337
+ /* First byte must be 0x00. */
338
+ response[24] = 0x00;
339
+
340
+ /* Second byte is the IP Family (0x01:IPv4, 0x02:IPv6). */
341
+ if (source_ip_is_ipv6)
342
+ response[25] = 0x02;
343
+ else
344
+ response[25] = 0x01;
345
+
346
+ /* Bytes 3 and 4 are the Port in network byte order. */
347
+ source_port = htons(source_port);
348
+ memcpy(response+26, &source_port, 2);
349
+
350
+ /* Next bytes are the IP in network byte order. */
351
+
352
+ /* IPv4. */
353
+ if (! source_ip_is_ipv6) {
354
+ memcpy(response+28, &in_addr_ipv4.s_addr, 4);
355
+ /* So set the attribute Length to 8. */
356
+ response[22] = 0;
357
+ response[23] = 8;
358
+ /* So set the STUN Response Message Length to 12 bytes. */
359
+ response[2] = 0;
360
+ response[3] = 12;
361
+
362
+ /* Return the Ruby string containing the response. */
363
+ return rb_str_new(response, STUN_BINDING_SUCCESS_RESPONSE_IPV4_SIZE);
364
+ }
365
+ /* IPv6. */
366
+ else {
367
+ memcpy(response+28, &in_addr_ipv6.s6_addr, 16);
368
+ /* So set the attribute Length to 20. */
369
+ response[22] = 0;
370
+ response[23] = 20;
371
+ /* So set the STUN Response Message Length to 24 bytes. */
372
+ response[2] = 0;
373
+ response[3] = 24;
374
+
375
+ /* Return the Ruby string containing the response. */
376
+ return rb_str_new(response, STUN_BINDING_SUCCESS_RESPONSE_IPV6_SIZE);
377
+ }
378
+ }
379
+
380
+ }
381
+
382
+
383
+ void Init_stun()
384
+ {
385
+ TRACE();
386
+
387
+ mOverSIP = rb_define_module("OverSIP");
388
+ mStun = rb_define_module_under(mOverSIP, "Stun");
389
+
390
+ rb_define_module_function(mStun, "parse_request", Stun_parse_request, 3);
391
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ /* Uncomment for enabling TRACE() function. */
5
+ /*#define DEBUG*/
6
+
7
+ #ifdef DEBUG
8
+ #define TRACE() fprintf(stderr, "TRACE: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
9
+ #else
10
+ #define TRACE()
11
+ #endif
12
+
13
+ #endif
14
+
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("oversip/utils")