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.
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
- * Bind a subset of IP addresses associated with the host system on the
110
- * given port, or a port assigned by the operating system if none is provided.
333
+ * call-seq:
334
+ * SCTP::Socket#bindx(options)
111
335
  *
112
- * Note that you can both add or remove an address to or from the socket
113
- * using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
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
- * Example:
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
- * socket = SCTP::Socket.new
343
+ * Example:
119
344
  *
120
- * # Bind 2 addresses
121
- * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
345
+ * socket = SCTP::Socket.new
122
346
  *
123
- * # Remove 1 later
124
- * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
347
+ * # Bind 2 addresses
348
+ * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
125
349
  *
126
- * If no addresses are specified, then it will bind to all available interfaces. If
127
- * no port is specified, then one will be assigned by the host.
350
+ * # Remove 1 later
351
+ * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
128
352
  *
129
- * Returns the port that it was bound to.
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
- * Return an array of all addresses of a peer of the current socket
272
- * and association number.
515
+ * call-seq:
516
+ * SCTP::Socket#getpeernames
273
517
  *
274
- * You may optionally pass a assocation fileno and association ID. Typically
275
- * this information would come from the peeloff method.
518
+ * Return an array of all addresses of a peer of the current socket
519
+ * and association number.
276
520
  *
277
- * Example:
521
+ * You may optionally pass a assocation fileno and association ID. Typically
522
+ * this information would come from the peeloff method.
278
523
  *
279
- * socket = SCTP::Socket.new
280
- * # ...
281
- * p socket.getpeernames
524
+ * Example:
282
525
  *
283
- * info = socket.recvmsg
284
- * association_fileno = socket.peeloff(info.association_id)
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
- * p socket.getpeernames(association_fileno, info.association_id)
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 addresses does not work, and info_type is not yet supported.
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 sctp_sndinfo info;
410
- int i, fileno, num_bytes, size, num_ip;
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(&info, sizeof(info));
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(struct sockaddr_in) * num_ip);
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
- info.snd_flags = SCTP_UNORDERED;
443
- info.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
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 = NUM2INT(rb_iv_get(self, "@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->sin_family = NUM2INT(rb_iv_get(self, "@domain"));
459
- addrs->sin_port = htons(port);
460
- addrs->sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
461
- addrs += sizeof(struct sockaddr_in);
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
- &info,
478
- sizeof(info),
479
- SCTP_SENDV_SNDINFO,
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 INT2NUM(num_bytes);
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, bytes, on;
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 INT2NUM(num_bytes);
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, num_ip, port;
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
- num_bytes = sctp_sendmsg(
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 INT2NUM(num_bytes);
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, bytes, fileno;
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
- uint32_t i;
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(v_sctp_event_subscribe_struct,
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
- (events.sctp_stream_reset_event ? Qtrue : Qfalse),
1498
- (events.sctp_assoc_reset_event ? Qtrue : Qfalse),
1499
- (events.sctp_stream_change_event ? Qtrue : Qfalse),
1500
- (events.sctp_send_failure_event_event ? Qtrue : Qfalse)
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", NULL
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, "get_status", rsctp_get_status, 0);
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, "get_association_info", rsctp_get_association_info, 0);
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.0: The version of this library */
1663
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.0"));
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));