sctp-socket 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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));
|