oversip 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|