sctp-socket 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/sctp/socket.c CHANGED
@@ -25,6 +25,7 @@ VALUE v_sctp_event_subscribe_struct;
25
25
  VALUE v_sctp_receive_info_struct;
26
26
  VALUE v_sctp_peer_addr_params_struct;
27
27
  VALUE v_sender_dry_event_struct;
28
+ VALUE v_sctp_initmsg_struct;
28
29
 
29
30
  #if !defined(IOV_MAX)
30
31
  #if defined(_SC_IOV_MAX)
@@ -63,7 +64,195 @@ VALUE rb_hash_aref2(VALUE v_hash, const char* key){
63
64
  return v_val;
64
65
  }
65
66
 
67
+ VALUE get_notification_info(char* buffer){
68
+ uint32_t i;
69
+ char str[16];
70
+ union sctp_notification* snp;
71
+ VALUE v_notification = Qnil;
72
+ VALUE v_str = Qnil;
73
+ VALUE* v_temp;
74
+
75
+ snp = (union sctp_notification*)buffer;
76
+
77
+ switch(snp->sn_header.sn_type){
78
+ case SCTP_ASSOC_CHANGE:
79
+ switch(snp->sn_assoc_change.sac_state){
80
+ case SCTP_COMM_LOST:
81
+ v_str = rb_str_new2("comm lost");
82
+ break;
83
+ case SCTP_COMM_UP:
84
+ v_str = rb_str_new2("comm up");
85
+ break;
86
+ case SCTP_RESTART:
87
+ v_str = rb_str_new2("restart");
88
+ break;
89
+ case SCTP_SHUTDOWN_COMP:
90
+ v_str = rb_str_new2("shutdown complete");
91
+ break;
92
+ case SCTP_CANT_STR_ASSOC:
93
+ v_str = rb_str_new2("association setup failed");
94
+ break;
95
+ default:
96
+ v_str = rb_str_new2("unknown");
97
+ }
98
+
99
+ v_notification = rb_struct_new(v_assoc_change_struct,
100
+ UINT2NUM(snp->sn_assoc_change.sac_type),
101
+ UINT2NUM(snp->sn_assoc_change.sac_length),
102
+ UINT2NUM(snp->sn_assoc_change.sac_state),
103
+ UINT2NUM(snp->sn_assoc_change.sac_error),
104
+ UINT2NUM(snp->sn_assoc_change.sac_outbound_streams),
105
+ UINT2NUM(snp->sn_assoc_change.sac_inbound_streams),
106
+ UINT2NUM(snp->sn_assoc_change.sac_assoc_id),
107
+ v_str
108
+ );
109
+ break;
110
+ case SCTP_PEER_ADDR_CHANGE:
111
+ switch(snp->sn_paddr_change.spc_state){
112
+ case SCTP_ADDR_AVAILABLE:
113
+ v_str = rb_str_new2("available");
114
+ break;
115
+ case SCTP_ADDR_UNREACHABLE:
116
+ v_str = rb_str_new2("unreachable");
117
+ break;
118
+ case SCTP_ADDR_REMOVED:
119
+ v_str = rb_str_new2("removed from association");
120
+ break;
121
+ case SCTP_ADDR_ADDED:
122
+ v_str = rb_str_new2("added to association");
123
+ break;
124
+ case SCTP_ADDR_MADE_PRIM:
125
+ v_str = rb_str_new2("primary destination");
126
+ break;
127
+ default:
128
+ v_str = rb_str_new2("unknown");
129
+ }
130
+
131
+ inet_ntop(
132
+ ((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
133
+ &(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
134
+ str,
135
+ sizeof(str)
136
+ );
137
+
138
+ v_notification = rb_struct_new(v_peeraddr_change_struct,
139
+ UINT2NUM(snp->sn_paddr_change.spc_type),
140
+ UINT2NUM(snp->sn_paddr_change.spc_length),
141
+ rb_str_new2(str),
142
+ UINT2NUM(snp->sn_paddr_change.spc_state),
143
+ UINT2NUM(snp->sn_paddr_change.spc_error),
144
+ UINT2NUM(snp->sn_paddr_change.spc_assoc_id),
145
+ v_str
146
+ );
147
+ break;
148
+ case SCTP_REMOTE_ERROR:
149
+ v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
150
+
151
+ for(i = 0; i < snp->sn_remote_error.sre_length; i++){
152
+ v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
153
+ }
154
+
155
+ v_notification = rb_struct_new(v_remote_error_struct,
156
+ UINT2NUM(snp->sn_remote_error.sre_type),
157
+ UINT2NUM(snp->sn_remote_error.sre_flags),
158
+ UINT2NUM(snp->sn_remote_error.sre_length),
159
+ UINT2NUM(snp->sn_remote_error.sre_error),
160
+ UINT2NUM(snp->sn_remote_error.sre_assoc_id),
161
+ rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
162
+ );
163
+ break;
164
+ #ifdef SCTP_SEND_FAILED_EVENT
165
+ case SCTP_SEND_FAILED_EVENT:
166
+ v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
167
+
168
+ for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
169
+ v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
170
+ }
171
+
172
+ v_notification = rb_struct_new(v_send_failed_event_struct,
173
+ UINT2NUM(snp->sn_send_failed_event.ssf_type),
174
+ UINT2NUM(snp->sn_send_failed_event.ssf_length),
175
+ UINT2NUM(snp->sn_send_failed_event.ssf_error),
176
+ rb_struct_new(v_sndinfo_struct,
177
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
178
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
179
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
180
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
181
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
182
+ ),
183
+ UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
184
+ rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
185
+ );
186
+ break;
187
+ #else
188
+ case SCTP_SEND_FAILED:
189
+ v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
190
+
191
+ for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
192
+ v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
193
+ }
194
+
195
+ v_notification = rb_struct_new(v_send_failed_event_struct,
196
+ UINT2NUM(snp->sn_send_failed.ssf_type),
197
+ UINT2NUM(snp->sn_send_failed.ssf_length),
198
+ UINT2NUM(snp->sn_send_failed.ssf_error),
199
+ Qnil,
200
+ UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
201
+ rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
202
+ );
203
+ break;
204
+ #endif
205
+ case SCTP_SHUTDOWN_EVENT:
206
+ v_notification = rb_struct_new(v_shutdown_event_struct,
207
+ UINT2NUM(snp->sn_shutdown_event.sse_type),
208
+ UINT2NUM(snp->sn_shutdown_event.sse_length),
209
+ UINT2NUM(snp->sn_shutdown_event.sse_assoc_id)
210
+ );
211
+ break;
212
+ case SCTP_ADAPTATION_INDICATION:
213
+ v_notification = rb_struct_new(v_adaptation_event_struct,
214
+ UINT2NUM(snp->sn_adaptation_event.sai_type),
215
+ UINT2NUM(snp->sn_adaptation_event.sai_length),
216
+ UINT2NUM(snp->sn_adaptation_event.sai_adaptation_ind),
217
+ UINT2NUM(snp->sn_adaptation_event.sai_assoc_id)
218
+ );
219
+ break;
220
+ case SCTP_PARTIAL_DELIVERY_EVENT:
221
+ v_notification = rb_struct_new(v_partial_delivery_event_struct,
222
+ UINT2NUM(snp->sn_pdapi_event.pdapi_type),
223
+ UINT2NUM(snp->sn_pdapi_event.pdapi_length),
224
+ UINT2NUM(snp->sn_pdapi_event.pdapi_indication),
225
+ UINT2NUM(snp->sn_pdapi_event.pdapi_stream),
226
+ UINT2NUM(snp->sn_pdapi_event.pdapi_seq),
227
+ UINT2NUM(snp->sn_pdapi_event.pdapi_assoc_id)
228
+ );
229
+ break;
230
+ case SCTP_AUTHENTICATION_EVENT:
231
+ v_notification = rb_struct_new(v_auth_event_struct,
232
+ UINT2NUM(snp->sn_authkey_event.auth_type),
233
+ UINT2NUM(snp->sn_authkey_event.auth_length),
234
+ UINT2NUM(snp->sn_authkey_event.auth_keynumber),
235
+ UINT2NUM(snp->sn_authkey_event.auth_indication),
236
+ UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
237
+ );
238
+ break;
239
+ case SCTP_SENDER_DRY_EVENT:
240
+ v_notification = rb_struct_new(v_sender_dry_event_struct,
241
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
242
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
243
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
244
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
245
+ );
246
+ break;
247
+ }
248
+
249
+ return v_notification;
250
+ }
251
+
66
252
  /*
253
+ * call-seq:
254
+ * SCTP::Socket.new(domain = Socket::AF_INET, type = Socket::SOCK_STREAM)
255
+ *
67
256
  * Create and return a new SCTP::Socket instance. You may optionally pass in
68
257
  * a domain (aka family) value and socket type. By default these are AF_INET
69
258
  * and SOCK_SEQPACKET, respectively.
@@ -106,27 +295,30 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
106
295
  }
107
296
 
108
297
  /*
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.
298
+ * call-seq:
299
+ * SCTP::Socket#bindx(options)
111
300
  *
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.
301
+ * Bind a subset of IP addresses associated with the host system on the
302
+ * given port, or a port assigned by the operating system if none is provided.
115
303
  *
116
- * Example:
304
+ * Note that you can both add or remove an address to or from the socket
305
+ * using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
306
+ * respectively.
117
307
  *
118
- * socket = SCTP::Socket.new
308
+ * Example:
309
+ *
310
+ * socket = SCTP::Socket.new
119
311
  *
120
- * # Bind 2 addresses
121
- * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
312
+ * # Bind 2 addresses
313
+ * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
122
314
  *
123
- * # Remove 1 later
124
- * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
315
+ * # Remove 1 later
316
+ * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
125
317
  *
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.
318
+ * If no addresses are specified, then it will bind to all available interfaces. If
319
+ * no port is specified, then one will be assigned by the host.
128
320
  *
129
- * Returns the port that it was bound to.
321
+ * Returns the port that it was bound to.
130
322
  */
131
323
  static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
132
324
  struct sockaddr_in addrs[8];
@@ -196,6 +388,9 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
196
388
  }
