sctp-socket 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ruby.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGES.md +12 -0
- data/README.md +75 -0
- data/examples/client_for_server_test.rb +34 -0
- data/examples/sctp_server_example.rb +69 -0
- data/examples/server_using_sctp_server.rb +65 -0
- data/ext/sctp/socket.c +460 -65
- data/lib/sctp/server.rb +207 -0
- data/sctp-socket.gemspec +1 -1
- data.tar.gz.sig +0 -0
- metadata +6 -5
- metadata.gz.sig +0 -0
- data/ext/sctp/socket/client.c +0 -7
- data/ext/sctp/socket/server.c +0 -7
- data/ext/sctp/socket.h +0 -18
data/ext/sctp/socket.c
CHANGED
@@ -39,14 +39,57 @@ VALUE v_sctp_initmsg_struct;
|
|
39
39
|
#endif
|
40
40
|
#endif
|
41
41
|
|
42
|
-
//
|
42
|
+
// Memory safety and error handling macros
|
43
|
+
#define CHECK_FILENO_VALID(fileno) do { \
|
44
|
+
if ((fileno) < 0) { \
|
45
|
+
rb_raise(rb_eSystemCallError, "invalid file descriptor"); \
|
46
|
+
} \
|
47
|
+
} while(0)
|
48
|
+
|
49
|
+
#define SAFE_FREE(ptr) do { \
|
50
|
+
if ((ptr) != NULL) { \
|
51
|
+
free(ptr); \
|
52
|
+
(ptr) = NULL; \
|
53
|
+
} \
|
54
|
+
} while(0)
|
55
|
+
|
56
|
+
#define CHECK_SOCKET_CLOSED(self) do { \
|
57
|
+
VALUE v_fileno = rb_iv_get((self), "@fileno"); \
|
58
|
+
if (NIL_P(v_fileno) || NUM2INT(v_fileno) < 0) { \
|
59
|
+
rb_raise(rb_eIOError, "socket is closed"); \
|
60
|
+
} \
|
61
|
+
} while(0)
|
62
|
+
|
63
|
+
#define MAX_IP_ADDRESSES 8
|
64
|
+
#define DEFAULT_BUFFER_SIZE 1024
|
65
|
+
#define IP_BUFFER_SIZE INET6_ADDRSTRLEN
|
66
|
+
|
67
|
+
/*
|
68
|
+
* Convert a sockaddr_in structure to a Ruby struct.
|
69
|
+
* Handles both IPv4 and IPv6 addresses properly.
|
70
|
+
*
|
71
|
+
* @param addr Pointer to sockaddr_in structure
|
72
|
+
* @return Ruby struct representing the socket address
|
73
|
+
*/
|
43
74
|
VALUE convert_sockaddr_in_to_struct(struct sockaddr_in* addr){
|
44
|
-
char ipbuf[
|
75
|
+
char ipbuf[IP_BUFFER_SIZE];
|
76
|
+
const char* result;
|
77
|
+
|
78
|
+
if(addr == NULL)
|
79
|
+
rb_raise(rb_eArgError, "null address pointer");
|
80
|
+
|
81
|
+
if((addr->sin_family != AF_INET) && (addr->sin_family != AF_INET6))
|
82
|
+
rb_raise(rb_eArgError, "unsupported address family");
|
83
|
+
|
84
|
+
bzero(ipbuf, sizeof(ipbuf));
|
45
85
|
|
46
86
|
if(addr->sin_family == AF_INET6)
|
47
|
-
inet_ntop(addr->sin_family, &(((struct sockaddr_in6 *)addr)->sin6_addr), ipbuf, sizeof(ipbuf));
|
87
|
+
result = inet_ntop(addr->sin_family, &(((struct sockaddr_in6 *)addr)->sin6_addr), ipbuf, sizeof(ipbuf));
|
48
88
|
else
|
49
|
-
inet_ntop(addr->sin_family, &(((struct sockaddr_in *)addr)->sin_addr), ipbuf, sizeof(ipbuf));
|
89
|
+
result = inet_ntop(addr->sin_family, &(((struct sockaddr_in *)addr)->sin_addr), ipbuf, sizeof(ipbuf));
|
90
|
+
|
91
|
+
if(result == NULL)
|
92
|
+
rb_raise(rb_eSystemCallError, "inet_ntop: %s", strerror(errno));
|
50
93
|
|
51
94
|
return rb_struct_new(v_sockaddr_in_struct,
|
52
95
|
INT2NUM(addr->sin_family),
|
@@ -55,27 +98,49 @@ VALUE convert_sockaddr_in_to_struct(struct sockaddr_in* addr){
|
|
55
98
|
);
|
56
99
|
}
|
57
100
|
|
58
|
-
|
101
|
+
/*
|
102
|
+
* Helper function to get a hash value via string or symbol key.
|
103
|
+
* This provides Ruby's flexible hash access pattern.
|
104
|
+
*
|
105
|
+
* @param v_hash Ruby hash object
|
106
|
+
* @param key String key to look up
|
107
|
+
* @return Ruby value or Qnil if not found
|
108
|
+
*/
|
59
109
|
VALUE rb_hash_aref2(VALUE v_hash, const char* key){
|
60
110
|
VALUE v_key, v_val;
|
61
111
|
|
112
|
+
if(key == NULL)
|
113
|
+
return Qnil;
|
114
|
+
|
115
|
+
// Try a string key first
|
62
116
|
v_key = rb_str_new2(key);
|
63
117
|
v_val = rb_hash_aref(v_hash, v_key);
|
64
118
|
|
119
|
+
// If not found, try a symbol key
|
65
120
|
if(NIL_P(v_val))
|
66
121
|
v_val = rb_hash_aref(v_hash, ID2SYM(rb_intern(key)));
|
67
122
|
|
68
123
|
return v_val;
|
69
124
|
}
|
70
125
|
|
126
|
+
/*
|
127
|
+
* Parse and convert SCTP notification messages into Ruby structures.
|
128
|
+
* This function handles various types of SCTP notifications.
|
129
|
+
*
|
130
|
+
* @param buffer Raw notification buffer from SCTP
|
131
|
+
* @return Ruby struct representing the notification
|
132
|
+
*/
|
71
133
|
VALUE get_notification_info(char* buffer){
|
72
134
|
uint32_t i;
|
73
|
-
char str[
|
135
|
+
char str[IP_BUFFER_SIZE];
|
74
136
|
union sctp_notification* snp;
|
75
137
|
VALUE v_notification = Qnil;
|
76
138
|
VALUE v_str = Qnil;
|
77
139
|
VALUE* v_temp;
|
78
140
|
|
141
|
+
if(buffer == NULL)
|
142
|
+
rb_raise(rb_eArgError, "notification buffer is null");
|
143
|
+
|
79
144
|
snp = (union sctp_notification*)buffer;
|
80
145
|
|
81
146
|
switch(snp->sn_header.sn_type){
|
@@ -310,11 +375,24 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
310
375
|
|
311
376
|
rb_scan_args(argc, argv, "02", &v_domain, &v_type);
|
312
377
|
|
313
|
-
|
378
|
+
// Set defaults with validation
|
379
|
+
if(NIL_P(v_domain)){
|
314
380
|
v_domain = INT2NUM(AF_INET);
|
315
|
-
|
316
|
-
|
381
|
+
}
|
382
|
+
else{
|
383
|
+
int domain = NUM2INT(v_domain);
|
384
|
+
if((domain != AF_INET) && (domain != AF_INET6))
|
385
|
+
rb_raise(rb_eArgError, "unsupported domain family: %d", domain);
|
386
|
+
}
|
387
|
+
|
388
|
+
if(NIL_P(v_type)){
|
317
389
|
v_type = INT2NUM(SOCK_SEQPACKET);
|
390
|
+
}
|
391
|
+
else{
|
392
|
+
int type = NUM2INT(v_type);
|
393
|
+
if (type != SOCK_SEQPACKET && type != SOCK_STREAM)
|
394
|
+
rb_raise(rb_eArgError, "unsupported socket type: %d", type);
|
395
|
+
}
|
318
396
|
|
319
397
|
fileno = socket(NUM2INT(v_domain), NUM2INT(v_type), IPPROTO_SCTP);
|
320
398
|
|
@@ -373,7 +451,7 @@ static VALUE rsctp_init(int argc, VALUE* argv, VALUE self){
|
|
373
451
|
* Returns the port that it was bound to.
|
374
452
|
*/
|
375
453
|
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
376
|
-
struct sockaddr_in addrs[
|
454
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
377
455
|
int i, fileno, num_ip, flags, domain, port, on;
|
378
456
|
VALUE v_addresses, v_port, v_flags, v_address, v_reuse_addr, v_options;
|
379
457
|
|
@@ -404,7 +482,7 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
404
482
|
else
|
405
483
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
406
484
|
|
407
|
-
if(num_ip >
|
485
|
+
if(num_ip > MAX_IP_ADDRESSES)
|
408
486
|
rb_raise(rb_eArgError, "too many IP addresses to bind, maximum is eight");
|
409
487
|
|
410
488
|
domain = NUM2INT(rb_iv_get(self, "@domain"));
|
@@ -472,7 +550,7 @@ static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
|
|
472
550
|
* methods will automatically establish associations.
|
473
551
|
*/
|
474
552
|
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
475
|
-
struct sockaddr_in addrs[
|
553
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
476
554
|
int i, num_ip, fileno;
|
477
555
|
sctp_assoc_t assoc;
|
478
556
|
VALUE v_address, v_domain, v_options, v_addresses, v_port;
|
@@ -540,7 +618,7 @@ static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
|
|
540
618
|
* socket.close(linger: 5)
|
541
619
|
*/
|
542
620
|
static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
543
|
-
VALUE v_options, v_linger;
|
621
|
+
VALUE v_options, v_linger, v_fileno;
|
544
622
|
int fileno;
|
545
623
|
|
546
624
|
rb_scan_args(argc, argv, "01", &v_options);
|
@@ -551,27 +629,56 @@ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
551
629
|
Check_Type(v_options, T_HASH);
|
552
630
|
|
553
631
|
v_linger = rb_hash_aref2(v_options, "linger");
|
632
|
+
v_fileno = rb_iv_get(self, "@fileno");
|
554
633
|
|
555
|
-
|
634
|
+
if(NIL_P(v_fileno)) // Already closed
|
635
|
+
return self;
|
636
|
+
|
637
|
+
fileno = NUM2INT(v_fileno);
|
556
638
|
|
557
639
|
if(!NIL_P(v_linger)){
|
558
640
|
struct linger lin;
|
641
|
+
int linger_time = NUM2INT(v_linger);
|
642
|
+
|
643
|
+
if(linger_time < 0)
|
644
|
+
rb_raise(rb_eArgError, "linger time must be non-negative");
|
645
|
+
|
559
646
|
lin.l_onoff = 1;
|
560
|
-
lin.l_linger =
|
647
|
+
lin.l_linger = linger_time;
|
561
648
|
|
562
649
|
if(setsockopt(fileno, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
|
563
650
|
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
564
651
|
}
|
565
652
|
|
566
|
-
if(close(fileno))
|
653
|
+
if(close(fileno) < 0)
|
567
654
|
rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
|
568
655
|
|
656
|
+
// Mark socket as closed
|
657
|
+
rb_iv_set(self, "@fileno", Qnil);
|
658
|
+
|
569
659
|
return self;
|
570
660
|
}
|
571
661
|
|
572
662
|
/*
|
573
663
|
* call-seq:
|
574
|
-
* SCTP::Socket#
|
664
|
+
* SCTP::Socket#closed?
|
665
|
+
*
|
666
|
+
* Returns true if the socket is closed, false otherwise.
|
667
|
+
*
|
668
|
+
* Example:
|
669
|
+
* socket = SCTP::Socket.new
|
670
|
+
* socket.closed? # => false
|
671
|
+
* socket.close
|
672
|
+
* socket.closed? # => true
|
673
|
+
*/
|
674
|
+
static VALUE rsctp_closed_p(VALUE self){
|
675
|
+
VALUE v_fileno = rb_iv_get(self, "@fileno");
|
676
|
+
return NIL_P(v_fileno) ? Qtrue : Qfalse;
|
677
|
+
}
|
678
|
+
|
679
|
+
/*
|
680
|
+
* call-seq:
|
681
|
+
* SCTP::Socket#getpeernames
|
575
682
|
*
|
576
683
|
* Return an array of all addresses of a peer of the current socket
|
577
684
|
* and association number.
|
@@ -584,7 +691,7 @@ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
584
691
|
* socket = SCTP::Socket.new
|
585
692
|
* # ...
|
586
693
|
* p socket.getpeernames
|
587
|
-
*
|
694
|
+
*
|
588
695
|
* info = socket.recvmsg
|
589
696
|
* association_fileno = socket.peeloff(info.association_id)
|
590
697
|
*
|
@@ -592,20 +699,22 @@ static VALUE rsctp_close(int argc, VALUE* argv, VALUE self){
|
|
592
699
|
*/
|
593
700
|
static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
594
701
|
sctp_assoc_t assoc_id;
|
595
|
-
struct sockaddr* addrs;
|
702
|
+
struct sockaddr* addrs = NULL;
|
596
703
|
int i, fileno, num_addrs;
|
597
|
-
char str[
|
704
|
+
char str[IP_BUFFER_SIZE];
|
598
705
|
VALUE v_fileno, v_association_id;
|
599
706
|
VALUE v_array = rb_ary_new();
|
600
707
|
|
601
|
-
bzero(&addrs, sizeof(addrs));
|
602
|
-
|
603
708
|
rb_scan_args(argc, argv, "02", &v_fileno, &v_association_id);
|
604
709
|
|
605
|
-
if(NIL_P(v_fileno))
|
710
|
+
if(NIL_P(v_fileno)){
|
711
|
+
CHECK_SOCKET_CLOSED(self);
|
606
712
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
607
|
-
|
713
|
+
}
|
714
|
+
else{
|
608
715
|
fileno = NUM2INT(v_fileno);
|
716
|
+
CHECK_FILENO_VALID(fileno);
|
717
|
+
}
|
609
718
|
|
610
719
|
if(NIL_P(v_association_id))
|
611
720
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
@@ -615,14 +724,16 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
615
724
|
num_addrs = sctp_getpaddrs(fileno, assoc_id, &addrs);
|
616
725
|
|
617
726
|
if(num_addrs < 0){
|
618
|
-
|
727
|
+
if(addrs != NULL)
|
728
|
+
sctp_freepaddrs(addrs);
|
729
|
+
|
619
730
|
rb_raise(rb_eSystemCallError, "sctp_getpaddrs: %s", strerror(errno));
|
620
731
|
}
|
621
732
|
|
622
733
|
for(i = 0; i < num_addrs; i++){
|
734
|
+
bzero(&str, sizeof(str));
|
623
735
|
inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
|
624
736
|
rb_ary_push(v_array, rb_str_new2(str));
|
625
|
-
bzero(&str, sizeof(str));
|
626
737
|
}
|
627
738
|
|
628
739
|
sctp_freepaddrs(addrs);
|
@@ -649,20 +760,22 @@ static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
|
|
649
760
|
*/
|
650
761
|
static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
651
762
|
sctp_assoc_t assoc_id;
|
652
|
-
struct sockaddr* addrs;
|
763
|
+
struct sockaddr* addrs = NULL;
|
653
764
|
int i, fileno, num_addrs;
|
654
|
-
char str[
|
765
|
+
char str[IP_BUFFER_SIZE];
|
655
766
|
VALUE v_assoc_fileno, v_assoc_id;
|
656
767
|
VALUE v_array = rb_ary_new();
|
657
768
|
|
658
|
-
bzero(&addrs, sizeof(addrs));
|
659
|
-
|
660
769
|
rb_scan_args(argc, argv, "02", &v_assoc_fileno, &v_assoc_id);
|
661
770
|
|
662
|
-
if(NIL_P(v_assoc_fileno))
|
771
|
+
if(NIL_P(v_assoc_fileno)){
|
772
|
+
CHECK_SOCKET_CLOSED(self);
|
663
773
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
664
|
-
|
774
|
+
}
|
775
|
+
else{
|
665
776
|
fileno = NUM2INT(v_assoc_fileno);
|
777
|
+
CHECK_FILENO_VALID(fileno);
|
778
|
+
}
|
666
779
|
|
667
780
|
if(NIL_P(v_assoc_id))
|
668
781
|
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
@@ -672,14 +785,16 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
672
785
|
num_addrs = sctp_getladdrs(fileno, assoc_id, &addrs);
|
673
786
|
|
674
787
|
if(num_addrs < 0){
|
675
|
-
|
788
|
+
if(addrs != NULL)
|
789
|
+
sctp_freeladdrs(addrs);
|
790
|
+
|
676
791
|
rb_raise(rb_eSystemCallError, "sctp_getladdrs: %s", strerror(errno));
|
677
792
|
}
|
678
793
|
|
679
794
|
for(i = 0; i < num_addrs; i++){
|
795
|
+
bzero(&str, sizeof(str));
|
680
796
|
inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
|
681
797
|
rb_ary_push(v_array, rb_str_new2(str));
|
682
|
-
bzero(&str, sizeof(str));
|
683
798
|
}
|
684
799
|
|
685
800
|
sctp_freeladdrs(addrs);
|
@@ -704,11 +819,11 @@ static VALUE rsctp_getlocalnames(int argc, VALUE* argv, VALUE self){
|
|
704
819
|
* socket = SCTP::Socket.new
|
705
820
|
*
|
706
821
|
* # You can specify addresses here or in an earlier connectx call.
|
707
|
-
* socket.sendv
|
822
|
+
* socket.sendv({
|
708
823
|
* :message => ['Hello ', 'World.'],
|
709
824
|
* :addresses => ['10.0.5.4', '10.0.6.4'],
|
710
825
|
* :info_type => SCTP::Socket:::SCTP_SENDV_SNDINFO
|
711
|
-
* )
|
826
|
+
* })
|
712
827
|
*
|
713
828
|
* CAVEAT: Currently info_type is not yet supported.
|
714
829
|
*
|
@@ -730,8 +845,11 @@ static VALUE rsctp_sendv(VALUE self, VALUE v_options){
|
|
730
845
|
v_message = rb_hash_aref2(v_options, "message");
|
731
846
|
v_addresses = rb_hash_aref2(v_options, "addresses");
|
732
847
|
|
733
|
-
|
734
|
-
|
848
|
+
// Validate required message parameter
|
849
|
+
if(NIL_P(v_message))
|
850
|
+
rb_raise(rb_eArgError, "message parameter is required");
|
851
|
+
|
852
|
+
Check_Type(v_message, T_ARRAY);
|
735
853
|
|
736
854
|
if(!NIL_P(v_addresses)){
|
737
855
|
Check_Type(v_addresses, T_ARRAY);
|
@@ -982,7 +1100,7 @@ static VALUE rsctp_send(VALUE self, VALUE v_options){
|
|
982
1100
|
* :stream -> The SCTP stream number you wish to send the message on.
|
983
1101
|
* :addresses -> An array of addresses to send the message to.
|
984
1102
|
* :context -> The default context used for the sendmsg call if the send fails.
|
985
|
-
* :ppid -> The payload protocol identifier that is passed to the peer endpoint.
|
1103
|
+
* :ppid -> The payload protocol identifier that is passed to the peer endpoint.
|
986
1104
|
* :flags -> A bitwise integer that contain one or more values that control behavior.
|
987
1105
|
*
|
988
1106
|
* Note that the :addresses option is not mandatory in a one-to-one (SOCK_STREAM)
|
@@ -1008,7 +1126,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
1008
1126
|
uint16_t stream;
|
1009
1127
|
uint32_t ppid, flags, ttl, context;
|
1010
1128
|
ssize_t num_bytes;
|
1011
|
-
struct sockaddr_in addrs[
|
1129
|
+
struct sockaddr_in addrs[MAX_IP_ADDRESSES];
|
1012
1130
|
int fileno, size, num_ip;
|
1013
1131
|
|
1014
1132
|
Check_Type(v_options, T_HASH);
|
@@ -1023,6 +1141,9 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
1023
1141
|
v_ttl = rb_hash_aref2(v_options, "ttl");
|
1024
1142
|
v_addresses = rb_hash_aref2(v_options, "addresses");
|
1025
1143
|
|
1144
|
+
if(NIL_P(v_msg))
|
1145
|
+
rb_raise(rb_eArgError, "message parameter is required");
|
1146
|
+
|
1026
1147
|
if(NIL_P(v_stream))
|
1027
1148
|
stream = 0;
|
1028
1149
|
else
|
@@ -1055,6 +1176,7 @@ static VALUE rsctp_sendmsg(VALUE self, VALUE v_options){
|
|
1055
1176
|
int i, port;
|
1056
1177
|
VALUE v_address, v_port;
|
1057
1178
|
|
1179
|
+
Check_Type(v_addresses, T_ARRAY);
|
1058
1180
|
num_ip = (int)RARRAY_LEN(v_addresses);
|
1059
1181
|
v_port = rb_hash_aref2(v_options, "port");
|
1060
1182
|
|
@@ -1176,7 +1298,7 @@ static VALUE rsctp_recvmsg(int argc, VALUE* argv, VALUE self){
|
|
1176
1298
|
if(NIL_P(v_flags))
|
1177
1299
|
flags = 0;
|
1178
1300
|
else
|
1179
|
-
flags = NUM2INT(v_flags);
|
1301
|
+
flags = NUM2INT(v_flags);
|
1180
1302
|
|
1181
1303
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1182
1304
|
length = sizeof(struct sockaddr_in);
|
@@ -1305,7 +1427,7 @@ static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
|
|
1305
1427
|
* :peer_error (aka remote error)
|
1306
1428
|
*
|
1307
1429
|
* Example:
|
1308
|
-
*
|
1430
|
+
*
|
1309
1431
|
* socket = SCTP::Socket.new
|
1310
1432
|
*
|
1311
1433
|
* socket.bind(:port => port, :addresses => ['127.0.0.1'])
|
@@ -1402,7 +1524,7 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
1402
1524
|
|
1403
1525
|
if(listen(fileno, backlog) < 0)
|
1404
1526
|
rb_raise(rb_eSystemCallError, "listen: %s", strerror(errno));
|
1405
|
-
|
1527
|
+
|
1406
1528
|
return self;
|
1407
1529
|
}
|
1408
1530
|
|
@@ -1427,7 +1549,7 @@ static VALUE rsctp_listen(int argc, VALUE* argv, VALUE self){
|
|
1427
1549
|
static VALUE rsctp_peeloff(VALUE self, VALUE v_assoc_id){
|
1428
1550
|
int fileno, assoc_fileno;
|
1429
1551
|
sctp_assoc_t assoc_id;
|
1430
|
-
|
1552
|
+
|
1431
1553
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1432
1554
|
assoc_id = NUM2INT(v_assoc_id);
|
1433
1555
|
|
@@ -1884,7 +2006,7 @@ static VALUE rsctp_get_subscriptions(VALUE self){
|
|
1884
2006
|
*/
|
1885
2007
|
static VALUE rsctp_get_peer_address_params(VALUE self){
|
1886
2008
|
int fileno;
|
1887
|
-
char str[
|
2009
|
+
char str[IP_BUFFER_SIZE];
|
1888
2010
|
socklen_t size;
|
1889
2011
|
sctp_assoc_t assoc_id;
|
1890
2012
|
struct sctp_paddrparams paddr;
|
@@ -1991,11 +2113,9 @@ static VALUE rsctp_get_nodelay(VALUE self){
|
|
1991
2113
|
static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
1992
2114
|
int fileno;
|
1993
2115
|
socklen_t size;
|
1994
|
-
sctp_assoc_t assoc_id;
|
1995
2116
|
int value;
|
1996
2117
|
|
1997
2118
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
1998
|
-
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
1999
2119
|
size = sizeof(int);
|
2000
2120
|
|
2001
2121
|
if(NIL_P(v_bool) || v_bool == Qfalse)
|
@@ -2003,8 +2123,8 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
2003
2123
|
else
|
2004
2124
|
value = 1;
|
2005
2125
|
|
2006
|
-
if(
|
2007
|
-
rb_raise(rb_eSystemCallError, "
|
2126
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_NODELAY, &value, size) < 0)
|
2127
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
2008
2128
|
|
2009
2129
|
if(value)
|
2010
2130
|
return Qtrue;
|
@@ -2015,7 +2135,7 @@ static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
|
|
2015
2135
|
/*
|
2016
2136
|
* call-seq:
|
2017
2137
|
* SCTP::Socket#disable_fragments=(bool)
|
2018
|
-
*
|
2138
|
+
*
|
2019
2139
|
* This option is a on/off flag and is passed an integer where a non-
|
2020
2140
|
* zero is on and a zero is off. If enabled no SCTP message
|
2021
2141
|
* fragmentation will be performed. Instead if a message being sent
|
@@ -2093,19 +2213,15 @@ static VALUE rsctp_get_autoclose(VALUE self){
|
|
2093
2213
|
*/
|
2094
2214
|
static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
|
2095
2215
|
int fileno;
|
2096
|
-
socklen_t size;
|
2097
|
-
sctp_assoc_t assoc_id;
|
2098
2216
|
int value;
|
2099
2217
|
|
2100
2218
|
value = NUM2INT(v_seconds);
|
2101
2219
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2102
|
-
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2103
|
-
size = sizeof(int);
|
2104
2220
|
|
2105
|
-
if(
|
2106
|
-
rb_raise(rb_eSystemCallError, "
|
2221
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_AUTOCLOSE, &value, sizeof(value)) < 0)
|
2222
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
2107
2223
|
|
2108
|
-
return
|
2224
|
+
return INT2NUM(value);
|
2109
2225
|
}
|
2110
2226
|
|
2111
2227
|
/*
|
@@ -2140,6 +2256,43 @@ static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
|
|
2140
2256
|
return self;
|
2141
2257
|
}
|
2142
2258
|
|
2259
|
+
/*
|
2260
|
+
* call-seq:
|
2261
|
+
* SCTP::Socket#auth_support?(association_id=nil)
|
2262
|
+
*
|
2263
|
+
* Returns whether or not authentication support is enabled for the association.
|
2264
|
+
* Returns true if auth support is enabled, false otherwise.
|
2265
|
+
*/
|
2266
|
+
static VALUE rsctp_get_auth_support(int argc, VALUE* argv, VALUE self){
|
2267
|
+
int fileno;
|
2268
|
+
socklen_t size;
|
2269
|
+
sctp_assoc_t assoc_id;
|
2270
|
+
struct sctp_assoc_value assoc_value;
|
2271
|
+
VALUE v_assoc_id;
|
2272
|
+
|
2273
|
+
rb_scan_args(argc, argv, "01", &v_assoc_id);
|
2274
|
+
|
2275
|
+
CHECK_SOCKET_CLOSED(self);
|
2276
|
+
|
2277
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2278
|
+
size = sizeof(struct sctp_assoc_value);
|
2279
|
+
|
2280
|
+
if(NIL_P(v_assoc_id))
|
2281
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2282
|
+
else
|
2283
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2284
|
+
|
2285
|
+
assoc_value.assoc_id = assoc_id;
|
2286
|
+
|
2287
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, &size) < 0)
|
2288
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2289
|
+
|
2290
|
+
if(assoc_value.assoc_value)
|
2291
|
+
return Qtrue;
|
2292
|
+
else
|
2293
|
+
return Qfalse;
|
2294
|
+
}
|
2295
|
+
|
2143
2296
|
/*
|
2144
2297
|
* call-seq:
|
2145
2298
|
* SCTP::Socket#set_shared_key(key, keynum, association_id=nil)
|
@@ -2203,7 +2356,7 @@ static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2203
2356
|
|
2204
2357
|
auth_key->sca_assoc_id = assoc_id;
|
2205
2358
|
auth_key->sca_keynumber = keynum;
|
2206
|
-
auth_key->sca_keylength = strlen(key);
|
2359
|
+
auth_key->sca_keylength = strlen(key);
|
2207
2360
|
memcpy(auth_key->sca_key, byte_array, sizeof(byte_array));
|
2208
2361
|
|
2209
2362
|
if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_KEY, (void*)auth_key, &size) < 0)
|
@@ -2366,22 +2519,228 @@ static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
|
|
2366
2519
|
*/
|
2367
2520
|
static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
|
2368
2521
|
int fileno, boolean;
|
2369
|
-
sctp_assoc_t assoc_id;
|
2370
|
-
socklen_t size;
|
2371
2522
|
|
2372
2523
|
boolean = 0;
|
2373
2524
|
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2374
|
-
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2375
2525
|
|
2376
2526
|
if(v_bool == Qtrue)
|
2377
2527
|
boolean = 1;
|
2378
2528
|
|
2379
|
-
if(
|
2380
|
-
rb_raise(rb_eSystemCallError, "
|
2529
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&boolean, sizeof(boolean)) < 0)
|
2530
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
2381
2531
|
|
2382
2532
|
return v_bool;
|
2383
2533
|
}
|
2384
2534
|
|
2535
|
+
/*
|
2536
|
+
* call-seq:
|
2537
|
+
* SCTP::Socket#map_ipv4?
|
2538
|
+
*
|
2539
|
+
* Returns whether or not IPv4 addresses will be mapped to V6 representation
|
2540
|
+
* for PF_INET6 sockets. Returns true if mapping is enabled, false otherwise.
|
2541
|
+
*/
|
2542
|
+
static VALUE rsctp_get_map_ipv4(VALUE self){
|
2543
|
+
int fileno;
|
2544
|
+
socklen_t size;
|
2545
|
+
sctp_assoc_t assoc_id;
|
2546
|
+
int value;
|
2547
|
+
|
2548
|
+
CHECK_SOCKET_CLOSED(self);
|
2549
|
+
|
2550
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2551
|
+
assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
|
2552
|
+
size = sizeof(int);
|
2553
|
+
|
2554
|
+
if(sctp_opt_info(fileno, assoc_id, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&value, &size) < 0)
|
2555
|
+
rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
|
2556
|
+
|
2557
|
+
if(value)
|
2558
|
+
return Qtrue;
|
2559
|
+
else
|
2560
|
+
return Qfalse;
|
2561
|
+
}
|
2562
|
+
|
2563
|
+
/*
|
2564
|
+
* call-seq:
|
2565
|
+
* SCTP::Socket#set_default_send_params(options)
|
2566
|
+
*
|
2567
|
+
* Sets the default parameters that will be used by the sendmsg() call
|
2568
|
+
* when it is invoked with a null parameter.
|
2569
|
+
*
|
2570
|
+
* The +options+ hash may contain the following keys:
|
2571
|
+
*
|
2572
|
+
* * stream: A number indicating the stream number within the association
|
2573
|
+
* * ssn: Not used by applications. Ignored for one-to-many style sockets.
|
2574
|
+
* * flags: Indicates various options for sending. See SCTP_* constants.
|
2575
|
+
* * ppid: The payload protocol identifier
|
2576
|
+
* * context: User-specified context information
|
2577
|
+
* * ttl: The time to live (in milliseconds)
|
2578
|
+
* * tsn: Not used by applications
|
2579
|
+
* * cumtsn: Not used by applications
|
2580
|
+
* * association_id: The association identification (ignored for one-to-one sockets)
|
2581
|
+
*
|
2582
|
+
* Example:
|
2583
|
+
*
|
2584
|
+
* socket.set_default_send_params(:stream => 1, :flags => SCTP::Socket::SCTP_UNORDERED)
|
2585
|
+
*/
|
2586
|
+
static VALUE rsctp_set_default_send_params(VALUE self, VALUE v_options){
|
2587
|
+
VALUE v_stream, v_ssn, v_flags, v_ppid, v_context, v_ttl, v_tsn, v_cumtsn, v_assoc_id;
|
2588
|
+
int fileno;
|
2589
|
+
sctp_assoc_t assoc_id;
|
2590
|
+
struct sctp_sndrcvinfo sndrcv;
|
2591
|
+
|
2592
|
+
if(!RB_TYPE_P(v_options, T_HASH))
|
2593
|
+
rb_raise(rb_eTypeError, "options must be a hash");
|
2594
|
+
|
2595
|
+
bzero(&sndrcv, sizeof(sndrcv));
|
2596
|
+
|
2597
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2598
|
+
|
2599
|
+
v_stream = rb_hash_aref2(v_options, "stream");
|
2600
|
+
v_ssn = rb_hash_aref2(v_options, "ssn");
|
2601
|
+
v_flags = rb_hash_aref2(v_options, "flags");
|
2602
|
+
v_ppid = rb_hash_aref2(v_options, "ppid");
|
2603
|
+
v_context = rb_hash_aref2(v_options, "context");
|
2604
|
+
v_ttl = rb_hash_aref2(v_options, "ttl");
|
2605
|
+
v_tsn = rb_hash_aref2(v_options, "tsn");
|
2606
|
+
v_cumtsn = rb_hash_aref2(v_options, "cumtsn");
|
2607
|
+
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
2608
|
+
|
2609
|
+
if(NIL_P(v_assoc_id))
|
2610
|
+
v_assoc_id = rb_iv_get(self, "@association_id");
|
2611
|
+
|
2612
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2613
|
+
sndrcv.sinfo_assoc_id = assoc_id;
|
2614
|
+
|
2615
|
+
if(!NIL_P(v_stream))
|
2616
|
+
sndrcv.sinfo_stream = NUM2INT(v_stream);
|
2617
|
+
|
2618
|
+
if(!NIL_P(v_ssn))
|
2619
|
+
sndrcv.sinfo_ssn = NUM2INT(v_ssn);
|
2620
|
+
|
2621
|
+
if(!NIL_P(v_flags))
|
2622
|
+
sndrcv.sinfo_flags = NUM2INT(v_flags);
|
2623
|
+
|
2624
|
+
if(!NIL_P(v_ppid))
|
2625
|
+
sndrcv.sinfo_ppid = NUM2INT(v_ppid);
|
2626
|
+
|
2627
|
+
if(!NIL_P(v_context))
|
2628
|
+
sndrcv.sinfo_context = NUM2INT(v_context);
|
2629
|
+
|
2630
|
+
if(!NIL_P(v_ttl))
|
2631
|
+
sndrcv.sinfo_timetolive = NUM2INT(v_ttl);
|
2632
|
+
|
2633
|
+
if(!NIL_P(v_tsn))
|
2634
|
+
sndrcv.sinfo_tsn = NUM2INT(v_tsn);
|
2635
|
+
|
2636
|
+
if(!NIL_P(v_cumtsn))
|
2637
|
+
sndrcv.sinfo_cumtsn = NUM2INT(v_cumtsn);
|
2638
|
+
|
2639
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_DEFAULT_SEND_PARAM, &sndrcv, sizeof(sndrcv)) < 0)
|
2640
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
2641
|
+
|
2642
|
+
return rb_struct_new(
|
2643
|
+
v_sctp_default_send_params_struct,
|
2644
|
+
v_stream,
|
2645
|
+
v_ssn,
|
2646
|
+
v_flags,
|
2647
|
+
v_ppid,
|
2648
|
+
v_context,
|
2649
|
+
v_ttl,
|
2650
|
+
v_tsn,
|
2651
|
+
v_cumtsn,
|
2652
|
+
v_assoc_id
|
2653
|
+
);
|
2654
|
+
}
|
2655
|
+
|
2656
|
+
/*
|
2657
|
+
* call-seq:
|
2658
|
+
* SCTP::Socket#set_peer_address_params(options)
|
2659
|
+
*
|
2660
|
+
* Sets the peer address parameters. This allows applications to enable or
|
2661
|
+
* disable heartbeats for any peer address of an association, set the maximum
|
2662
|
+
* number of retransmissions to a destination address, and set the path MTU.
|
2663
|
+
*
|
2664
|
+
* The +options+ hash may contain the following keys:
|
2665
|
+
*
|
2666
|
+
* * association_id: The association identification
|
2667
|
+
* * address: The address of the remote peer
|
2668
|
+
* * hbinterval: The heartbeat interval (in milliseconds)
|
2669
|
+
* * pathmaxrxt: The maximum number of retransmissions
|
2670
|
+
* * pathmtu: The path MTU
|
2671
|
+
* * flags: Flags to control heartbeats, etc.
|
2672
|
+
* * ipv6_flowlabel: IPv6 flow label (only for IPv6 addresses)
|
2673
|
+
*
|
2674
|
+
* Example:
|
2675
|
+
*
|
2676
|
+
* socket.set_peer_address_params(:hbinterval => 5000, :pathmaxrxt => 5)
|
2677
|
+
*/
|
2678
|
+
static VALUE rsctp_set_peer_address_params(VALUE self, VALUE v_options){
|
2679
|
+
VALUE v_assoc_id, v_address, v_hbinterval, v_pathmaxrxt, v_pathmtu, v_flags, v_ipv6_flowlabel;
|
2680
|
+
int fileno;
|
2681
|
+
sctp_assoc_t assoc_id;
|
2682
|
+
struct sctp_paddrparams paddr;
|
2683
|
+
struct sockaddr_in* sin;
|
2684
|
+
|
2685
|
+
if(!RB_TYPE_P(v_options, T_HASH))
|
2686
|
+
rb_raise(rb_eTypeError, "options must be a hash");
|
2687
|
+
|
2688
|
+
bzero(&paddr, sizeof(paddr));
|
2689
|
+
|
2690
|
+
fileno = NUM2INT(rb_iv_get(self, "@fileno"));
|
2691
|
+
|
2692
|
+
v_assoc_id = rb_hash_aref2(v_options, "association_id");
|
2693
|
+
v_address = rb_hash_aref2(v_options, "address");
|
2694
|
+
v_hbinterval = rb_hash_aref2(v_options, "hbinterval");
|
2695
|
+
v_pathmaxrxt = rb_hash_aref2(v_options, "pathmaxrxt");
|
2696
|
+
v_pathmtu = rb_hash_aref2(v_options, "pathmtu");
|
2697
|
+
v_flags = rb_hash_aref2(v_options, "flags");
|
2698
|
+
v_ipv6_flowlabel = rb_hash_aref2(v_options, "ipv6_flowlabel");
|
2699
|
+
|
2700
|
+
if(NIL_P(v_assoc_id))
|
2701
|
+
v_assoc_id = rb_iv_get(self, "@association_id");
|
2702
|
+
|
2703
|
+
assoc_id = NUM2INT(v_assoc_id);
|
2704
|
+
paddr.spp_assoc_id = assoc_id;
|
2705
|
+
|
2706
|
+
// If address is provided, set up the sockaddr structure
|
2707
|
+
if(!NIL_P(v_address)){
|
2708
|
+
sin = (struct sockaddr_in*)&paddr.spp_address;
|
2709
|
+
sin->sin_family = AF_INET;
|
2710
|
+
if(inet_pton(AF_INET, StringValueCStr(v_address), &sin->sin_addr) <= 0)
|
2711
|
+
rb_raise(rb_eArgError, "invalid IP address");
|
2712
|
+
}
|
2713
|
+
|
2714
|
+
if(!NIL_P(v_hbinterval))
|
2715
|
+
paddr.spp_hbinterval = NUM2INT(v_hbinterval);
|
2716
|
+
|
2717
|
+
if(!NIL_P(v_pathmaxrxt))
|
2718
|
+
paddr.spp_pathmaxrxt = NUM2INT(v_pathmaxrxt);
|
2719
|
+
|
2720
|
+
if(!NIL_P(v_pathmtu))
|
2721
|
+
paddr.spp_pathmtu = NUM2INT(v_pathmtu);
|
2722
|
+
|
2723
|
+
if(!NIL_P(v_flags))
|
2724
|
+
paddr.spp_flags = NUM2INT(v_flags);
|
2725
|
+
|
2726
|
+
if(!NIL_P(v_ipv6_flowlabel))
|
2727
|
+
paddr.spp_ipv6_flowlabel = NUM2INT(v_ipv6_flowlabel);
|
2728
|
+
|
2729
|
+
if(setsockopt(fileno, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &paddr, sizeof(paddr)) < 0)
|
2730
|
+
rb_raise(rb_eSystemCallError, "setsockopt: %s", strerror(errno));
|
2731
|
+
|
2732
|
+
return rb_struct_new(
|
2733
|
+
v_sctp_peer_addr_params_struct,
|
2734
|
+
v_assoc_id,
|
2735
|
+
v_address,
|
2736
|
+
v_hbinterval,
|
2737
|
+
v_pathmaxrxt,
|
2738
|
+
v_pathmtu,
|
2739
|
+
v_flags,
|
2740
|
+
v_ipv6_flowlabel
|
2741
|
+
);
|
2742
|
+
}
|
2743
|
+
|
2385
2744
|
void Init_socket(void){
|
2386
2745
|
mSCTP = rb_define_module("SCTP");
|
2387
2746
|
cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
|
@@ -2485,23 +2844,26 @@ void Init_socket(void){
|
|
2485
2844
|
rb_define_method(cSocket, "autoclose=", rsctp_set_autoclose, 1);
|
2486
2845
|
rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
|
2487
2846
|
rb_define_method(cSocket, "close", rsctp_close, -1);
|
2847
|
+
rb_define_method(cSocket, "closed?", rsctp_closed_p, 0);
|
2488
2848
|
rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
|
2489
2849
|
rb_define_method(cSocket, "delete_shared_key", rsctp_delete_shared_key, -1);
|
2490
2850
|
rb_define_method(cSocket, "disable_fragments=", rsctp_disable_fragments, 1);
|
2491
2851
|
rb_define_method(cSocket, "enable_auth_support", rsctp_enable_auth_support, -1);
|
2852
|
+
rb_define_method(cSocket, "auth_support?", rsctp_get_auth_support, -1);
|
2492
2853
|
rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
|
2493
2854
|
rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
|
2494
2855
|
rb_define_method(cSocket, "get_active_shared_key", rsctp_get_active_shared_key, -1);
|
2495
2856
|
rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
|
2496
2857
|
rb_define_method(cSocket, "get_autoclose", rsctp_get_autoclose, 0);
|
2497
2858
|
rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
|
2498
|
-
rb_define_method(cSocket, "
|
2859
|
+
rb_define_method(cSocket, "get_init_msg", rsctp_get_init_msg, 0);
|
2499
2860
|
rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
|
2500
2861
|
rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
|
2501
2862
|
rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
|
2502
2863
|
rb_define_method(cSocket, "get_subscriptions", rsctp_get_subscriptions, 0);
|
2503
2864
|
rb_define_method(cSocket, "listen", rsctp_listen, -1);
|
2504
2865
|
rb_define_method(cSocket, "map_ipv4=", rsctp_map_ipv4, 1);
|
2866
|
+
rb_define_method(cSocket, "map_ipv4?", rsctp_get_map_ipv4, 0);
|
2505
2867
|
rb_define_method(cSocket, "nodelay?", rsctp_get_nodelay, 0);
|
2506
2868
|
rb_define_method(cSocket, "nodelay=", rsctp_set_nodelay, 1);
|
2507
2869
|
rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
|
@@ -2521,12 +2883,15 @@ void Init_socket(void){
|
|
2521
2883
|
rb_define_method(cSocket, "set_association_info", rsctp_set_association_info, 1);
|
2522
2884
|
rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
|
2523
2885
|
rb_define_method(cSocket, "set_retransmission_info", rsctp_set_retransmission_info, 1);
|
2886
|
+
rb_define_method(cSocket, "set_default_send_params", rsctp_set_default_send_params, 1);
|
2887
|
+
rb_define_method(cSocket, "set_peer_address_params", rsctp_set_peer_address_params, 1);
|
2524
2888
|
rb_define_method(cSocket, "set_shared_key", rsctp_set_shared_key, -1);
|
2525
2889
|
rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
|
2526
2890
|
rb_define_method(cSocket, "subscribe", rsctp_subscribe, 1);
|
2527
2891
|
|
2528
2892
|
rb_define_alias(cSocket, "get_rto_info", "get_retransmission_info");
|
2529
2893
|
rb_define_alias(cSocket, "set_rto_info", "set_retransmission_info");
|
2894
|
+
rb_define_alias(cSocket, "get_initmsg", "get_init_msg");
|
2530
2895
|
|
2531
2896
|
rb_define_attr(cSocket, "domain", 1, 1);
|
2532
2897
|
rb_define_attr(cSocket, "type", 1, 1);
|
@@ -2535,7 +2900,7 @@ void Init_socket(void){
|
|
2535
2900
|
rb_define_attr(cSocket, "port", 1, 1);
|
2536
2901
|
|
2537
2902
|
/* 0.1.4: The version of this library */
|
2538
|
-
rb_define_const(cSocket, "VERSION", rb_str_new2("0.
|
2903
|
+
rb_define_const(cSocket, "VERSION", rb_str_new2("0.2.0"));
|
2539
2904
|
|
2540
2905
|
/* send flags */
|
2541
2906
|
|
@@ -2574,4 +2939,34 @@ void Init_socket(void){
|
|
2574
2939
|
|
2575
2940
|
rb_define_const(cSocket, "SCTP_BINDX_ADD_ADDR", INT2NUM(SCTP_BINDX_ADD_ADDR));
|
2576
2941
|
rb_define_const(cSocket, "SCTP_BINDX_REM_ADDR", INT2NUM(SCTP_BINDX_REM_ADDR));
|
2942
|
+
|
2943
|
+
// PEER ADDRESS PARAMETER FLAGS //
|
2944
|
+
|
2945
|
+
#ifdef SPP_HB_ENABLE
|
2946
|
+
rb_define_const(cSocket, "SPP_HB_ENABLE", INT2NUM(SPP_HB_ENABLE));
|
2947
|
+
#endif
|
2948
|
+
#ifdef SPP_HB_DISABLE
|
2949
|
+
rb_define_const(cSocket, "SPP_HB_DISABLE", INT2NUM(SPP_HB_DISABLE));
|
2950
|
+
#endif
|
2951
|
+
#ifdef SPP_HB_DEMAND
|
2952
|
+
rb_define_const(cSocket, "SPP_HB_DEMAND", INT2NUM(SPP_HB_DEMAND));
|
2953
|
+
#endif
|
2954
|
+
#ifdef SPP_PMTUD_ENABLE
|
2955
|
+
rb_define_const(cSocket, "SPP_PMTUD_ENABLE", INT2NUM(SPP_PMTUD_ENABLE));
|
2956
|
+
#endif
|
2957
|
+
#ifdef SPP_PMTUD_DISABLE
|
2958
|
+
rb_define_const(cSocket, "SPP_PMTUD_DISABLE", INT2NUM(SPP_PMTUD_DISABLE));
|
2959
|
+
#endif
|
2960
|
+
|
2961
|
+
// PARTIAL RELIABILITY SCTP POLICY CONSTANTS //
|
2962
|
+
|
2963
|
+
#ifdef SCTP_PR_SCTP_TTL
|
2964
|
+
rb_define_const(cSocket, "SCTP_PR_SCTP_TTL", INT2NUM(SCTP_PR_SCTP_TTL));
|
2965
|
+
#endif
|
2966
|
+
#ifdef SCTP_PR_SCTP_RTX
|
2967
|
+
rb_define_const(cSocket, "SCTP_PR_SCTP_RTX", INT2NUM(SCTP_PR_SCTP_RTX));
|
2968
|
+
#endif
|
2969
|
+
#ifdef SCTP_PR_SCTP_BUF
|
2970
|
+
rb_define_const(cSocket, "SCTP_PR_SCTP_BUF", INT2NUM(SCTP_PR_SCTP_BUF));
|
2971
|
+
#endif
|
2577
2972
|
}
|