oversip 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS.txt +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +55 -0
- data/bin/oversip +182 -0
- data/ext/common/c_util.h +74 -0
- data/ext/common/ruby_c_util.h +88 -0
- data/ext/sip_parser/common_headers.h +209 -0
- data/ext/sip_parser/ext_help.h +18 -0
- data/ext/sip_parser/extconf.rb +3 -0
- data/ext/sip_parser/sip_parser.c +29649 -0
- data/ext/sip_parser/sip_parser.h +227 -0
- data/ext/sip_parser/sip_parser_ruby.c +1292 -0
- data/ext/stud/extconf.rb +27 -0
- data/ext/stud/stud.tar.gz +0 -0
- data/ext/stun/ext_help.h +16 -0
- data/ext/stun/extconf.rb +3 -0
- data/ext/stun/stun_ruby.c +391 -0
- data/ext/utils/ext_help.h +14 -0
- data/ext/utils/extconf.rb +3 -0
- data/ext/utils/haproxy_protocol.c +6163 -0
- data/ext/utils/haproxy_protocol.h +27 -0
- data/ext/utils/ip_utils.c +5952 -0
- data/ext/utils/ip_utils.h +61 -0
- data/ext/utils/outbound_utils.c +3227 -0
- data/ext/utils/outbound_utils.h +27 -0
- data/ext/utils/utils_ruby.c +384 -0
- data/ext/utils/utils_ruby.h +75 -0
- data/ext/websocket_framing_utils/ext_help.h +18 -0
- data/ext/websocket_framing_utils/extconf.rb +3 -0
- data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
- data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
- data/ext/websocket_http_parser/ext_help.h +18 -0
- data/ext/websocket_http_parser/extconf.rb +3 -0
- data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
- data/ext/websocket_http_parser/ws_http_parser.h +86 -0
- data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
- data/lib/oversip/config.rb +541 -0
- data/lib/oversip/config_validators.rb +126 -0
- data/lib/oversip/errors.rb +7 -0
- data/lib/oversip/fiber_pool.rb +56 -0
- data/lib/oversip/launcher.rb +507 -0
- data/lib/oversip/logger.rb +170 -0
- data/lib/oversip/master_process.rb +67 -0
- data/lib/oversip/posix_mq.rb +121 -0
- data/lib/oversip/proxies_config.rb +169 -0
- data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
- data/lib/oversip/sip/client_transaction.rb +587 -0
- data/lib/oversip/sip/constants.rb +87 -0
- data/lib/oversip/sip/grammar/name_addr.rb +27 -0
- data/lib/oversip/sip/grammar/uri.rb +116 -0
- data/lib/oversip/sip/launcher.rb +180 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/reactor.rb +39 -0
- data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
- data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
- data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
- data/lib/oversip/sip/listeners/tls_client.rb +117 -0
- data/lib/oversip/sip/listeners/tls_server.rb +70 -0
- data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
- data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
- data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
- data/lib/oversip/sip/listeners.rb +28 -0
- data/lib/oversip/sip/logic.rb +14 -0
- data/lib/oversip/sip/message.rb +168 -0
- data/lib/oversip/sip/message_processor.rb +202 -0
- data/lib/oversip/sip/modules/core.rb +200 -0
- data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
- data/lib/oversip/sip/modules/user_assertion.rb +123 -0
- data/lib/oversip/sip/proxy.rb +460 -0
- data/lib/oversip/sip/request.rb +128 -0
- data/lib/oversip/sip/response.rb +30 -0
- data/lib/oversip/sip/rfc3263.rb +646 -0
- data/lib/oversip/sip/server_transaction.rb +295 -0
- data/lib/oversip/sip/sip.rb +74 -0
- data/lib/oversip/sip/tags.rb +39 -0
- data/lib/oversip/sip/timers.rb +55 -0
- data/lib/oversip/sip/transport_manager.rb +129 -0
- data/lib/oversip/syslogger_process.rb +119 -0
- data/lib/oversip/tls.rb +179 -0
- data/lib/oversip/utils.rb +25 -0
- data/lib/oversip/version.rb +23 -0
- data/lib/oversip/websocket/constants.rb +56 -0
- data/lib/oversip/websocket/default_policy.rb +19 -0
- data/lib/oversip/websocket/http_request.rb +63 -0
- data/lib/oversip/websocket/launcher.rb +207 -0
- data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
- data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
- data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
- data/lib/oversip/websocket/listeners.rb +12 -0
- data/lib/oversip/websocket/ws_app.rb +75 -0
- data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
- data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
- data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
- data/lib/oversip/websocket/ws_apps.rb +9 -0
- data/lib/oversip/websocket/ws_framing.rb +597 -0
- data/lib/oversip.rb +59 -0
- data/test/oversip_test_helper.rb +20 -0
- data/test/test_http_parser.rb +73 -0
- data/test/test_sip_parser.rb +139 -0
- metadata +256 -0
data/ext/stud/extconf.rb
ADDED
@@ -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
|
data/ext/stun/ext_help.h
ADDED
@@ -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
|
+
|
data/ext/stun/extconf.rb
ADDED
@@ -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
|
+
|