197
389
 
198
390
  /*
391
+ * call-seq:
392
+ * SCTP::Socket#connectx(options)
393
+ *
199
394
  * Connect the socket to a multihomed peer via the provided array of addresses
200
395
  * using the domain specified in the constructor. You must also specify the port.
201
396
  *
@@ -204,7 +399,9 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
204
399
  * socket = SCTP::Socket.new
205
400
  * socket.connectx(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
206
401
  *
207
- * Note that this will also set/update the object's association_id.
402
+ * Note that this will also set/update the object's association_id. Also note that
403
+ * this method is not strictly necessary on the client side, since the various send
404
+ * methods will automatically establish associations.
208
405
  */
209
406
  static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
210
407
  struct sockaddr_in addrs[8];
@@ -251,6 +448,9 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
251
448
  }
252
449
 
253
450
  /*
451
+ * call-seq:
452
+ * SCTP::Socket#close
453
+ *
254
454
  * Close the socket. You should always do this.
255
455
  *
256
456
  * Example:
@@ -268,22 +468,25 @@ static VALUE rsctp_close(VALUE self){
268
468
  }
269
469
 
270
470
  /*
271
- * Return an array of all addresses of a peer of the current socket
272
- * and association number.
471
+ * call-seq:
472
+ * SCTP::Socket#getpeernames
273
473
  *
274
- * You may optionally pass a assocation fileno and association ID. Typically
275
- * this information would come from the peeloff method.
474
+ * Return an array of all addresses of a peer of the current socket
475
+ * and association number.
276
476
  *
277
- * Example:
477
+ * You may optionally pass a assocation fileno and association ID. Typically
478
+ * this information would come from the peeloff method.
278
479
  *
279
- * socket = SCTP::Socket.new
280
- * # ...
281
- * p socket.getpeernames
480
+ * Example:
282
481
  *
283
- * info = socket.recvmsg
284
- * association_fileno = socket.peeloff(info.association_id)
482
+ * socket = SCTP::Socket.new
483
+ * # ...
484
+ * p socket.getpeernames
485
+ *
486
+ * info = socket.recvmsg
487
+ * association_fileno = socket.peeloff(info.association_id)
285
488
  *
286
- * p socket.getpeernames(association_fileno, info.association_id)
489
+ * p socket.getpeernames(association_fileno, info.association_id)
287
490
  */
