sctp-socket 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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