sctp-socket 0.1.0 → 0.1.2
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ruby.yml +37 -0
- data/CHANGES.md +16 -0
- data/README.md +16 -6
- data/Rakefile +11 -0
- data/ext/sctp/extconf.rb +20 -3
- data/ext/sctp/socket.c +941 -254
- data/sctp-socket.gemspec +3 -2
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
data/ext/sctp/socket.c
CHANGED
@@ -4,6 +4,10 @@
|
|
4
4
|
#include <arpa/inet.h>
|
5
5
|
#include <netinet/sctp.h>
|
6
6
|
|
7
|
+
#ifdef HAVE_SYS_PARAM_H
|
8
|
+
#include <sys/param.h>
|
9
|
+
#endif
|
10
|
+
|
7
11
|
VALUE mSCTP;
|
8
12
|
VALUE cSocket;
|
9
13
|
VALUE v_sndrcv_struct;
|
@@ -25,6 +29,7 @@ VALUE v_sctp_event_subscribe_struct;
|
|
25
29
|
VALUE v_sctp_receive_info_struct;
|
26
30
|
VALUE v_sctp_peer_addr_params_struct;
|
27
31
|
VALUE v_sender_dry_event_struct;
|
32
|
+
VALUE v_sctp_initmsg_struct;
|
28
33
|
|
29
34
|
#if !defined(IOV_MAX)
|
30
35
|
#if defined(_SC_IOV_MAX)
|
@@ -63,7 +68,226 @@ VALUE rb_hash_aref2(VALUE v_hash, const char* key){
|
|
63
68
|
return v_val;
|
64
69
|
}
|
65
70
|
|
71
|
+
VALUE get_notification_info(char* buffer){
|
72
|
+
uint32_t i;
|
73
|
+
char str[16];
|
74
|
+
union sctp_notification* snp;
|
75
|
+
VALUE v_notification = Qnil;
|
76
|
+
VALUE v_str = Qnil;
|
77
|
+
VALUE* v_temp;
|
78
|
+
|
79
|
+
snp = (union sctp_notification*)buffer;
|
80
|
+
|
81
|
+
switch(snp->sn_header.sn_type){
|
82
|
+
case SCTP_ASSOC_CHANGE:
|
83
|
+
switch(snp->sn_assoc_change.sac_state){
|
84
|
+
case SCTP_COMM_LOST:
|
85
|
+
v_str = rb_str_new2("comm lost");
|
86
|
+
break;
|
87
|
+
case SCTP_COMM_UP:
|
88
|
+
v_str = rb_str_new2("comm up");
|
89
|
+
break;
|
90
|
+
case SCTP_RESTART:
|
91
|
+
v_str = rb_str_new2("restart");
|
92
|
+
break;
|
93
|
+
case SCTP_SHUTDOWN_COMP:
|
94
|
+
v_str = rb_str_new2("shutdown complete");
|
95
|
+
break;
|
96
|
+
case SCTP_CANT_STR_ASSOC:
|
97
|
+
v_str = rb_str_new2("association setup failed");
|
98
|
+
break;
|
99
|
+
default:
|
100
|
+
v_str = rb_str_new2("unknown");
|
101
|
+
}
|
102
|
+
|
103
|
+
v_notification = rb_struct_new(v_assoc_change_struct,
|
104
|
+
UINT2NUM(snp->sn_assoc_change.sac_type),
|
105
|
+
UINT2NUM(snp->sn_assoc_change.sac_length),
|
106
|
+
UINT2NUM(snp->sn_assoc_change.sac_state),
|
107
|
+
UINT2NUM(snp->sn_assoc_change.sac_error),
|
108
|
+
UINT2NUM(snp->sn_assoc_change.sac_outbound_streams),
|
109
|
+
UINT2NUM(snp->sn_assoc_change.sac_inbound_streams),
|
110
|
+
UINT2NUM(snp->sn_assoc_change.sac_assoc_id),
|
111
|
+
v_str
|
112
|
+
);
|
113
|
+
break;
|
114
|
+
case SCTP_PEER_ADDR_CHANGE:
|
115
|
+
switch(snp->sn_paddr_change.spc_state){
|
116
|
+
case SCTP_ADDR_AVAILABLE:
|
117
|
+
v_str = rb_str_new2("available");
|
118
|
+
break;
|
119
|
+
case SCTP_ADDR_UNREACHABLE:
|
120
|
+
v_str = rb_str_new2("unreachable");
|
121
|
+
break;
|
122
|
+
case SCTP_ADDR_REMOVED:
|
123
|
+
v_str = rb_str_new2("removed from association");
|
124
|
+
break;
|
125
|
+
case SCTP_ADDR_ADDED:
|
126
|
+
v_str = rb_str_new2("added to association");
|
127
|
+
break;
|
128
|
+
case SCTP_ADDR_MADE_PRIM:
|
129
|
+
v_str = rb_str_new2("primary destination");
|
130
|
+
break;
|
131
|
+
default:
|
132
|
+
v_str = rb_str_new2("unknown");
|
133
|
+
}
|
134
|
+
|
135
|
+
inet_ntop(
|
136
|
+
((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
|
137
|
+
&(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
|
138
|
+
str,
|
139
|
+
sizeof(str)
|
140
|
+
);
|
141
|
+
|
142
|
+
v_notification = rb_struct_new(v_peeraddr_change_struct,
|
143
|
+
UINT2NUM(snp->sn_paddr_change.spc_type),
|
144
|
+
UINT2NUM(snp->sn_paddr_change.spc_length),
|
145
|
+
rb_str_new2(str),
|
146
|
+
UINT2NUM(snp->sn_paddr_change.spc_state),
|
147
|
+
UINT2NUM(snp->sn_paddr_change.spc_error),
|
148
|
+
UINT2NUM(snp->sn_paddr_change.spc_assoc_id),
|
149
|
+
v_str
|
150
|
+
);
|
151
|
+
break;
|
152
|
+
case SCTP_REMOTE_ERROR:
|
153
|
+
v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
|
154
|
+
|
155
|
+
for(i = 0; i < snp->sn_remote_error.sre_length; i++){
|
156
|
+
v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
|
157
|
+
}
|
158
|
+
|
159
|
+
v_notification = rb_struct_new(v_remote_error_struct,
|
160
|
+
UINT2NUM(snp->sn_remote_error.sre_type),
|
161
|
+
UINT2NUM(snp->sn_remote_error.sre_flags),
|
162
|
+
UINT2NUM(snp->sn_remote_error.sre_length),
|
163
|
+
UINT2NUM(snp->sn_remote_error.sre_error),
|
164
|
+
UINT2NUM(snp->sn_remote_error.sre_assoc_id),
|
165
|
+
rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
|
166
|
+
);
|
167
|
+
break;
|
168
|
+
#ifdef SCTP_SEND_FAILED_EVENT
|
169
|
+
case SCTP_SEND_FAILED_EVENT:
|
170
|
+
#ifdef HAVE_STRUCT_SCTP_SEND_FAILED_EVENT_SSFE_LENGTH
|
171
|
+
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssfe_length);
|
172
|
+
|
173
|
+
for(i = 0; i < snp->sn_send_failed_event.ssfe_length; i++){
|
174
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssfe_data[i]);
|
175
|
+
}
|
176
|
+
|
177
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
178
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_type),
|
179
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_length),
|
180
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_error),
|
181
|
+
rb_struct_new(v_sndinfo_struct,
|
182
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
183
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
184
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
185
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
186
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
187
|
+
),
|
188
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_assoc_id),
|
189
|
+
rb_ary_new4(snp->sn_send_failed_event.ssfe_length, v_temp)
|
190
|
+
);
|
191
|
+
#else
|
192
|
+
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
|
193
|
+
|
194
|
+
for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
|
195
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
|
196
|
+
}
|
197
|
+
|
198
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
199
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_type),
|
200
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_length),
|
201
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_error),
|
202
|
+
rb_struct_new(v_sndinfo_struct,
|
203
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
204
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
205
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
206
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
207
|
+
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
208
|
+
),
|
209
|
+
UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
|
210
|
+
rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
|
211
|
+
);
|
212
|
+
#endif
|
213
|
+
break;
|
214
|
+
#else
|
215
|
+
case SCTP_SEND_FAILED:
|
216
|
+
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
|
217
|
+
|
218
|
+
for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
|
219
|
+
v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
|
220
|
+
}
|
221
|
+
|
222
|
+
v_notification = rb_struct_new(v_send_failed_event_struct,
|
223
|
+
UINT2NUM(snp->sn_send_failed.ssf_type),
|
224
|
+
UINT2NUM(snp->sn_send_failed.ssf_length),
|
225
|
+
UINT2NUM(snp->sn_send_failed.ssf_error),
|
226
|
+
Qnil,
|
227
|
+
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
228
|
+
rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
|
229
|
+
);
|
230
|
+
break;
|
231
|
+
#endif
|
232
|
+
case SCTP_SHUTDOWN_EVENT:
|
233
|
+
v_notification = rb_struct_new(v_shutdown_event_struct,
|
234
|
+
UINT2NUM(snp->sn_shutdown_event.sse_type),
|
235
|
+
UINT2NUM(snp->sn_shutdown_event.sse_length),
|
236
|
+
UINT2NUM(snp->sn_shutdown_event.sse_assoc_id)
|
237
|
+
);
|
238
|
+
break;
|
239
|
+
case SCTP_ADAPTATION_INDICATION:
|
240
|
+
v_notification = rb_struct_new(v_adaptation_event_struct,
|
241
|
+
UINT2NUM(snp->sn_adaptation_event.sai_type),
|
242
|
+
UINT2NUM(snp->sn_adaptation_event.sai_length),
|
243
|
+
UINT2NUM(snp->sn_adaptation_event.sai_adaptation_ind),
|
244
|
+
UINT2NUM(snp->sn_adaptation_event.sai_assoc_id)
|
245
|
+
);
|
246
|
+
break;
|
247
|
+
case SCTP_PARTIAL_DELIVERY_EVENT:
|
248
|
+
v_notification = rb_struct_new(v_partial_delivery_event_struct,
|
249
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_type),
|
250
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_length),
|
251
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_indication),
|
252
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_stream),
|
253
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_seq),
|
254
|
+
UINT2NUM(snp->sn_pdapi_event.pdapi_assoc_id)
|
255
|
+
);
|
256
|
+
break;
|
257
|
+
case SCTP_AUTHENTICATION_EVENT:
|
258
|
+
v_notification = rb_struct_new(v_auth_event_struct,
|
259
|
+
#ifdef HAVE_UNION_SCTP_NOTIFICATION_SN_AUTH_EVENT
|
260
|
+
UINT2NUM(snp->sn_auth_event.auth_type),
|
261
|
+
UINT2NUM(snp->sn_auth_event.auth_length),
|
262
|
+
UINT2NUM(snp->sn_auth_event.auth_keynumber),
|
263
|
+
UINT2NUM(snp->sn_auth_event.auth_indication),
|
264
|
+
UINT2NUM(snp->sn_auth_event.auth_assoc_id)
|
265
|
+
#else
|
266
|
+
UINT2NUM(snp->sn_authkey_event.auth_type),
|
267
|
+
UINT2NUM(snp->sn_authkey_event.auth_length),
|
268
|
+
UINT2NUM(snp->sn_authkey_event.auth_keynumber),
|
269
|
+
UINT2NUM(snp->sn_authkey_event.auth_indication),
|
270
|
+
UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
|
271
|
+
#endif
|
272
|
+
);
|
273
|
+
break;
|
274
|
+
case SCTP_SENDER_DRY_EVENT:
|
275
|
+
v_notification = rb_struct_new(v_sender_dry_event_struct,
|
276
|
+
UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
|
277
|
+
UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
|
278
|
+
UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
|
279
|
+
UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
|
280
|
+
);
|
281
|
+
break;
|
282
|
+
}
|
283
|
+
|
284
|
+
return v_notification;
|
285
|
+
}
|
286
|
+
|
66
287
|
/*
|
288
|
+
* call-seq:
|
289
|
+
* SCTP::Socket.new(domain = Socket::AF_INET, type = Socket::SOCK_STREAM)
|
290
|
+
*
|
67
291
|
* Create and return a new SCTP::Socket instance. You may optionally pass in
|
68
292
|
* a domain (aka family) value and socket type. By default these are AF_INET
|
69
293
|
* and SOCK_SEQPACKET, respectively.
|
@@ -106,27 +330,30 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
106
330
|
}
|
107
331
|
|
108
332
|
/*
|
109
|
-
*
|
110
|
-
*
|
333
|
+
* call-seq:
|
334
|
+
* SCTP::Socket#bindx(options)
|
111
335
|
*
|
112
|
-
*
|
113
|
-
*
|
114
|
-
* respectively.
|
336
|
+
* Bind a subset of IP addresses associated with the host system on the
|
337
|
+
* given port, or a port assigned by the operating system if none is provided.
|
115
338
|
*
|
116
|
-
*
|
339
|
+
* Note that you can both add or remove an address to or from the socket
|
340
|
+
* using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
|
341
|
+
* respectively.
|
117
342
|
*
|
118
|
-
*
|
343
|
+
* Example:
|
119
344
|
*
|
120
|
-
*
|
121
|
-
* socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
|
345
|
+
* socket = SCTP::Socket.new
|
122
346
|
*
|
123
|
-
*
|
124
|
-
*
|
347
|
+
* # Bind 2 addresses
|
348
|
+
* socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
|
125
349
|
*
|
126
|
-
*
|
127
|
-
*
|
350
|
+
* # Remove 1 later
|
351
|
+
* socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
|
128
352
|
*
|
129
|
-
*
|
353
|
+
* If no addresses are specified, then it will bind to all available interfaces. If
|
354
|
+
* no port is specified, then one will be assigned by the host.
|
355
|
+
*
|
356
|
+
* Returns the port that it was bound to.
|
130
357
|
*/
|
131
358
|
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
132
359
|
struct sockaddr_in addrs[8];
|
@@ -157,7 +384,7 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
157
384
|
if(NIL_P(v_addresses))
|
158
385
|
num_ip = 1;
|
159
386
|
else
|
160
|
-
num_ip = RARRAY_LEN(v_addresses);
|
387
|
+
num_ip = (int)RARRAY_LEN(v_addresses);
|
161
388
|
|
162
389
|
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
163
390
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
@@ -168,12 +395,18 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
168
395
|
addrs[i].sin_family = domain;
|
169
396
|
addrs[i].sin_port = htons(port);
|
170
397
|
addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
398
|
+
#ifdef BSD
|
399
|
+
addrs[i].sin_len = sizeof(struct sockaddr_in);
|
400
|
+
#endif
|
171
401
|
}
|
172
402
|
}
|
173
403
|
else{
|
174
404
|
addrs[0].sin_family = domain;
|
175
405
|
addrs[0].sin_port = htons(port);
|
176
406
|
addrs[0].sin_addr.s_addr = htonl(INADDR_ANY);
|
407
|
+
#ifdef BSD
|
408
|
+
addrs[0].sin_len = sizeof(struct sockaddr_in);
|
409
|
+
#endif
|
177
410
|
}
|
178
411
|
|
179
412
|
if(sctp_bindx(fileno, (struct sockaddr *) addrs, num_ip, flags) != 0)
|
@@ -196,6 +429,9 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
196
429
|
}
|
197
430
|
|
198
431
|
/*
|
432
|
+
* call-seq:
|
433
|
+
* SCTP::Socket#connectx(options)
|
434
|
+
*
|
199
435
|
* Connect the socket to a multihomed peer via the provided array of addresses
|
200
436
|
* using the domain specified in the constructor. You must also specify the port.
|
201
437
|
*
|
@@ -204,7 +440,9 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
204
440
|
* socket = SCTP::Socket.new
|
205
441
|
* socket.connectx(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
|
206
442
|
*
|
207
|
-
* Note that this will also set/update the object's association_id.
|
443
|
+
* Note that this will also set/update the object's association_id. Also note that
|
444
|
+
* this method is not strictly necessary on the client side, since the various send
|
445
|
+
* methods will automatically establish associations.
|
208
446
|
*/
|
209
447
|
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
210
448
|
struct sockaddr_in addrs[8];
|
@@ -230,7 +468,7 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
230
468
|
|
231
469
|
v_domain = rb_iv_get(self, "@domain");
|
232
470
|
|
233
|
-
num_ip = RARRAY_LEN(v_addresses);
|
471
|
+
num_ip = (int)RARRAY_LEN(v_addresses);
|
234
472
|
bzero(&addrs, sizeof(addrs));
|
235
473
|
|
236
474
|
for(i = 0; i < num_ip; i++){
|
@@ -238,6 +476,9 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
238
476
|
addrs[i].sin_family = NUM2INT(v_domain);
|
239
477
|
addrs[i].sin_port = htons(NUM2INT(v_port));
|
240
478
|
addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
479
|
+
#ifdef BSD
|
480
|
+
addrs[i].sin_len = sizeof(struct sockaddr_in);
|
481
|
+
#endif
|
241
482
|
}
|
242
483
|
|
243
484
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
@@ -251,6 +492,9 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
251
492
|
}
|
252
493
|
|
253
494
|
/*
|
495
|
+
* call-seq:
|
496
|
+
* SCTP::Socket#close
|
497
|
+
*
|
254
498
|
* Close the socket. You should always do this.
|
255
499
|
*
|
256
500
|
* Example:
|
@@ -268,22 +512,25 @@ static VALUE rsctp_close(VALUE self){
|
|
268
512
|
}
|
269
513
|
|
270
514
|
/*
|
271
|
-
*
|
272
|
-
*
|
515
|
+
* call-seq:
|
516
|
+
* SCTP::Socket#getpeernames
|
273
517
|
*
|
274
|
-
*
|
275
|
-
*
|
518
|
+
* Return an array of all addresses of a peer of the current socket
|
519
|
+
* and association number.
|
276
520
|
*
|
277
|
-
*
|
521
|
+
* You may optionally pass a assocation fileno and association ID. Typically
|
522
|
+
* this information would come from the peeloff method.
|
278
523
|
*
|
279
|
-
*
|
280
|
-
* # ...
|
281
|
-
* p socket.getpeernames
|
524
|
+
* Example:
|
282
525
|
*
|
283
|
-
*
|
284
|
-
*
|
526
|
+
* socket = SCTP::Socket.new
|
527
|
+
* # ...
|
528
|
+
* p socket.getpeernames
|
529
|
+
*
|
530
|
+
* info = socket.recvmsg
|
531
|
+
* association_fileno = socket.peeloff(info.association_id)
|
285
532
|
*
|
286
|
-
*
|
533
|
+
* p socket.getpeernames(association_fileno, info.association_id)
|
287
534
|
*/
|
288
535
|
static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
289
536
|
sctp_assoc_t assoc_id;
|
@@ -326,6 +573,9 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
326
573
|
}
|
327
574
|
|
328
575
|
/*
|
576
|
+
* call-seq:
|
577
|
+
* SCTP::Socket#getlocalnames
|
578
|
+
*
|
329
579
|
* Return an array of local addresses that are part of the association.
|
330
580
|
*
|
331
581
|
* Example:
|
@@ -381,6 +631,9 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
381
631
|
|
382
632
|
#ifdef HAVE_SCTP_SENDV
|
383
633
|
/*
|
634
|
+
* call-seq:
|
635
|
+
* SCTP::Socket#sendv(options)
|
636
|
+
*
|
384
637
|
* Transmit a message to an SCTP endpoint using a gather-write. The following
|
385
638
|
* hash of options is permitted:
|
386
639
|
*
|
@@ -392,13 +645,14 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
392
645
|
*
|
393
646
|
* socket = SCTP::Socket.new
|
394
647
|
*
|
648
|
+
* # You can specify addresses here or in an earlier connectx call.
|
395
649
|
* socket.sendv
|
396
650
|
* :message => ['Hello ', 'World.'],
|
397
651
|
* :addresses => ['10.0.5.4', '10.0.6.4'],
|
398
652
|
* :info_type => SCTP::Socket:::SCTP_SENDV_SNDINFO
|
399
653
|
* )
|
400
654
|
*
|
401
|
-
* CAVEAT: Currently
|
655
|
+
* CAVEAT: Currently info_type is not yet supported.
|
402
656
|
*
|
403
657
|
* Returns the number of bytes sent.
|
404
658
|
*/
|
@@ -406,13 +660,14 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
406
660
|
VALUE v_msg, v_message, v_addresses;
|
407
661
|
struct iovec iov[IOV_MAX];
|
408
662
|
struct sockaddr_in* addrs;
|
409
|
-
struct
|
410
|
-
int i, fileno,
|
663
|
+
struct sctp_sendv_spa spa;
|
664
|
+
int i, fileno, size, num_ip;
|
665
|
+
ssize_t num_bytes;
|
411
666
|
|
412
667
|
Check_Type(v_options, T_HASH);
|
413
668
|
|
414
669
|
bzero(&iov, sizeof(iov));
|
415
|
-
bzero(&
|
670
|
+
bzero(&spa, sizeof(spa));
|
416
671
|
|
417
672
|
v_message = rb_hash_aref2(v_options, "message");
|
418
673
|
v_addresses = rb_hash_aref2(v_options, "addresses");
|
@@ -422,8 +677,8 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
422
677
|
|
423
678
|
if(!NIL_P(v_addresses)){
|
424
679
|
Check_Type(v_addresses, T_ARRAY);
|
425
|
-
num_ip = RARRAY_LEN(v_addresses);
|
426
|
-
addrs = (struct sockaddr_in*)alloca(sizeof(
|
680
|
+
num_ip = (int)RARRAY_LEN(v_addresses);
|
681
|
+
addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(*addrs));
|
427
682
|
}
|
428
683
|
else{
|
429
684
|
addrs = NULL;
|
@@ -431,7 +686,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
431
686
|
}
|
432
687
|
|
433
688
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
434
|
-
size = RARRAY_LEN(v_message);
|
689
|
+
size = (int)RARRAY_LEN(v_message);
|
435
690
|
|
436
691
|
if(!size)
|
437
692
|
rb_raise(rb_eArgError, "Must contain at least one message");
|
@@ -439,26 +694,31 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
439
694
|
if(size > IOV_MAX)
|
440
695
|
rb_raise(rb_eArgError, "Array size is greater than IOV_MAX");
|
441
696
|
|
442
|
-
|
443
|
-
|
697
|
+
// TODO: Make this configurable
|
698
|
+
spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
|
699
|
+
spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
444
700
|
|
445
701
|
if(!NIL_P(v_addresses)){
|
446
|
-
int i, port;
|
702
|
+
int i, port, domain;
|
447
703
|
VALUE v_address, v_port;
|
448
704
|
|
449
|
-
v_port =
|
705
|
+
v_port = rb_iv_get(self, "@port");
|
450
706
|
|
451
707
|
if(NIL_P(v_port))
|
452
708
|
port = 0;
|
453
709
|
else
|
454
710
|
port = NUM2INT(v_port);
|
455
711
|
|
712
|
+
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
713
|
+
|
456
714
|
for(i = 0; i < num_ip; i++){
|
457
715
|
v_address = RARRAY_PTR(v_addresses)[i];
|
458
|
-
addrs
|
459
|
-
addrs
|
460
|
-
addrs
|
461
|
-
|
716
|
+
addrs[i].sin_family = domain;
|
717
|
+
addrs[i].sin_port = htons(port);
|
718
|
+
addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
719
|
+
#ifdef BSD
|
720
|
+
addrs[i].sin_len = sizeof(struct sockaddr_in);
|
721
|
+
#endif
|
462
722
|
}
|
463
723
|
}
|
464
724
|
|
@@ -468,29 +728,30 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
468
728
|
iov[i].iov_len = RSTRING_LEN(v_msg);
|
469
729
|
}
|
470
730
|
|
471
|
-
num_bytes = sctp_sendv(
|
731
|
+
num_bytes = (ssize_t)sctp_sendv(
|
472
732
|
fileno,
|
473
733
|
iov,
|
474
734
|
size,
|
475
735
|
(struct sockaddr*)addrs,
|
476
736
|
num_ip,
|
477
|
-
&
|
478
|
-
sizeof(
|
479
|
-
|
737
|
+
&spa,
|
738
|
+
sizeof(spa),
|
739
|
+
SCTP_SENDV_SPA,
|
480
740
|
0
|
481
741
|
);
|
482
742
|
|
483
743
|
if(num_bytes < 0)
|
484
744
|
rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
|
485
745
|
|
486
|
-
return
|
746
|
+
return LONG2NUM(num_bytes);
|
487
747
|
}
|
488
748
|
#endif
|
489
749
|
|
490
750
|
#ifdef HAVE_SCTP_RECVV
|
491
751
|
static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
492
752
|
VALUE v_flags;
|
493
|
-
int fileno, flags,
|
753
|
+
int fileno, flags, on;
|
754
|
+
ssize_t bytes;
|
494
755
|
uint infotype;
|
495
756
|
socklen_t infolen;
|
496
757
|
struct iovec iov[1];
|
@@ -520,7 +781,7 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
520
781
|
infolen = sizeof(struct sctp_rcvinfo);
|
521
782
|
infotype = 0;
|
522
783
|
|
523
|
-
bytes = sctp_recvv(
|
784
|
+
bytes = (ssize_t)sctp_recvv(
|
524
785
|
fileno,
|
525
786
|
iov,
|
526
787
|
1,
|
@@ -556,6 +817,9 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
|
|
556
817
|
#endif
|
557
818
|
|
558
819
|
/*
|
820
|
+
* call-seq:
|
821
|
+
* SCTP::Socket.send(options)
|
822
|
+
*
|
559
823
|
* Send a message on an already-connected socket to a specific association.
|
560
824
|
*
|
561
825
|
* Example:
|
@@ -634,7 +898,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
634
898
|
|
635
899
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
636
900
|
|
637
|
-
num_bytes = sctp_send(
|
901
|
+
num_bytes = (ssize_t)sctp_send(
|
638
902
|
fileno,
|
639
903
|
StringValueCStr(v_msg),
|
640
904
|
RSTRING_LEN(v_msg),
|
@@ -645,10 +909,13 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
645
909
|
if(num_bytes < 0)
|
646
910
|
rb_raise(rb_eSystemCallError, "sctp_send: %s", strerror(errno));
|
647
911
|
|
648
|
-
return
|
912
|
+
return LONG2NUM(num_bytes);
|
649
913
|
}
|
650
914
|
|
651
915
|
/*
|
916
|
+
* call-seq:
|
917
|
+
* SCTP::Socket#sendmsg(options)
|
918
|
+
*
|
652
919
|
* Transmit a message to an SCTP endpoint. The following hash of options
|
653
920
|
* is permitted:
|
654
921
|
*
|
@@ -683,7 +950,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
683
950
|
uint32_t ppid, flags, ttl, context;
|
684
951
|
ssize_t num_bytes;
|
685
952
|
struct sockaddr_in addrs[8];
|
686
|
-
int fileno, size;
|
953
|
+
int fileno, size, num_ip;
|
687
954
|
|
688
955
|
Check_Type(v_options, T_HASH);
|
689
956
|
|
@@ -726,10 +993,10 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
726
993
|
context = NUM2INT(v_context);
|
727
994
|
|
728
995
|
if(!NIL_P(v_addresses)){
|
729
|
-
int i,
|
996
|
+
int i, port;
|
730
997
|
VALUE v_address, v_port;
|
731
998
|
|
732
|
-
num_ip = RARRAY_LEN(v_addresses);
|
999
|
+
num_ip = (int)RARRAY_LEN(v_addresses);
|
733
1000
|
v_port = rb_hash_aref2(v_options, "port");
|
734
1001
|
|
735
1002
|
if(NIL_P(v_port))
|
@@ -742,17 +1009,51 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
742
1009
|
addrs[i].sin_family = NUM2INT(rb_iv_get(self, "@domain"));
|
743
1010
|
addrs[i].sin_port = htons(port);
|
744
1011
|
addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
|
1012
|
+
#ifdef BSD
|
1013
|
+
addrs[i].sin_len = sizeof(struct sockaddr_in);
|
1014
|
+
#endif
|
745
1015
|
}
|
746
1016
|
|
747
1017
|
size = sizeof(addrs);
|
748
1018
|
}
|
749
1019
|
else{
|
1020
|
+
num_ip = 0;
|
750
1021
|
size = 0;
|
751
1022
|
}
|
752
1023
|
|
753
1024
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
754
1025
|
|
755
|
-
|
1026
|
+
#ifdef BSD
|
1027
|
+
if(num_ip){
|
1028
|
+
num_bytes = (ssize_t)sctp_sendmsgx(
|
1029
|
+
fileno,
|
1030
|
+
StringValueCStr(v_msg),
|
1031
|
+
RSTRING_LEN(v_msg),
|
1032
|
+
(struct sockaddr*)addrs,
|
1033
|
+
num_ip,
|
1034
|
+
ppid,
|
1035
|
+
flags,
|
1036
|
+
stream,
|
1037
|
+
ttl,
|
1038
|
+
context
|
1039
|
+
);
|
1040
|
+
}
|
1041
|
+
else{
|
1042
|
+
num_bytes = (ssize_t)sctp_sendmsg(
|
1043
|
+
fileno,
|
1044
|
+
StringValueCStr(v_msg),
|
1045
|
+
RSTRING_LEN(v_msg),
|
1046
|
+
(struct sockaddr*)addrs,
|
1047
|
+
size,
|
1048
|
+
ppid,
|
1049
|
+
flags,
|
1050
|
+
stream,
|
1051
|
+
ttl,
|
1052
|
+
context
|
1053
|
+
);
|
1054
|
+
}
|
1055
|
+
#else
|
1056
|
+
num_bytes = (ssize_t)sctp_sendmsg(
|
756
1057
|
fileno,
|
757
1058
|
StringValueCStr(v_msg),
|
758
1059
|
RSTRING_LEN(v_msg),
|
@@ -764,14 +1065,26 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
764
1065
|
ttl,
|
765
1066
|
context
|
766
1067
|
);
|
1068
|
+
#endif
|
767
1069
|
|
768
|
-
if(num_bytes < 0)
|
1070
|
+
if(num_bytes < 0){
|
1071
|
+
#ifdef BSD
|
1072
|
+
if(num_ip > 0)
|
1073
|
+
rb_raise(rb_eSystemCallError, "sctp_sendmsgx: %s", strerror(errno));
|
1074
|
+
else
|
1075
|
+
rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
|
1076
|
+
#else
|
769
1077
|
rb_raise(rb_eSystemCallError, "sctp_sendmsg: %s", strerror(errno));
|
1078
|
+
#endif
|
1079
|
+
}
|
770
1080
|
|
771
|
-
return
|
1081
|
+
return LONG2NUM(num_bytes);
|
772
1082
|
}
|
773
1083
|
|
774
1084
|
/*
|
1085
|
+
* call-seq:
|
1086
|
+
* SCTP::Socket#recvmsg(flags=0)
|
1087
|
+
*
|
775
1088
|
* Receive a message from another SCTP endpoint.
|
776
1089
|
*
|
777
1090
|
* Example:
|
@@ -794,7 +1107,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
794
1107
|
VALUE v_flags, v_notification, v_message;
|
795
1108
|
struct sctp_sndrcvinfo sndrcvinfo;
|
796
1109
|
struct sockaddr_in clientaddr;
|
797
|
-
int flags,
|
1110
|
+
int flags, fileno;
|
1111
|
+
ssize_t bytes;
|
798
1112
|
char buffer[1024]; // TODO: Let this be configurable?
|
799
1113
|
socklen_t length;
|
800
1114
|
|
@@ -812,7 +1126,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
812
1126
|
bzero(&clientaddr, sizeof(clientaddr));
|
813
1127
|
bzero(&sndrcvinfo, sizeof(sndrcvinfo));
|
814
1128
|
|
815
|
-
bytes = sctp_recvmsg(
|
1129
|
+
bytes = (ssize_t)sctp_recvmsg(
|
816
1130
|
fileno,
|
817
1131
|
buffer,
|
818
1132
|
sizeof(buffer),
|
@@ -827,187 +1141,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
827
1141
|
|
828
1142
|
v_notification = Qnil;
|
829
1143
|
|
830
|
-
if(flags & MSG_NOTIFICATION)
|
831
|
-
|
832
|
-
char str[16];
|
833
|
-
union sctp_notification* snp;
|
834
|
-
VALUE v_str;
|
835
|
-
VALUE* v_temp;
|
836
|
-
|
837
|
-
snp = (union sctp_notification*)buffer;
|
838
|
-
|
839
|
-
switch(snp->sn_header.sn_type){
|
840
|
-
case SCTP_ASSOC_CHANGE:
|
841
|
-
switch(snp->sn_assoc_change.sac_state){
|
842
|
-
case SCTP_COMM_LOST:
|
843
|
-
v_str = rb_str_new2("comm lost");
|
844
|
-
break;
|
845
|
-
case SCTP_COMM_UP:
|
846
|
-
v_str = rb_str_new2("comm up");
|
847
|
-
break;
|
848
|
-
case SCTP_RESTART:
|
849
|
-
v_str = rb_str_new2("restart");
|
850
|
-
break;
|
851
|
-
case SCTP_SHUTDOWN_COMP:
|
852
|
-
v_str = rb_str_new2("shutdown complete");
|
853
|
-
break;
|
854
|
-
case SCTP_CANT_STR_ASSOC:
|
855
|
-
v_str = rb_str_new2("association setup failed");
|
856
|
-
break;
|
857
|
-
default:
|
858
|
-
v_str = rb_str_new2("unknown");
|
859
|
-
}
|
860
|
-
|
861
|
-
v_notification = rb_struct_new(v_assoc_change_struct,
|
862
|
-
UINT2NUM(snp->sn_assoc_change.sac_type),
|
863
|
-
UINT2NUM(snp->sn_assoc_change.sac_length),
|
864
|
-
UINT2NUM(snp->sn_assoc_change.sac_state),
|
865
|
-
UINT2NUM(snp->sn_assoc_change.sac_error),
|
866
|
-
UINT2NUM(snp->sn_assoc_change.sac_outbound_streams),
|
867
|
-
UINT2NUM(snp->sn_assoc_change.sac_inbound_streams),
|
868
|
-
UINT2NUM(snp->sn_assoc_change.sac_assoc_id),
|
869
|
-
v_str
|
870
|
-
);
|
871
|
-
break;
|
872
|
-
case SCTP_PEER_ADDR_CHANGE:
|
873
|
-
switch(snp->sn_paddr_change.spc_state){
|
874
|
-
case SCTP_ADDR_AVAILABLE:
|
875
|
-
v_str = rb_str_new2("available");
|
876
|
-
break;
|
877
|
-
case SCTP_ADDR_UNREACHABLE:
|
878
|
-
v_str = rb_str_new2("unreachable");
|
879
|
-
break;
|
880
|
-
case SCTP_ADDR_REMOVED:
|
881
|
-
v_str = rb_str_new2("removed from association");
|
882
|
-
break;
|
883
|
-
case SCTP_ADDR_ADDED:
|
884
|
-
v_str = rb_str_new2("added to association");
|
885
|
-
break;
|
886
|
-
case SCTP_ADDR_MADE_PRIM:
|
887
|
-
v_str = rb_str_new2("primary destination");
|
888
|
-
break;
|
889
|
-
default:
|
890
|
-
v_str = rb_str_new2("unknown");
|
891
|
-
}
|
892
|
-
|
893
|
-
inet_ntop(
|
894
|
-
((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
|
895
|
-
&(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
|
896
|
-
str,
|
897
|
-
sizeof(str)
|
898
|
-
);
|
899
|
-
|
900
|
-
v_notification = rb_struct_new(v_peeraddr_change_struct,
|
901
|
-
UINT2NUM(snp->sn_paddr_change.spc_type),
|
902
|
-
UINT2NUM(snp->sn_paddr_change.spc_length),
|
903
|
-
rb_str_new2(str),
|
904
|
-
UINT2NUM(snp->sn_paddr_change.spc_state),
|
905
|
-
UINT2NUM(snp->sn_paddr_change.spc_error),
|
906
|
-
UINT2NUM(snp->sn_paddr_change.spc_assoc_id),
|
907
|
-
v_str
|
908
|
-
);
|
909
|
-
break;
|
910
|
-
case SCTP_REMOTE_ERROR:
|
911
|
-
v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
|
912
|
-
|
913
|
-
for(i = 0; i < snp->sn_remote_error.sre_length; i++){
|
914
|
-
v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
|
915
|
-
}
|
916
|
-
|
917
|
-
v_notification = rb_struct_new(v_remote_error_struct,
|
918
|
-
UINT2NUM(snp->sn_remote_error.sre_type),
|
919
|
-
UINT2NUM(snp->sn_remote_error.sre_flags),
|
920
|
-
UINT2NUM(snp->sn_remote_error.sre_length),
|
921
|
-
UINT2NUM(snp->sn_remote_error.sre_error),
|
922
|
-
UINT2NUM(snp->sn_remote_error.sre_assoc_id),
|
923
|
-
rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
|
924
|
-
);
|
925
|
-
break;
|
926
|
-
#ifdef SCTP_SEND_FAILED_EVENT
|
927
|
-
case SCTP_SEND_FAILED_EVENT:
|
928
|
-
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
|
929
|
-
|
930
|
-
for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
|
931
|
-
v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
|
932
|
-
}
|
933
|
-
|
934
|
-
v_notification = rb_struct_new(v_send_failed_event_struct,
|
935
|
-
UINT2NUM(snp->sn_send_failed_event.ssf_type),
|
936
|
-
UINT2NUM(snp->sn_send_failed_event.ssf_length),
|
937
|
-
UINT2NUM(snp->sn_send_failed_event.ssf_error),
|
938
|
-
rb_struct_new(v_sndinfo_struct,
|
939
|
-
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
|
940
|
-
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
|
941
|
-
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
|
942
|
-
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
|
943
|
-
UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
|
944
|
-
),
|
945
|
-
UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
|
946
|
-
rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
|
947
|
-
);
|
948
|
-
break;
|
949
|
-
#else
|
950
|
-
case SCTP_SEND_FAILED:
|
951
|
-
v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
|
952
|
-
|
953
|
-
for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
|
954
|
-
v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
|
955
|
-
}
|
956
|
-
|
957
|
-
v_notification = rb_struct_new(v_send_failed_event_struct,
|
958
|
-
UINT2NUM(snp->sn_send_failed.ssf_type),
|
959
|
-
UINT2NUM(snp->sn_send_failed.ssf_length),
|
960
|
-
UINT2NUM(snp->sn_send_failed.ssf_error),
|
961
|
-
Qnil,
|
962
|
-
UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
|
963
|
-
rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
|
964
|
-
);
|
965
|
-
break;
|
966
|
-
#endif
|
967
|
-
case SCTP_SHUTDOWN_EVENT:
|
968
|
-
v_notification = rb_struct_new(v_shutdown_event_struct,
|
969
|
-
UINT2NUM(snp->sn_shutdown_event.sse_type),
|
970
|
-
UINT2NUM(snp->sn_shutdown_event.sse_length),
|
971
|
-
UINT2NUM(snp->sn_shutdown_event.sse_assoc_id)
|
972
|
-
);
|
973
|
-
break;
|
974
|
-
case SCTP_ADAPTATION_INDICATION:
|
975
|
-
v_notification = rb_struct_new(v_adaptation_event_struct,
|
976
|
-
UINT2NUM(snp->sn_adaptation_event.sai_type),
|
977
|
-
UINT2NUM(snp->sn_adaptation_event.sai_length),
|
978
|
-
UINT2NUM(snp->sn_adaptation_event.sai_adaptation_ind),
|
979
|
-
UINT2NUM(snp->sn_adaptation_event.sai_assoc_id)
|
980
|
-
);
|
981
|
-
break;
|
982
|
-
case SCTP_PARTIAL_DELIVERY_EVENT:
|
983
|
-
v_notification = rb_struct_new(v_partial_delivery_event_struct,
|
984
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_type),
|
985
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_length),
|
986
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_indication),
|
987
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_stream),
|
988
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_seq),
|
989
|
-
UINT2NUM(snp->sn_pdapi_event.pdapi_assoc_id)
|
990
|
-
);
|
991
|
-
break;
|
992
|
-
case SCTP_AUTHENTICATION_EVENT:
|
993
|
-
v_notification = rb_struct_new(v_auth_event_struct,
|
994
|
-
UINT2NUM(snp->sn_authkey_event.auth_type),
|
995
|
-
UINT2NUM(snp->sn_authkey_event.auth_length),
|
996
|
-
UINT2NUM(snp->sn_authkey_event.auth_keynumber),
|
997
|
-
UINT2NUM(snp->sn_authkey_event.auth_indication),
|
998
|
-
UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
|
999
|
-
);
|
1000
|
-
break;
|
1001
|
-
case SCTP_SENDER_DRY_EVENT:
|
1002
|
-
v_notification = rb_struct_new(v_sender_dry_event_struct,
|
1003
|
-
UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
|
1004
|
-
UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
|
1005
|
-
UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
|
1006
|
-
UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
|
1007
|
-
);
|
1008
|
-
break;
|
1009
|
-
}
|
1010
|
-
}
|
1144
|
+
if(flags & MSG_NOTIFICATION)
|
1145
|
+
v_notification = get_notification_info(buffer);
|
1011
1146
|
|
1012
1147
|
if(NIL_P(v_notification))
|
1013
1148
|
v_message = rb_str_new(buffer, bytes);
|
@@ -1028,6 +1163,9 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
1028
1163
|
}
|
1029
1164
|
|
1030
1165
|
/*
|
1166
|
+
* call-seq:
|
1167
|
+
* SCTP::Socket#set_initmsg(options)
|
1168
|
+
*
|
1031
1169
|
* Set the initial parameters used by the socket when sending out the INIT message.
|
1032
1170
|
*
|
1033
1171
|
* Example:
|
@@ -1077,6 +1215,9 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
1077
1215
|
}
|
1078
1216
|
|
1079
1217
|
/*
|
1218
|
+
* call-seq:
|
1219
|
+
* SCTP::Socket#subscribe(options)
|
1220
|
+
*
|
1080
1221
|
* Subscribe to various notification type events, which will generate additional
|
1081
1222
|
* data that the socket may receive. The possible notification type events are
|
1082
1223
|
* as follows:
|
@@ -1161,6 +1302,9 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
|
|
1161
1302
|
}
|
1162
1303
|
|
1163
1304
|
/*
|
1305
|
+
* call-seq:
|
1306
|
+
* SCTP::Socket#listen(backlog=128)
|
1307
|
+
*
|
1164
1308
|
* Marks the socket referred to by sockfd as a passive socket, i.e. a socket that
|
1165
1309
|
* will be used to accept incoming connection requests.
|
1166
1310
|
*
|
@@ -1204,6 +1348,9 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
1204
1348
|
}
|
1205
1349
|
|
1206
1350
|
/*
|
1351
|
+
* call-seq:
|
1352
|
+
* SCTP::Socket#peeloff(association_id)
|
1353
|
+
*
|
1207
1354
|
* Extracts an association contained by a one-to-many socket connection into
|
1208
1355
|
* a one-to-one style socket. Returns the socket descriptor (fileno).
|
1209
1356
|
*
|
@@ -1234,6 +1381,9 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
|
1234
1381
|
}
|
1235
1382
|
|
1236
1383
|
/*
|
1384
|
+
* call-seq:
|
1385
|
+
* SCTP::Socket#get_default_send_params
|
1386
|
+
*
|
1237
1387
|
* Returns the default set of parameters that a call to the sendto function
|
1238
1388
|
* uses on this association. This is a struct that contains the following
|
1239
1389
|
* members:
|
@@ -1278,6 +1428,9 @@ static VALUE rsctp_get_default_send_params(VALUE self){
|
|
1278
1428
|
}
|
1279
1429
|
|
1280
1430
|
/*
|
1431
|
+
* call-seq:
|
1432
|
+
* SCTP::Socket#get_association_info
|
1433
|
+
*
|
1281
1434
|
* Returns the association specific parameters. This is a struct
|
1282
1435
|
* that contains the following members:
|
1283
1436
|
*
|
@@ -1317,6 +1470,9 @@ static VALUE rsctp_get_association_info(VALUE self){
|
|
1317
1470
|
}
|
1318
1471
|
|
1319
1472
|
/*
|
1473
|
+
* call-seq:
|
1474
|
+
* SCTP::Socket#shutdown
|
1475
|
+
*
|
1320
1476
|
* Shuts down socket send and receive operations.
|
1321
1477
|
*
|
1322
1478
|
* Optionally accepts an argument that specifieds the type of shutdown.
|
@@ -1351,6 +1507,9 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
|
|
1351
1507
|
}
|
1352
1508
|
|
1353
1509
|
/*
|
1510
|
+
* call-seq:
|
1511
|
+
* SCTP::Socket#get_retransmission_info
|
1512
|
+
*
|
1354
1513
|
* Returns the protocol parameters that are used to initialize and bind the
|
1355
1514
|
* retransmission timeout (RTO) tunable. This is a struct with the following
|
1356
1515
|
* members:
|
@@ -1385,6 +1544,9 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
|
|
1385
1544
|
}
|
1386
1545
|
|
1387
1546
|
/*
|
1547
|
+
* call-seq:
|
1548
|
+
* SCTP::Socket#get_status
|
1549
|
+
*
|
1388
1550
|
* Get the status of a connected socket.
|
1389
1551
|
*
|
1390
1552
|
* Example:
|
@@ -1449,6 +1611,9 @@ static VALUE rsctp_get_status(VALUE self){
|
|
1449
1611
|
}
|
1450
1612
|
|
1451
1613
|
/*
|
1614
|
+
* call-seq:
|
1615
|
+
* SCTP::Socket#get_subscriptions
|
1616
|
+
*
|
1452
1617
|
* Returns a struct of events detailing which events have been
|
1453
1618
|
* subscribed to by the socket. The struct contains the following
|
1454
1619
|
* members:
|
@@ -1483,7 +1648,8 @@ static VALUE rsctp_get_subscriptions(VALUE self){
|
|
1483
1648
|
if(sctp_opt_info(fileno, assoc_id, SCTP_EVENTS, (void*)&events, &size) < 0)
|
1484
1649
|
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1485
1650
|
|
1486
|
-
return rb_struct_new(
|
1651
|
+
return rb_struct_new(
|
1652
|
+
v_sctp_event_subscribe_struct,
|
1487
1653
|
(events.sctp_data_io_event ? Qtrue : Qfalse),
|
1488
1654
|
(events.sctp_association_event ? Qtrue : Qfalse),
|
1489
1655
|
(events.sctp_address_event ? Qtrue : Qfalse),
|
@@ -1493,14 +1659,43 @@ static VALUE rsctp_get_subscriptions(VALUE self){
|
|
1493
1659
|
(events.sctp_partial_delivery_event ? Qtrue : Qfalse),
|
1494
1660
|
(events.sctp_adaptation_layer_event ? Qtrue : Qfalse),
|
1495
1661
|
(events.sctp_authentication_event ? Qtrue : Qfalse),
|
1496
|
-
(events.sctp_sender_dry_event ? Qtrue : Qfalse)
|
1497
|
-
|
1498
|
-
(events.
|
1499
|
-
|
1500
|
-
|
1662
|
+
(events.sctp_sender_dry_event ? Qtrue : Qfalse)
|
1663
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_STREAM_RESET_EVENT
|
1664
|
+
,(events.sctp_stream_reset_event ? Qtrue : Qfalse)
|
1665
|
+
#endif
|
1666
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_ASSOC_RESET_EVENT
|
1667
|
+
,(events.sctp_assoc_reset_event ? Qtrue : Qfalse)
|
1668
|
+
#endif
|
1669
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_STREAM_CHANGE_EVENT
|
1670
|
+
,(events.sctp_stream_change_event ? Qtrue : Qfalse)
|
1671
|
+
#endif
|
1672
|
+
#ifdef HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SEND_FAILURE_EVENT_EVENT
|
1673
|
+
,(events.sctp_send_failure_event_event ? Qtrue : Qfalse)
|
1674
|
+
#endif
|
1501
1675
|
);
|
1502
1676
|
}
|
1503
1677
|
|
1678
|
+
/*
|
1679
|
+
* call-seq:
|
1680
|
+
* SCTP::Socket#get_peer_address_params
|
1681
|
+
*
|
1682
|
+
* Applications can enable or disable heartbeats for any peer address of
|
1683
|
+
* an association, modify an address's heartbeat interval, force a
|
1684
|
+
* heartbeat to be sent immediately, and adjust the address's maximum
|
1685
|
+
* number of retransmissions sent before an address is considered
|
1686
|
+
* unreachable.
|
1687
|
+
*
|
1688
|
+
* This method returns a struct that contains this information. It contains
|
1689
|
+
* the following struct members.
|
1690
|
+
*
|
1691
|
+
* * association_id
|
1692
|
+
* * address
|
1693
|
+
* * heartbeat_interval
|
1694
|
+
* * max_retransmission_count
|
1695
|
+
* * path_mtu
|
1696
|
+
* * flags
|
1697
|
+
* * ipv6_flowlabel
|
1698
|
+
*/
|
1504
1699
|
static VALUE rsctp_get_peer_address_params(VALUE self){
|
1505
1700
|
int fileno;
|
1506
1701
|
char str[16];
|
@@ -1525,10 +1720,482 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
|
|
1525
1720
|
INT2NUM(paddr.spp_assoc_id),
|
1526
1721
|
rb_str_new2(str),
|
1527
1722
|
INT2NUM(paddr.spp_hbinterval),
|
1528
|
-
INT2NUM(paddr.spp_pathmaxrxt)
|
1723
|
+
INT2NUM(paddr.spp_pathmaxrxt),
|
1724
|
+
INT2NUM(paddr.spp_pathmtu),
|
1725
|
+
INT2NUM(paddr.spp_flags),
|
1726
|
+
INT2NUM(paddr.spp_ipv6_flowlabel)
|
1529
1727
|
);
|
1530
1728
|
}
|
1531
1729
|
|
1730
|
+
/*
|
1731
|
+
* call-seq:
|
1732
|
+
* SCTP::Socket#get_init_msg
|
1733
|
+
*
|
1734
|
+
* Returns a structure that contains various initialization parameters.
|
1735
|
+
*
|
1736
|
+
* * num_ostreams: A number representing the number of streams that the
|
1737
|
+
* application wishes to be able to send to.
|
1738
|
+
*
|
1739
|
+
* * max_instreams: The maximum number of inbound streams the application
|
1740
|
+
* is prepared to support.
|
1741
|
+
*
|
1742
|
+
* * max_attempts: The number of attempts the SCTP endpoint should make at
|
1743
|
+
* resending the INIT.
|
1744
|
+
*
|
1745
|
+
* * max_init_timeout: This value represents the largest Timeout or RTO value
|
1746
|
+
* (in milliseconds) to use in attempting an INIT.
|
1747
|
+
*/
|
1748
|
+
static VALUE rsctp_get_init_msg(VALUE self){
|
1749
|
+
int fileno;
|
1750
|
+
socklen_t size;
|
1751
|
+
sctp_assoc_t assoc_id;
|
1752
|
+
struct sctp_initmsg initmsg;
|
1753
|
+
|
1754
|
+
bzero(&initmsg, sizeof(initmsg));
|
1755
|
+
|
1756
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1757
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1758
|
+
size = sizeof(struct sctp_initmsg);
|
1759
|
+
|
1760
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_INITMSG, (void*)&initmsg, &size) < 0)
|
1761
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1762
|
+
|
1763
|
+
return rb_struct_new(
|
1764
|
+
v_sctp_initmsg_struct,
|
1765
|
+
INT2NUM(initmsg.sinit_num_ostreams),
|
1766
|
+
INT2NUM(initmsg.sinit_max_instreams),
|
1767
|
+
INT2NUM(initmsg.sinit_max_attempts),
|
1768
|
+
INT2NUM(initmsg.sinit_max_init_timeo)
|
1769
|
+
);
|
1770
|
+
}
|
1771
|
+
|
1772
|
+
/*
|
1773
|
+
* call-seq:
|
1774
|
+
* SCTP::Socket#nodelay?
|
1775
|
+
*
|
1776
|
+
* Returns whether or not the nodelay option has been set.
|
1777
|
+
*/
|
1778
|
+
static VALUE rsctp_get_nodelay(VALUE self){
|
1779
|
+
int fileno;
|
1780
|
+
socklen_t size;
|
1781
|
+
sctp_assoc_t assoc_id;
|
1782
|
+
int value;
|
1783
|
+
|
1784
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1785
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1786
|
+
size = sizeof(int);
|
1787
|
+
|
1788
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
|
1789
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1790
|
+
|
1791
|
+
if(value)
|
1792
|
+
return Qtrue;
|
1793
|
+
else
|
1794
|
+
return Qfalse;
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
/*
|
1798
|
+
* call-seq:
|
1799
|
+
* SCTP::Socket#nodelay=(bool)
|
1800
|
+
*
|
1801
|
+
* Turn on/off any Nagle-like algorithm. This means that packets are generally
|
1802
|
+
* sent as soon as possible and no unnecessary delays are introduced, at the
|
1803
|
+
* cost of more packets in the network.
|
1804
|
+
*/
|
1805
|
+
static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
1806
|
+
int fileno;
|
1807
|
+
socklen_t size;
|
1808
|
+
sctp_assoc_t assoc_id;
|
1809
|
+
int value;
|
1810
|
+
|
1811
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1812
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1813
|
+
size = sizeof(int);
|
1814
|
+
|
1815
|
+
if(NIL_P(v_bool) || v_bool == Qfalse)
|
1816
|
+
value = 0;
|
1817
|
+
else
|
1818
|
+
value = 1;
|
1819
|
+
|
1820
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
|
1821
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1822
|
+
|
1823
|
+
if(value)
|
1824
|
+
return Qtrue;
|
1825
|
+
else
|
1826
|
+
return Qfalse;
|
1827
|
+
}
|
1828
|
+
|
1829
|
+
/*
|
1830
|
+
* call-seq:
|
1831
|
+
* SCTP::Socket#disable_fragments=(bool)
|
1832
|
+
*
|
1833
|
+
* This option is a on/off flag and is passed an integer where a non-
|
1834
|
+
* zero is on and a zero is off. If enabled no SCTP message
|
1835
|
+
* fragmentation will be performed. Instead if a message being sent
|
1836
|
+
* exceeds the current PMTU size, the message will NOT be sent and
|
1837
|
+
* instead a error will be indicated to the user.
|
1838
|
+
*/
|
1839
|
+
static VALUE rsctp_disable_fragments(VALUE self, VALUE v_bool){
|
1840
|
+
int fileno;
|
1841
|
+
socklen_t size;
|
1842
|
+
sctp_assoc_t assoc_id;
|
1843
|
+
int value;
|
1844
|
+
|
1845
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1846
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1847
|
+
size = sizeof(int);
|
1848
|
+
|
1849
|
+
if(NIL_P(v_bool) || v_bool == Qfalse)
|
1850
|
+
value = 0;
|
1851
|
+
else
|
1852
|
+
value = 1;
|
1853
|
+
|
1854
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_DISABLE_FRAGMENTS, (void*)&value, &size) < 0)
|
1855
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1856
|
+
|
1857
|
+
if(value)
|
1858
|
+
return Qtrue;
|
1859
|
+
else
|
1860
|
+
return Qfalse;
|
1861
|
+
}
|
1862
|
+
|
1863
|
+
/*
|
1864
|
+
* call-seq:
|
1865
|
+
* SCTP::Socket#autoclose
|
1866
|
+
*
|
1867
|
+
* Returns the number of seconds before socket associations automatically
|
1868
|
+
* shut down.
|
1869
|
+
*/
|
1870
|
+
static VALUE rsctp_get_autoclose(VALUE self){
|
1871
|
+
int fileno;
|
1872
|
+
socklen_t size;
|
1873
|
+
sctp_assoc_t assoc_id;
|
1874
|
+
int value;
|
1875
|
+
|
1876
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1877
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1878
|
+
size = sizeof(int);
|
1879
|
+
|
1880
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
|
1881
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1882
|
+
|
1883
|
+
return INT2NUM(value);
|
1884
|
+
}
|
1885
|
+
|
1886
|
+
/*
|
1887
|
+
* call-seq:
|
1888
|
+
* SCTP::Socket#autoclose=(seconds=0)
|
1889
|
+
*
|
1890
|
+
* When set it will cause associations that are idle for more than the specified
|
1891
|
+
* number of seconds to automatically close using the graceful shutdown
|
1892
|
+
* procedure. An association being idle is defined as an association that has
|
1893
|
+
* NOT sent or received user data.
|
1894
|
+
*
|
1895
|
+
* The special value of 0 indicates that no automatic close of any associations
|
1896
|
+
* should be performed, this is the default value. The option expects an integer
|
1897
|
+
* defining the number of seconds of idle time before an association is closed.
|
1898
|
+
*
|
1899
|
+
* An application using this option should enable receiving the association
|
1900
|
+
* change notification. This is the only mechanism an application is informed
|
1901
|
+
* about the closing of an association. After an association is closed, the
|
1902
|
+
* association ID assigned to it can be reused. An application should be aware
|
1903
|
+
* of this to avoid the possible problem of sending data to an incorrect peer
|
1904
|
+
* end point.
|
1905
|
+
*
|
1906
|
+
* This socket option is applicable to the one-to-many style socket only.
|
1907
|
+
*/
|
1908
|
+
static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
|
1909
|
+
int fileno;
|
1910
|
+
socklen_t size;
|
1911
|
+
sctp_assoc_t assoc_id;
|
1912
|
+
int value;
|
1913
|
+
|
1914
|
+
value = NUM2INT(v_seconds);
|
1915
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1916
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1917
|
+
size = sizeof(int);
|
1918
|
+
|
1919
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
|
1920
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1921
|
+
|
1922
|
+
return v_seconds;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
/*
|
1926
|
+
* call-seq:
|
1927
|
+
* SCTP::Socket#enable_auth_support(association_id=nil)
|
1928
|
+
*
|
1929
|
+
* Enables auth for future associations.
|
1930
|
+
*/
|
1931
|
+
static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
1932
|
+
int fileno;
|
1933
|
+
socklen_t size;
|
1934
|
+
sctp_assoc_t assoc_id;
|
1935
|
+
struct sctp_assoc_value assoc_value;
|
1936
|
+
VALUE v_assoc_id;
|
1937
|
+
|
1938
|
+
rb_scan_args(argc, argv, "01", &v_assoc_id);
|
1939
|
+
|
1940
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1941
|
+
size = sizeof(struct sctp_assoc_value);
|
1942
|
+
|
1943
|
+
if(NIL_P(v_assoc_id))
|
1944
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1945
|
+
else
|
1946
|
+
assoc_id = NUM2INT(v_assoc_id);
|
1947
|
+
|
1948
|
+
assoc_value.assoc_id = assoc_id;
|
1949
|
+
assoc_value.assoc_value = 1;
|
1950
|
+
|
1951
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, &size) < 0)
|
1952
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
1953
|
+
|
1954
|
+
return self;
|
1955
|
+
}
|
1956
|
+
|
1957
|
+
/*
|
1958
|
+
* call-seq:
|
1959
|
+
* SCTP::Socket#set_shared_key(key, keynum, association_id=nil)
|
1960
|
+
*
|
1961
|
+
* This option will set a shared secret key which is used to build an
|
1962
|
+
* association shared key.
|
1963
|
+
*
|
1964
|
+
* The +key+ parameter should be a string (converted to an array of bytes
|
1965
|
+
* internally) that is to be used by the endpoint (or association) as the
|
1966
|
+
* shared secret key. If an empty string is used, then a null key is set.
|
1967
|
+
*
|
1968
|
+
* The +keynum+ parameter is the shared key identifier by which the
|
1969
|
+
* application will refer to this key. If a key of the specified index already
|
1970
|
+
* exists, then this new key will replace the old existing key. Note that
|
1971
|
+
* shared key identifier '0' defaults to a null key.
|
1972
|
+
*
|
1973
|
+
* The +association_id+, if non-zero, indicates what association that the shared
|
1974
|
+
* key is being set upon. If this argument is zero, then the shared key is set
|
1975
|
+
* upon the endpoint and all future associations will use this key (if not
|
1976
|
+
* changed by subsequent calls). By default this is the result of the
|
1977
|
+
* SCTP::Socket#association_id method.
|
1978
|
+
*
|
1979
|
+
* For one-to-one sockets, this parameter is ignored. Note, however, that this
|
1980
|
+
* option will set a key on the association if the socket is connected,
|
1981
|
+
* otherwise this will set a key on the endpoint.
|
1982
|
+
*/
|
1983
|
+
static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
1984
|
+
int fileno;
|
1985
|
+
size_t len;
|
1986
|
+
char* key;
|
1987
|
+
uint keynum;
|
1988
|
+
socklen_t size;
|
1989
|
+
sctp_assoc_t assoc_id;
|
1990
|
+
struct sctp_authkey* auth_key;
|
1991
|
+
VALUE v_key, v_keynumber, v_assoc_id;
|
1992
|
+
|
1993
|
+
rb_scan_args(argc, argv, "12", &v_key, &v_keynumber, &v_assoc_id);
|
1994
|
+
|
1995
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1996
|
+
key = StringValuePtr(v_key);
|
1997
|
+
len = strlen(key);
|
1998
|
+
unsigned char byte_array[len+1];
|
1999
|
+
|
2000
|
+
for(size_t i = 0; i < len; i++)
|
2001
|
+
byte_array[i] = key[i];
|
2002
|
+
|
2003
|
+
byte_array[len] = '\0';
|
2004
|
+
|
2005
|
+
auth_key = malloc(sizeof(auth_key) + sizeof(char[strlen(key)+1]));
|
2006
|
+
size = sizeof(auth_key);
|
2007
|
+
|
2008
|
+
if(NIL_P(v_assoc_id))
|
2009
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2010
|
+
else
|
2011
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2012
|
+
|
2013
|
+
if(NIL_P(v_keynumber))
|
2014
|
+
keynum = 1;
|
2015
|
+
else
|
2016
|
+
keynum = NUM2INT(v_keynumber);
|
2017
|
+
|
2018
|
+
auth_key->sca_assoc_id = assoc_id;
|
2019
|
+
auth_key->sca_keynumber = keynum;
|
2020
|
+
auth_key->sca_keylength = strlen(key);
|
2021
|
+
memcpy(auth_key->sca_key, byte_array, sizeof(byte_array));
|
2022
|
+
|
2023
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_KEY, (void*)auth_key, &size) < 0)
|
2024
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2025
|
+
|
2026
|
+
return self;
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
/*
|
2030
|
+
* call-seq:
|
2031
|
+
* SCTP::Socket#get_active_shared_key(keynum, association_id=nil)
|
2032
|
+
*
|
2033
|
+
* Gets the active shared key to be used to build the association shared key.
|
2034
|
+
*/
|
2035
|
+
static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
|
2036
|
+
int fileno;
|
2037
|
+
socklen_t size;
|
2038
|
+
struct sctp_authkeyid authkey;
|
2039
|
+
sctp_assoc_t assoc_id;
|
2040
|
+
VALUE v_assoc_id, v_keynum;
|
2041
|
+
uint keynum;
|
2042
|
+
|
2043
|
+
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
2044
|
+
|
2045
|
+
bzero(&authkey, sizeof(authkey));
|
2046
|
+
|
2047
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2048
|
+
keynum = NUM2UINT(v_keynum);
|
2049
|
+
|
2050
|
+
if(NIL_P(v_assoc_id))
|
2051
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2052
|
+
else
|
2053
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2054
|
+
|
2055
|
+
authkey.scact_assoc_id = assoc_id;
|
2056
|
+
authkey.scact_keynumber = keynum;
|
2057
|
+
|
2058
|
+
size = sizeof(struct sctp_authkeyid);
|
2059
|
+
|
2060
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
|
2061
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2062
|
+
|
2063
|
+
return INT2NUM(authkey.scact_keynumber);
|
2064
|
+
}
|
2065
|
+
|
2066
|
+
/*
|
2067
|
+
* call-seq:
|
2068
|
+
* SCTP::Socket#set_active_shared_key(keynum, association_id=nil)
|
2069
|
+
*
|
2070
|
+
* Sets the active shared key to be used to build the association shared key.
|
2071
|
+
*
|
2072
|
+
* Th +keynum+ parameter is the shared key identifier which the application is
|
2073
|
+
* requesting to become the active shared key to be used for sending
|
2074
|
+
* authenticated chunks. The key identifier MUST correspond to an existing
|
2075
|
+
* shared key. Note that shared key identifier '0' defaults to a null key.
|
2076
|
+
*
|
2077
|
+
* The association_idparameter, if non-zero, indicates what association that
|
2078
|
+
* the shared key identifier is being set active upon. If this element contains
|
2079
|
+
* zero, then the activation applies to the endpoint and all future
|
2080
|
+
* associations will use the specified shared key identifier.
|
2081
|
+
*
|
2082
|
+
* For one-to-one sockets, this parameter is ignored. Note, however, that this
|
2083
|
+
* option will set the active key on the association if the socket is connected,
|
2084
|
+
* otherwise this will set the default active key for the endpoint.
|
2085
|
+
*
|
2086
|
+
* By default, the association_id is the result of SCTP::Socket#association_id.
|
2087
|
+
*/
|
2088
|
+
static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
|
2089
|
+
int fileno;
|
2090
|
+
socklen_t size;
|
2091
|
+
struct sctp_authkeyid authkey;
|
2092
|
+
sctp_assoc_t assoc_id;
|
2093
|
+
VALUE v_assoc_id, v_keynum;
|
2094
|
+
uint keynum;
|
2095
|
+
|
2096
|
+
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
2097
|
+
|
2098
|
+
keynum = NUM2UINT(v_keynum);
|
2099
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2100
|
+
|
2101
|
+
if(NIL_P(v_assoc_id))
|
2102
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2103
|
+
else
|
2104
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2105
|
+
|
2106
|
+
authkey.scact_assoc_id = assoc_id;
|
2107
|
+
authkey.scact_keynumber = keynum;
|
2108
|
+
size = sizeof(struct sctp_authkeyid);
|
2109
|
+
|
2110
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
|
2111
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2112
|
+
|
2113
|
+
return self;
|
2114
|
+
}
|
2115
|
+
|
2116
|
+
/*
|
2117
|
+
* call-seq:
|
2118
|
+
* SCTP::Socket#delete_shared_key(keynum, association_id=nil)
|
2119
|
+
*
|
2120
|
+
* Delete a shared secret key from use.
|
2121
|
+
*
|
2122
|
+
* The +keynum+ parameter is the shared key identifier which the application
|
2123
|
+
* is requesting to be deleted. The key identifier MUST correspond to an
|
2124
|
+
* existing shared key and MUST NOT be the current active key.
|
2125
|
+
*
|
2126
|
+
* If this parameter is zero, use of the null key identifier '0' is disabled
|
2127
|
+
* on the endpoint and/or association.
|
2128
|
+
*
|
2129
|
+
* The +association_id+ parameter, if non-zero, indicates what association that
|
2130
|
+
* the shared key identifier is being deleted from. By default this is the
|
2131
|
+
* association that's returned via SCTP::Socket#association_id.
|
2132
|
+
*
|
2133
|
+
* If set to zero, then the shared key is deleted from the endpoint and
|
2134
|
+
* and ALL associations will no longer use the specified shared key identifier
|
2135
|
+
* (unless otherwise set on the association using SCTP_AUTH_KEY).
|
2136
|
+
*
|
2137
|
+
* For one-to-one sockets, this parameter is ignored. Note, however, that this
|
2138
|
+
* option will delete the key from the association if the socket is connected,
|
2139
|
+
* otherwise this will delete the key from the endpoint.
|
2140
|
+
*/
|
2141
|
+
static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
2142
|
+
int fileno;
|
2143
|
+
socklen_t size;
|
2144
|
+
struct sctp_authkeyid authkey;
|
2145
|
+
sctp_assoc_t assoc_id;
|
2146
|
+
VALUE v_assoc_id, v_keynum;
|
2147
|
+
uint keynum;
|
2148
|
+
|
2149
|
+
rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
|
2150
|
+
|
2151
|
+
bzero(&authkey, sizeof(authkey));
|
2152
|
+
|
2153
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2154
|
+
keynum = NUM2UINT(v_keynum);
|
2155
|
+
|
2156
|
+
if(NIL_P(v_assoc_id))
|
2157
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2158
|
+
else
|
2159
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2160
|
+
|
2161
|
+
authkey.scact_assoc_id = assoc_id;
|
2162
|
+
authkey.scact_keynumber = keynum;
|
2163
|
+
|
2164
|
+
size = sizeof(struct sctp_authkeyid);
|
2165
|
+
|
2166
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_DELETE_KEY, (void*)&authkey, &size) < 0)
|
2167
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2168
|
+
|
2169
|
+
return INT2NUM(authkey.scact_keynumber);
|
2170
|
+
}
|
2171
|
+
|
2172
|
+
/*
|
2173
|
+
* call-seq:
|
2174
|
+
* SCTP::Socket#map_ipv4=(bool)
|
2175
|
+
*
|
2176
|
+
* If set to true and the socket is type PF_INET6, then IPv4 addresses will be
|
2177
|
+
* mapped to V6 representation. If set to false (the default), then no mapping
|
2178
|
+
* will be done of V4 addresses and a user will receive both PF_INET6 and
|
2179
|
+
* PF_INET type addresses on the socket.
|
2180
|
+
*/
|
2181
|
+
static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
|
2182
|
+
int fileno, boolean;
|
2183
|
+
sctp_assoc_t assoc_id;
|
2184
|
+
socklen_t size;
|
2185
|
+
|
2186
|
+
boolean = 0;
|
2187
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2188
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2189
|
+
|
2190
|
+
if(v_bool == Qtrue)
|
2191
|
+
boolean = 1;
|
2192
|
+
|
2193
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&boolean, &size) < 0)
|
2194
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2195
|
+
|
2196
|
+
return v_bool;
|
2197
|
+
}
|
2198
|
+
|
1532
2199
|
void Init_socket(void){
|
1533
2200
|
mSCTP = rb_define_module("SCTP");
|
1534
2201
|
cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
|
@@ -1619,23 +2286,38 @@ void Init_socket(void){
|
|
1619
2286
|
|
1620
2287
|
v_sctp_peer_addr_params_struct = rb_struct_define(
|
1621
2288
|
"PeerAddressParams", "association_id", "address", "heartbeat_interval",
|
1622
|
-
"max_retransmission_count",
|
2289
|
+
"max_retransmission_count", "path_mtu", "flags",
|
2290
|
+
"ipv6_flowlabel", NULL
|
2291
|
+
);
|
2292
|
+
|
2293
|
+
v_sctp_initmsg_struct = rb_struct_define(
|
2294
|
+
"InitMsg", "num_ostreams", "max_instreams", "max_attempts", "max_init_timeout", NULL
|
1623
2295
|
);
|
1624
2296
|
|
1625
2297
|
rb_define_method(cSocket, "initialize", rsctp_init, -1);
|
1626
2298
|
|
2299
|
+
rb_define_method(cSocket, "autoclose=", rsctp_set_autoclose, 1);
|
1627
2300
|
rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
|
1628
2301
|
rb_define_method(cSocket, "close", rsctp_close, 0);
|
1629
2302
|
rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
|
2303
|
+
rb_define_method(cSocket, "delete_shared_key", rsctp_delete_shared_key, -1);
|
2304
|
+
rb_define_method(cSocket, "disable_fragments=", rsctp_disable_fragments, 1);
|
2305
|
+
rb_define_method(cSocket, "enable_auth_support", rsctp_enable_auth_support, -1);
|
1630
2306
|
rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
|
1631
2307
|
rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
|
1632
|
-
rb_define_method(cSocket, "
|
2308
|
+
rb_define_method(cSocket, "get_active_shared_key", rsctp_get_active_shared_key, -1);
|
2309
|
+
rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
|
2310
|
+
rb_define_method(cSocket, "get_autoclose", rsctp_get_autoclose, 0);
|
1633
2311
|
rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
|
2312
|
+
rb_define_method(cSocket, "get_initmsg", rsctp_get_init_msg, 0);
|
2313
|
+
rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
|
1634
2314
|
rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
|
1635
|
-
rb_define_method(cSocket, "
|
2315
|
+
rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
|
1636
2316
|
rb_define_method(cSocket, "get_subscriptions", rsctp_get_subscriptions, 0);
|
1637
|
-
rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
|
1638
2317
|
rb_define_method(cSocket, "listen", rsctp_listen, -1);
|
2318
|
+
rb_define_method(cSocket, "map_ipv4=", rsctp_map_ipv4, 1);
|
2319
|
+
rb_define_method(cSocket, "nodelay?", rsctp_get_nodelay, 0);
|
2320
|
+
rb_define_method(cSocket, "nodelay=", rsctp_set_nodelay, 1);
|
1639
2321
|
rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
|
1640
2322
|
rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
|
1641
2323
|
rb_define_method(cSocket, "send", rsctp_send, 1);
|
@@ -1649,7 +2331,10 @@ void Init_socket(void){
|
|
1649
2331
|
#endif
|
1650
2332
|
|
1651
2333
|
rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
|
2334
|
+
rb_define_method(cSocket, "set_active_shared_key", rsctp_set_active_shared_key, -1);
|
1652
2335
|
rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
|
2336
|
+
//rb_define_method(cSocket, "set_retransmission_info", rsctp_set_retransmission_info, -1);
|
2337
|
+
rb_define_method(cSocket, "set_shared_key", rsctp_set_shared_key, -1);
|
1653
2338
|
rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
|
1654
2339
|
rb_define_method(cSocket, "subscribe", rsctp_subscribe, 1);
|
1655
2340
|
|
@@ -1659,8 +2344,8 @@ void Init_socket(void){
|
|
1659
2344
|
rb_define_attr(cSocket, "association_id", 1, 1);
|
1660
2345
|
rb_define_attr(cSocket, "port", 1, 1);
|
1661
2346
|
|
1662
|
-
/* 0.1.
|
1663
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.
|
2347
|
+
/* 0.1.2: The version of this library */
|
2348
|
+
rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.2"));
|
1664
2349
|
|
1665
2350
|
/* send flags */
|
1666
2351
|
|
@@ -1683,7 +2368,9 @@ void Init_socket(void){
|
|
1683
2368
|
|
1684
2369
|
// ASSOCIATION STATES //
|
1685
2370
|
|
2371
|
+
#ifdef HAVE_SCTP_EMPTY
|
1686
2372
|
rb_define_const(cSocket, "SCTP_EMPTY", INT2NUM(SCTP_EMPTY));
|
2373
|
+
#endif
|
1687
2374
|
rb_define_const(cSocket, "SCTP_CLOSED", INT2NUM(SCTP_CLOSED));
|
1688
2375
|
rb_define_const(cSocket, "SCTP_COOKIE_WAIT", INT2NUM(SCTP_COOKIE_WAIT));
|
1689
2376
|
rb_define_const(cSocket, "SCTP_COOKIE_ECHOED", INT2NUM(SCTP_COOKIE_ECHOED));
|