288
491
  static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
289
492
  sctp_assoc_t assoc_id;
@@ -326,6 +529,9 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
326
529
  }
327
530
 
328
531
  /*
532
+ * call-seq:
533
+ * SCTP::Socket#getlocalnames
534
+ *
329
535
  * Return an array of local addresses that are part of the association.
330
536
  *
331
537
  * Example:
@@ -381,6 +587,9 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
381
587
 
382
588
  #ifdef HAVE_SCTP_SENDV
383
589
  /*
590
+ * call-seq:
591
+ * SCTP::Socket#sendv(options)
592
+ *
384
593
  * Transmit a message to an SCTP endpoint using a gather-write. The following
385
594
  * hash of options is permitted:
386
595
  *
@@ -392,13 +601,14 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
392
601
  *
393
602
  * socket = SCTP::Socket.new
394
603
  *
604
+ * # You can specify addresses here or in an earlier connectx call.
395
605
  * socket.sendv
396
606
  * :message => ['Hello ', 'World.'],
397
607
  * :addresses => ['10.0.5.4', '10.0.6.4'],
398
608
  * :info_type => SCTP::Socket:::SCTP_SENDV_SNDINFO
399
609
  * )
400
610
  *
401
- * CAVEAT: Currently addresses does not work, and info_type is not yet supported.
611
+ * CAVEAT: Currently info_type is not yet supported.
402
612
  *
403
613
  * Returns the number of bytes sent.
404
614
  */
@@ -406,13 +616,13 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
406
616
  VALUE v_msg, v_message, v_addresses;
407
617
  struct iovec iov[IOV_MAX];
408
618
  struct sockaddr_in* addrs;
409
- struct sctp_sndinfo info;
619
+ struct sctp_sendv_spa spa;
410
620
  int i, fileno, num_bytes, size, num_ip;
411
621
 
412
622
  Check_Type(v_options, T_HASH);
413
623
 
414
624
  bzero(&iov, sizeof(iov));
415
- bzero(&info, sizeof(info));
625
+ bzero(&spa, sizeof(spa));
416
626
 
417
627
  v_message = rb_hash_aref2(v_options, "message");
418
628
  v_addresses = rb_hash_aref2(v_options, "addresses");
@@ -423,7 +633,7 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
423
633
  if(!NIL_P(v_addresses)){
424
634
  Check_Type(v_addresses, T_ARRAY);
425
635
  num_ip = RARRAY_LEN(v_addresses);
426
- addrs = (struct sockaddr_in*)alloca(sizeof(struct sockaddr_in) * num_ip);
636
+ addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(*addrs));
427
637
  }
428
638
  else{
429
639
  addrs = NULL;
@@ -439,26 +649,28 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
439
649
  if(size > IOV_MAX)
440
650
  rb_raise(rb_eArgError, "Array size is greater than IOV_MAX");
441
651
 
442
- info.snd_flags = SCTP_UNORDERED;
443
- info.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
652
+ // TODO: Make this configurable
653
+ spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
654
+ spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
444
655
 
445
656
  if(!NIL_P(v_addresses)){
446
- int i, port;
657
+ int i, port, domain;
447
658
  VALUE v_address, v_port;
448
659
 
449
- v_port = NUM2INT(rb_iv_get(self, "@port"));
660
+ v_port = rb_iv_get(self, "@port");
450
661
 
451
662
  if(NIL_P(v_port))
452
663
  port = 0;
453
664
  else
454
665
  port = NUM2INT(v_port);
455
666
 
667
+ domain = NUM2INT(rb_iv_get(self, "@domain"));
668
+
456
669
  for(i = 0; i < num_ip; i++){
457
670
  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);
671
+ addrs[i].sin_family = domain;
672
+ addrs[i].sin_port = htons(port);
673
+ addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
462
674
  }
463
675
  }
464
676
 
@@ -474,9 +686,9 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
474
686
  size,
475
687
  (struct sockaddr*)addrs,
476
688
  num_ip,
477
- &info,
478
- sizeof(info),
479
- SCTP_SENDV_SNDINFO,
689
+ &spa,
690
+ sizeof(spa),
691
+ SCTP_SENDV_SPA,
480
692
  0
481
693
  );
482
694
 
@@ -556,6 +768,9 @@ static VALUE rsctp_recvv(int argc, VALUE* argv, VALUE self){
556
768
  #endif
557
769
 
558
770
  /*
771
+ * call-seq:
772
+ * SCTP::Socket.send(options)
773
+ *
559
774
  * Send a message on an already-connected socket to a specific association.
560
775
  *
561
776
  * Example:
@@ -649,6 +864,9 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
649
864
  }
650
865
 
651
866
  /*
867
+ * call-seq:
868
+ * SCTP::Socket#sendmsg(options)
869
+ *
652
870
  * Transmit a message to an SCTP endpoint. The following hash of options
653
871
  * is permitted:
654
872
  *
@@ -772,6 +990,9 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
772
990
  }
773
991
 
774
992
  /*
993
+ * call-seq:
994
+ * SCTP::Socket#recvmsg(flags=0)
995
+ *
775
996
  * Receive a message from another SCTP endpoint.
776
997
  *
777
998
  * Example:
@@ -827,187 +1048,8 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
827
1048
 
828
1049
  v_notification = Qnil;
829
1050
 
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
- }
1051
+ if(flags & MSG_NOTIFICATION)
1052
+ v_notification = get_notification_info(buffer);
1011
1053
 
1012
1054
  if(NIL_P(v_notification))
1013
1055
  v_message = rb_str_new(buffer, bytes);
@@ -1028,6 +1070,9 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
1028
1070
  }
1029
1071
 
1030
1072
  /*
1073
+ * call-seq:
1074
+ * SCTP::Socket#set_initmsg(options)
1075
+ *
1031
1076
  * Set the initial parameters used by the socket when sending out the INIT message.
1032
1077
  *
1033
1078
  * Example:
@@ -1077,6 +1122,9 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
1077
1122
  }
1078
1123
 
1079
1124
  /*
1125
+ * call-seq:
1126
+ * SCTP::Socket#subscribe(options)
1127
+ *
1080
1128
  * Subscribe to various notification type events, which will generate additional
1081
1129
  * data that the socket may receive. The possible notification type events are
1082
1130
  * as follows:
@@ -1161,6 +1209,9 @@ static VALUE rsctp_subscribe(VALUE self, VALUE v_options){
1161
1209
  }
1162
1210
 
1163
1211
  /*
1212
+ * call-seq:
1213
+ * SCTP::Socket#listen(backlog=128)
1214
+ *
1164
1215
  * Marks the socket referred to by sockfd as a passive socket, i.e. a socket that
1165
1216
  * will be used to accept incoming connection requests.
1166
1217
  *
@@ -1204,6 +1255,9 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
1204
1255
  }
1205
1256
 
1206
1257
  /*
1258
+ * call-seq:
1259
+ * SCTP::Socket#peeloff(association_id)
1260
+ *
1207
1261
  * Extracts an association contained by a one-to-many socket connection into
1208
1262
  * a one-to-one style socket. Returns the socket descriptor (fileno).
1209
1263
  *
@@ -1234,6 +1288,9 @@ static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
1234
1288
  }
1235
1289
 
1236
1290
  /*
1291
+ * call-seq:
1292
+ * SCTP::Socket#get_default_send_params
1293
+ *
1237
1294
  * Returns the default set of parameters that a call to the sendto function
1238
1295
  * uses on this association. This is a struct that contains the following
1239
1296
  * members:
@@ -1278,6 +1335,9 @@ static VALUE rsctp_get_default_send_params(VALUE self){
1278
1335
  }
1279
1336
 
1280
1337
  /*
1338
+ * call-seq:
1339
+ * SCTP::Socket#get_association_info
1340
+ *
1281
1341
  * Returns the association specific parameters. This is a struct
1282
1342
  * that contains the following members:
1283
1343
  *
@@ -1317,6 +1377,9 @@ static VALUE rsctp_get_association_info(VALUE self){
1317
1377
  }
1318
1378
 
1319
1379
  /*
1380
+ * call-seq:
1381
+ * SCTP::Socket#shutdown
1382
+ *
1320
1383
  * Shuts down socket send and receive operations.
1321
1384
  *
1322
1385
  * Optionally accepts an argument that specifieds the type of shutdown.
@@ -1351,6 +1414,9 @@ static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
1351
1414
  }
1352
1415
 
1353
1416
  /*
1417
+ * call-seq:
1418
+ * SCTP::Socket#get_retransmission_info
1419
+ *
1354
1420
  * Returns the protocol parameters that are used to initialize and bind the
1355
1421
  * retransmission timeout (RTO) tunable. This is a struct with the following
1356
1422
  * members:
@@ -1385,6 +1451,9 @@ static VALUE rsctp_get_retransmission_info(VALUE self){
1385
1451
  }
1386
1452
 
1387
1453
  /*
1454
+ * call-seq:
1455
+ * SCTP::Socket#get_status
1456
+ *
1388
1457
  * Get the status of a connected socket.
1389
1458
  *
1390
1459
  * Example:
@@ -1449,6 +1518,9 @@ static VALUE rsctp_get_status(VALUE self){
1449
1518
  }
1450
1519
 
1451
1520
  /*
1521
+ * call-seq:
1522
+ * SCTP::Socket#get_subscriptions
1523
+ *
1452
1524
  * Returns a struct of events detailing which events have been
1453
1525
  * subscribed to by the socket. The struct contains the following
1454
1526
  * members:
@@ -1501,6 +1573,27 @@ static VALUE rsctp_get_subscriptions(VALUE self){
1501
1573
  );
1502
1574
  }
1503
1575
 
1576
+ /*
1577
+ * call-seq:
1578
+ * SCTP::Socket#get_peer_address_params
1579
+ *
1580
+ * Applications can enable or disable heartbeats for any peer address of
1581
+ * an association, modify an address's heartbeat interval, force a
1582
+ * heartbeat to be sent immediately, and adjust the address's maximum
1583
+ * number of retransmissions sent before an address is considered
1584
+ * unreachable.
1585
+ *
1586
+ * This method returns a struct that contains this information. It contains
1587
+ * the following struct members.
1588
+ *
1589
+ * * association_id
1590
+ * * address
1591
+ * * heartbeat_interval
1592
+ * * max_retransmission_count
1593
+ * * path_mtu
1594
+ * * flags
1595
+ * * ipv6_flowlabel
1596
+ */
1504
1597
  static VALUE rsctp_get_peer_address_params(VALUE self){
1505
1598
  int fileno;
1506
1599
  char str[16];
@@ -1525,10 +1618,447 @@ static VALUE rsctp_get_peer_address_params(VALUE self){
1525
1618
  INT2NUM(paddr.spp_assoc_id),
1526
1619
  rb_str_new2(str),
1527
1620
  INT2NUM(paddr.spp_hbinterval),
1528
- INT2NUM(paddr.spp_pathmaxrxt)
1621
+ INT2NUM(paddr.spp_pathmaxrxt),
1622
+ INT2NUM(paddr.spp_pathmtu),
1623
+ INT2NUM(paddr.spp_flags),
1624
+ INT2NUM(paddr.spp_ipv6_flowlabel)
1625
+ );
1626
+ }
1627
+
1628
+ /*
1629
+ * call-seq:
1630
+ * SCTP::Socket#get_init_msg
1631
+ *
1632
+ * Returns a structure that contains various initialization parameters.
1633
+ *
1634
+ * * num_ostreams: A number representing the number of streams that the
1635
+ * application wishes to be able to send to.
1636
+ *
1637
+ * * max_instreams: The maximum number of inbound streams the application
1638
+ * is prepared to support.
1639
+ *
1640
+ * * max_attempts: The number of attempts the SCTP endpoint should make at
1641
+ * resending the INIT.
1642
+ *
1643
+ * * max_init_timeout: This value represents the largest Timeout or RTO value
1644
+ * (in milliseconds) to use in attempting an INIT.
1645
+ */
1646
+ static VALUE rsctp_get_init_msg(VALUE self){
1647
+ int fileno;
1648
+ socklen_t size;
1649
+ sctp_assoc_t assoc_id;
1650
+ struct sctp_initmsg initmsg;
1651
+
1652
+ bzero(&initmsg, sizeof(initmsg));
1653
+
1654
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1655
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1656
+ size = sizeof(struct sctp_initmsg);
1657
+
1658
+ if(sctp_opt_info(fileno, assoc_id, SCTP_INITMSG, (void*)&initmsg, &size) < 0)
1659
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1660
+
1661
+ return rb_struct_new(
1662
+ v_sctp_initmsg_struct,
1663
+ INT2NUM(initmsg.sinit_num_ostreams),
1664
+ INT2NUM(initmsg.sinit_max_instreams),
1665
+ INT2NUM(initmsg.sinit_max_attempts),
1666
+ INT2NUM(initmsg.sinit_max_init_timeo)
1529
1667
  );
1530
1668
  }
1531
1669
 
1670
+ /*
1671
+ * call-seq:
1672
+ * SCTP::Socket#nodelay?
1673
+ *
1674
+ * Returns whether or not the nodelay option has been set.
1675
+ */
1676
+ static VALUE rsctp_get_nodelay(VALUE self){
1677
+ int fileno;
1678
+ socklen_t size;
1679
+ sctp_assoc_t assoc_id;
1680
+ int value;
1681
+
1682
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1683
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1684
+ size = sizeof(int);
1685
+
1686
+ if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
1687
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1688
+
1689
+ if(value)
1690
+ return Qtrue;
1691
+ else
1692
+ return Qfalse;
1693
+ }
1694
+
1695
+ /*
1696
+ * call-seq:
1697
+ * SCTP::Socket#nodelay=(bool)
1698
+ *
1699
+ * Turn on/off any Nagle-like algorithm. This means that packets are generally
1700
+ * sent as soon as possible and no unnecessary delays are introduced, at the
1701
+ * cost of more packets in the network.
1702
+ */
1703
+ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
1704
+ int fileno;
1705
+ socklen_t size;
1706
+ sctp_assoc_t assoc_id;
1707
+ int value;
1708
+
1709
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1710
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1711
+ size = sizeof(int);
1712
+
1713
+ if(NIL_P(v_bool) || v_bool == Qfalse)
1714
+ value = 0;
1715
+ else
1716
+ value = 1;
1717
+
1718
+ if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
1719
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1720
+
1721
+ if(value)
1722
+ return Qtrue;
1723
+ else
1724
+ return Qfalse;
1725
+ }
1726
+
1727
+ /*
1728
+ * call-seq:
1729
+ * SCTP::Socket#autoclose
1730
+ *
1731
+ * Returns the number of seconds before socket associations automatically
1732
+ * shut down.
1733
+ */
1734
+ static VALUE rsctp_get_autoclose(VALUE self){
1735
+ int fileno;
1736
+ socklen_t size;
1737
+ sctp_assoc_t assoc_id;
1738
+ int value;
1739
+
1740
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1741
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1742
+ size = sizeof(int);
1743
+
1744
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
1745
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1746
+
1747
+ return INT2NUM(value);
1748
+ }
1749
+
1750
+ /*
1751
+ * call-seq:
1752
+ * SCTP::Socket#autoclose=(seconds=0)
1753
+ *
1754
+ * When set it will cause associations that are idle for more than the specified
1755
+ * number of seconds to automatically close using the graceful shutdown
1756
+ * procedure. An association being idle is defined as an association that has
1757
+ * NOT sent or received user data.
1758
+ *
1759
+ * The special value of 0 indicates that no automatic close of any associations
1760
+ * should be performed, this is the default value. The option expects an integer
1761
+ * defining the number of seconds of idle time before an association is closed.
1762
+ *
1763
+ * An application using this option should enable receiving the association
1764
+ * change notification. This is the only mechanism an application is informed
1765
+ * about the closing of an association. After an association is closed, the
1766
+ * association ID assigned to it can be reused. An application should be aware
1767
+ * of this to avoid the possible problem of sending data to an incorrect peer
1768
+ * end point.
1769
+ *
1770
+ * This socket option is applicable to the one-to-many style socket only.
1771
+ */
1772
+ static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
1773
+ int fileno;
1774
+ socklen_t size;
1775
+ sctp_assoc_t assoc_id;
1776
+ int value;
1777
+
1778
+ value = NUM2INT(v_seconds);
1779
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1780
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1781
+ size = sizeof(int);
1782
+
1783
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
1784
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1785
+
1786
+ return v_seconds;
1787
+ }
1788
+
1789
+ /*
1790
+ * call-seq:
1791
+ * SCTP::Socket#enable_auth_support(association_id=nil)
1792
+ *
1793
+ * Enables auth for future associations.
1794
+ */
1795
+ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
1796
+ int fileno;
1797
+ socklen_t size;
1798
+ sctp_assoc_t assoc_id;
1799
+ struct sctp_assoc_value assoc_value;
1800
+ VALUE v_assoc_id;
1801
+
1802
+ rb_scan_args(argc, argv, "01", &v_assoc_id);
1803
+
1804
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1805
+ size = sizeof(struct sctp_assoc_value);
1806
+
1807
+ if(NIL_P(v_assoc_id))
1808
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1809
+ else
1810
+ assoc_id = NUM2INT(v_assoc_id);
1811
+
1812
+ assoc_value.assoc_id = assoc_id;
1813
+ assoc_value.assoc_value = 1;
1814
+
1815
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, &size) < 0)
1816
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1817
+
1818
+ return self;
1819
+ }
1820
+
1821
+ /*
1822
+ * call-seq:
1823
+ * SCTP::Socket#set_shared_key(key, keynum, association_id=nil)
1824
+ *
1825
+ * This option will set a shared secret key which is used to build an
1826
+ * association shared key.
1827
+ *
1828
+ * The +key+ parameter should be a string (converted to an array of bytes
1829
+ * internally) that is to be used by the endpoint (or association) as the
1830
+ * shared secret key. If an empty string is used, then a null key is set.
1831
+ *
1832
+ * The +keynum+ parameter is the shared key identifier by which the
1833
+ * application will refer to this key. If a key of the specified index already
1834
+ * exists, then this new key will replace the old existing key. Note that
1835
+ * shared key identifier '0' defaults to a null key.
1836
+ *
1837
+ * The +association_id+, if non-zero, indicates what association that the shared
1838
+ * key is being set upon. If this argument is zero, then the shared key is set
1839
+ * upon the endpoint and all future associations will use this key (if not
1840
+ * changed by subsequent calls). By default this is the result of the
1841
+ * SCTP::Socket#association_id method.
1842
+ *
1843
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
1844
+ * option will set a key on the association if the socket is connected,
1845
+ * otherwise this will set a key on the endpoint.
1846
+ */
1847
+ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
1848
+ int fileno, len;
1849
+ char* key;
1850
+ uint keynum;
1851
+ socklen_t size;
1852
+ sctp_assoc_t assoc_id;
1853
+ struct sctp_authkey* auth_key;
1854
+ VALUE v_key, v_keynumber, v_assoc_id;
1855
+
1856
+ rb_scan_args(argc, argv, "12", &v_key, &v_keynumber, &v_assoc_id);
1857
+
1858
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1859
+ key = StringValuePtr(v_key);
1860
+ len = strlen(key);
1861
+ unsigned char byte_array[len+1];
1862
+
1863
+ for(int i = 0; i < len; i++)
1864
+ byte_array[i] = key[i];
1865
+
1866
+ byte_array[len] = '\0';
1867
+
1868
+ auth_key = malloc(sizeof(auth_key) + sizeof(char[strlen(key)+1]));
1869
+ size = sizeof(auth_key);
1870
+
1871
+ if(NIL_P(v_assoc_id))
1872
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1873
+ else
1874
+ assoc_id = NUM2INT(v_assoc_id);
1875
+
1876
+ if(NIL_P(v_keynumber))
1877
+ keynum = 1;
1878
+ else
1879
+ keynum = NUM2INT(v_keynumber);
1880
+
1881
+ auth_key->sca_assoc_id = assoc_id;
1882
+ auth_key->sca_keynumber = keynum;
1883
+ auth_key->sca_keylength = strlen(key);
1884
+ memcpy(auth_key->sca_key, byte_array, sizeof(byte_array));
1885
+
1886
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_KEY, (void*)auth_key, &size) < 0)
1887
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1888
+
1889
+ return self;
1890
+ }
1891
+
1892
+ /*
1893
+ * call-seq:
1894
+ * SCTP::Socket#get_active_shared_key(keynum, association_id=nil)
1895
+ *
1896
+ * Gets the active shared key to be used to build the association shared key.
1897
+ */
1898
+ static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
1899
+ int fileno;
1900
+ socklen_t size;
1901
+ struct sctp_authkeyid authkey;
1902
+ sctp_assoc_t assoc_id;
1903
+ VALUE v_assoc_id, v_keynum;
1904
+ uint keynum;
1905
+
1906
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
1907
+
1908
+ bzero(&authkey, sizeof(authkey));
1909
+
1910
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1911
+ keynum = NUM2UINT(v_keynum);
1912
+
1913
+ if(NIL_P(v_assoc_id))
1914
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1915
+ else
1916
+ assoc_id = NUM2INT(v_assoc_id);
1917
+
1918
+ authkey.scact_assoc_id = assoc_id;
1919
+ authkey.scact_keynumber = keynum;
1920
+
1921
+ size = sizeof(struct sctp_authkeyid);
1922
+
1923
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
1924
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1925
+
1926
+ return INT2NUM(authkey.scact_keynumber);
1927
+ }
1928
+
1929
+ /*
1930
+ * call-seq:
1931
+ * SCTP::Socket#set_active_shared_key(keynum, association_id=nil)
1932
+ *
1933
+ * Sets the active shared key to be used to build the association shared key.
1934
+ *
1935
+ * Th +keynum+ parameter is the shared key identifier which the application is
1936
+ * requesting to become the active shared key to be used for sending
1937
+ * authenticated chunks. The key identifier MUST correspond to an existing
1938
+ * shared key. Note that shared key identifier '0' defaults to a null key.
1939
+ *
1940
+ * The association_idparameter, if non-zero, indicates what association that
1941
+ * the shared key identifier is being set active upon. If this element contains
1942
+ * zero, then the activation applies to the endpoint and all future
1943
+ * associations will use the specified shared key identifier.
1944
+ *
1945
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
1946
+ * option will set the active key on the association if the socket is connected,
1947
+ * otherwise this will set the default active key for the endpoint.
1948
+ *
1949
+ * By default, the association_id is the result of SCTP::Socket#association_id.
1950
+ */
1951
+ static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
1952
+ int fileno;
1953
+ socklen_t size;
1954
+ struct sctp_authkeyid authkey;
1955
+ sctp_assoc_t assoc_id;
1956
+ VALUE v_assoc_id, v_keynum;
1957
+ uint keynum;
1958
+
1959
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
1960
+
1961
+ keynum = NUM2UINT(v_keynum);
1962
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
1963
+
1964
+ if(NIL_P(v_assoc_id))
1965
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
1966
+ else
1967
+ assoc_id = NUM2INT(v_assoc_id);
1968
+
1969
+ authkey.scact_assoc_id = assoc_id;
1970
+ authkey.scact_keynumber = keynum;
1971
+ size = sizeof(struct sctp_authkeyid);
1972
+
1973
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
1974
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
1975
+
1976
+ return self;
1977
+ }
1978
+
1979
+ /*
1980
+ * call-seq:
1981
+ * SCTP::Socket#delete_shared_key(keynum, association_id=nil)
1982
+ *
1983
+ * Delete a shared secret key from use.
1984
+ *
1985
+ * The +keynum+ parameter is the shared key identifier which the application
1986
+ * is requesting to be deleted. The key identifier MUST correspond to an
1987
+ * existing shared key and MUST NOT be the current active key.
1988
+ *
1989
+ * If this parameter is zero, use of the null key identifier '0' is disabled
1990
+ * on the endpoint and/or association.
1991
+ *
1992
+ * The +association_id+ parameter, if non-zero, indicates what association that
1993
+ * the shared key identifier is being deleted from. By default this is the
1994
+ * association that's returned via SCTP::Socket#association_id.
1995
+ *
1996
+ * If set to zero, then the shared key is deleted from the endpoint and
1997
+ * and ALL associations will no longer use the specified shared key identifier
1998
+ * (unless otherwise set on the association using SCTP_AUTH_KEY).
1999
+ *
2000
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
2001
+ * option will delete the key from the association if the socket is connected,
2002
+ * otherwise this will delete the key from the endpoint.
2003
+ */
2004
+ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
2005
+ int fileno;
2006
+ socklen_t size;
2007
+ struct sctp_authkeyid authkey;
2008
+ sctp_assoc_t assoc_id;
2009
+ VALUE v_assoc_id, v_keynum;
2010
+ uint keynum;
2011
+
2012
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
2013
+
2014
+ bzero(&authkey, sizeof(authkey));
2015
+
2016
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2017
+ keynum = NUM2UINT(v_keynum);
2018
+
2019
+ if(NIL_P(v_assoc_id))
2020
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2021
+ else
2022
+ assoc_id = NUM2INT(v_assoc_id);
2023
+
2024
+ authkey.scact_assoc_id = assoc_id;
2025
+ authkey.scact_keynumber = keynum;
2026
+
2027
+ size = sizeof(struct sctp_authkeyid);
2028
+
2029
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_DELETE_KEY, (void*)&authkey, &size) < 0)
2030
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
2031
+
2032
+ return INT2NUM(authkey.scact_keynumber);
2033
+ }
2034
+
2035
+ /*
2036
+ * call-seq:
2037
+ * SCTP::Socket#map_ipv4=(bool)
2038
+ *
2039
+ * If set to true and the socket is type PF_INET6, then IPv4 addresses will be
2040
+ * mapped to V6 representation. If set to false (the default), then no mapping
2041
+ * will be done of V4 addresses and a user will receive both PF_INET6 and
2042
+ * PF_INET type addresses on the socket.
2043
+ */
2044
+ static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
2045
+ int fileno, boolean;
2046
+ sctp_assoc_t assoc_id;
2047
+ socklen_t size;
2048
+
2049
+ boolean = 0;
2050
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
2051
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
2052
+
2053
+ if(v_bool == Qtrue)
2054
+ boolean = 1;
2055
+
2056
+ if(sctp_opt_info(fileno, assoc_id, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&boolean, &size) < 0)
2057
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
2058
+
2059
+ return v_bool;
2060
+ }
2061
+
1532
2062
  void Init_socket(void){
1533
2063
  mSCTP = rb_define_module("SCTP");
1534
2064
  cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
@@ -1619,23 +2149,37 @@ void Init_socket(void){
1619
2149
 
1620
2150
  v_sctp_peer_addr_params_struct = rb_struct_define(
1621
2151
  "PeerAddressParams", "association_id", "address", "heartbeat_interval",
1622
- "max_retransmission_count", NULL
2152
+ "max_retransmission_count", "path_mtu", "flags",
2153
+ "ipv6_flowlabel", NULL
2154
+ );
2155
+
2156
+ v_sctp_initmsg_struct = rb_struct_define(
2157
+ "InitMsg", "num_ostreams", "max_instreams", "max_attempts", "max_init_timeout", NULL
1623
2158
  );
1624
2159
 
1625
2160
  rb_define_method(cSocket, "initialize", rsctp_init, -1);
1626
2161
 
2162
+ rb_define_method(cSocket, "autoclose=", rsctp_set_autoclose, 1);
1627
2163
  rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
1628
2164
  rb_define_method(cSocket, "close", rsctp_close, 0);
1629
2165
  rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
2166
+ rb_define_method(cSocket, "delete_shared_key", rsctp_delete_shared_key, -1);
2167
+ rb_define_method(cSocket, "enable_auth_support", rsctp_enable_auth_support, -1);
1630
2168
  rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
1631
2169
  rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
1632
- rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
2170
+ rb_define_method(cSocket, "get_active_shared_key", rsctp_get_active_shared_key, -1);
2171
+ rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
2172
+ rb_define_method(cSocket, "get_autoclose", rsctp_get_autoclose, 0);
1633
2173
  rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
2174
+ rb_define_method(cSocket, "get_initmsg", rsctp_get_init_msg, 0);
2175
+ rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
1634
2176
  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);
2177
+ rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
1636
2178
  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
2179
  rb_define_method(cSocket, "listen", rsctp_listen, -1);
2180
+ rb_define_method(cSocket, "map_ipv4=", rsctp_map_ipv4, 1);
2181
+ rb_define_method(cSocket, "nodelay?", rsctp_get_nodelay, 0);
2182
+ rb_define_method(cSocket, "nodelay=", rsctp_set_nodelay, 1);
1639
2183
  rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
1640
2184
  rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
1641
2185
  rb_define_method(cSocket, "send", rsctp_send, 1);
@@ -1649,7 +2193,10 @@ void Init_socket(void){
1649
2193
  #endif
1650
2194
 
1651
2195
  rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
2196
+ rb_define_method(cSocket, "set_active_shared_key", rsctp_set_active_shared_key, -1);
1652
2197
  rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
2198
+ //rb_define_method(cSocket, "set_retransmission_info", rsctp_set_retransmission_info, -1);
2199
+ rb_define_method(cSocket, "set_shared_key", rsctp_set_shared_key, -1);
1653
2200
  rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
1654
2201
  rb_define_method(cSocket, "subscribe", rsctp_subscribe, 1);
1655
2202
 
@@ -1659,8 +2206,8 @@ void Init_socket(void){
1659
2206
  rb_define_attr(cSocket, "association_id", 1, 1);
1660
2207
  rb_define_attr(cSocket, "port", 1, 1);
1661
2208
 
1662
- /* 0.1.0: The version of this library */
1663
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.0"));
2209
+ /* 0.1.1: The version of this library */
2210
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.1"));
1664
2211
 
1665
2212
  /* send flags */
1666
2213