ext/sctp/socket.c in sctp-socket-0.1.0 vs ext/sctp/socket.c in sctp-socket-0.1.1
- old
+ new
@@ -23,10 +23,11 @@
VALUE v_sctp_default_send_params_struct;
VALUE v_sctp_event_subscribe_struct;
VALUE v_sctp_receive_info_struct;
VALUE v_sctp_peer_addr_params_struct;
VALUE v_sender_dry_event_struct;
+VALUE v_sctp_initmsg_struct;
#if !defined(IOV_MAX)
#if defined(_SC_IOV_MAX)
#define IOV_MAX (sysconf(_SC_IOV_MAX))
#else
@@ -61,11 +62,199 @@
v_val = rb_hash_aref(v_hash, ID2SYM(rb_intern(key)));
return v_val;
}
+VALUE get_notification_info(char* buffer){
+ uint32_t i;
+ char str[16];
+ union sctp_notification* snp;
+ VALUE v_notification = Qnil;
+ VALUE v_str = Qnil;
+ VALUE* v_temp;
+
+ snp = (union sctp_notification*)buffer;
+
+ switch(snp->sn_header.sn_type){
+ case SCTP_ASSOC_CHANGE:
+ switch(snp->sn_assoc_change.sac_state){
+ case SCTP_COMM_LOST:
+ v_str = rb_str_new2("comm lost");
+ break;
+ case SCTP_COMM_UP:
+ v_str = rb_str_new2("comm up");
+ break;
+ case SCTP_RESTART:
+ v_str = rb_str_new2("restart");
+ break;
+ case SCTP_SHUTDOWN_COMP:
+ v_str = rb_str_new2("shutdown complete");
+ break;
+ case SCTP_CANT_STR_ASSOC:
+ v_str = rb_str_new2("association setup failed");
+ break;
+ default:
+ v_str = rb_str_new2("unknown");
+ }
+
+ v_notification = rb_struct_new(v_assoc_change_struct,
+ UINT2NUM(snp->sn_assoc_change.sac_type),
+ UINT2NUM(snp->sn_assoc_change.sac_length),
+ UINT2NUM(snp->sn_assoc_change.sac_state),
+ UINT2NUM(snp->sn_assoc_change.sac_error),
+ UINT2NUM(snp->sn_assoc_change.sac_outbound_streams),
+ UINT2NUM(snp->sn_assoc_change.sac_inbound_streams),
+ UINT2NUM(snp->sn_assoc_change.sac_assoc_id),
+ v_str
+ );
+ break;
+ case SCTP_PEER_ADDR_CHANGE:
+ switch(snp->sn_paddr_change.spc_state){
+ case SCTP_ADDR_AVAILABLE:
+ v_str = rb_str_new2("available");
+ break;
+ case SCTP_ADDR_UNREACHABLE:
+ v_str = rb_str_new2("unreachable");
+ break;
+ case SCTP_ADDR_REMOVED:
+ v_str = rb_str_new2("removed from association");
+ break;
+ case SCTP_ADDR_ADDED:
+ v_str = rb_str_new2("added to association");
+ break;
+ case SCTP_ADDR_MADE_PRIM:
+ v_str = rb_str_new2("primary destination");
+ break;
+ default:
+ v_str = rb_str_new2("unknown");
+ }
+
+ inet_ntop(
+ ((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
+ &(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
+ str,
+ sizeof(str)
+ );
+
+ v_notification = rb_struct_new(v_peeraddr_change_struct,
+ UINT2NUM(snp->sn_paddr_change.spc_type),
+ UINT2NUM(snp->sn_paddr_change.spc_length),
+ rb_str_new2(str),
+ UINT2NUM(snp->sn_paddr_change.spc_state),
+ UINT2NUM(snp->sn_paddr_change.spc_error),
+ UINT2NUM(snp->sn_paddr_change.spc_assoc_id),
+ v_str
+ );
+ break;
+ case SCTP_REMOTE_ERROR:
+ v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
+
+ for(i = 0; i < snp->sn_remote_error.sre_length; i++){
+ v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
+ }
+
+ v_notification = rb_struct_new(v_remote_error_struct,
+ UINT2NUM(snp->sn_remote_error.sre_type),
+ UINT2NUM(snp->sn_remote_error.sre_flags),
+ UINT2NUM(snp->sn_remote_error.sre_length),
+ UINT2NUM(snp->sn_remote_error.sre_error),
+ UINT2NUM(snp->sn_remote_error.sre_assoc_id),
+ rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
+ );
+ break;
+#ifdef SCTP_SEND_FAILED_EVENT
+ case SCTP_SEND_FAILED_EVENT:
+ v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
+
+ for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
+ v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
+ }
+
+ v_notification = rb_struct_new(v_send_failed_event_struct,
+ UINT2NUM(snp->sn_send_failed_event.ssf_type),
+ UINT2NUM(snp->sn_send_failed_event.ssf_length),
+ UINT2NUM(snp->sn_send_failed_event.ssf_error),
+ rb_struct_new(v_sndinfo_struct,
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
+ UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
+ ),
+ UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
+ rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
+ );
+ break;
+#else
+ case SCTP_SEND_FAILED:
+ v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
+
+ for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
+ v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
+ }
+
+ v_notification = rb_struct_new(v_send_failed_event_struct,
+ UINT2NUM(snp->sn_send_failed.ssf_type),
+ UINT2NUM(snp->sn_send_failed.ssf_length),
+ UINT2NUM(snp->sn_send_failed.ssf_error),
+ Qnil,
+ UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
+ rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
+ );
+ break;
+#endif
+ case SCTP_SHUTDOWN_EVENT:
+ v_notification = rb_struct_new(v_shutdown_event_struct,
+ UINT2NUM(snp->sn_shutdown_event.sse_type),
+ UINT2NUM(snp->sn_shutdown_event.sse_length),
+ UINT2NUM(snp->sn_shutdown_event.sse_assoc_id)
+ );
+ break;
+ case SCTP_ADAPTATION_INDICATION:
+ v_notification = rb_struct_new(v_adaptation_event_struct,
+ UINT2NUM(snp->sn_adaptation_event.sai_type),
+ UINT2NUM(snp->sn_adaptation_event.sai_length),
+ UINT2NUM(snp->sn_adaptation_event.sai_adaptation_ind),
+ UINT2NUM(snp->sn_adaptation_event.sai_assoc_id)
+ );
+ break;
+ case SCTP_PARTIAL_DELIVERY_EVENT:
+ v_notification = rb_struct_new(v_partial_delivery_event_struct,
+ UINT2NUM(snp->sn_pdapi_event.pdapi_type),
+ UINT2NUM(snp->sn_pdapi_event.pdapi_length),
+ UINT2NUM(snp->sn_pdapi_event.pdapi_indication),
+ UINT2NUM(snp->sn_pdapi_event.pdapi_stream),
+ UINT2NUM(snp->sn_pdapi_event.pdapi_seq),
+ UINT2NUM(snp->sn_pdapi_event.pdapi_assoc_id)
+ );
+ break;
+ case SCTP_AUTHENTICATION_EVENT:
+ v_notification = rb_struct_new(v_auth_event_struct,
+ UINT2NUM(snp->sn_authkey_event.auth_type),
+ UINT2NUM(snp->sn_authkey_event.auth_length),
+ UINT2NUM(snp->sn_authkey_event.auth_keynumber),
+ UINT2NUM(snp->sn_authkey_event.auth_indication),
+ UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
+ );
+ break;
+ case SCTP_SENDER_DRY_EVENT:
+ v_notification = rb_struct_new(v_sender_dry_event_struct,
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
+ UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
+ );
+ break;
+ }
+
+ return v_notification;
+}
+
/*
+ * call-seq:
+ * SCTP::Socket.new(domain = Socket::AF_INET, type = Socket::SOCK_STREAM)
+ *
* Create and return a new SCTP::Socket instance. You may optionally pass in
* a domain (aka family) value and socket type. By default these are AF_INET
* and SOCK_SEQPACKET, respectively.
*
* There are only two supported families: SOCK_SEQPACKET for the creation
@@ -104,31 +293,34 @@
return self;
}
/*
- * Bind a subset of IP addresses associated with the host system on the
- * given port, or a port assigned by the operating system if none is provided.
+ * call-seq:
+ * SCTP::Socket#bindx(options)
*
- * Note that you can both add or remove an address to or from the socket
- * using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
- * respectively.
+ * Bind a subset of IP addresses associated with the host system on the
+ * given port, or a port assigned by the operating system if none is provided.
*
- * Example:
+ * Note that you can both add or remove an address to or from the socket
+ * using the SCTP_BINDX_ADD_ADDR (default) or SCTP_BINDX_REM_ADDR constants,
+ * respectively.
*
- * socket = SCTP::Socket.new
+ * Example:
*
- * # Bind 2 addresses
- * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
+ * socket = SCTP::Socket.new
*
- * # Remove 1 later
- * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
+ * # Bind 2 addresses
+ * socket.bindx(:port => 64325, :addresses => ['10.0.4.5', '10.0.5.5'])
*
- * If no addresses are specified, then it will bind to all available interfaces. If
- * no port is specified, then one will be assigned by the host.
+ * # Remove 1 later
+ * socket.bindx(:addresses => ['10.0.4.5'], :flags => SCTP::Socket::BINDX_REM_ADDR)
*
- * Returns the port that it was bound to.
+ * If no addresses are specified, then it will bind to all available interfaces. If
+ * no port is specified, then one will be assigned by the host.
+ *
+ * Returns the port that it was bound to.
*/
static VALUE rsctp_bindx(int argc, VALUE* argv, VALUE self){
struct sockaddr_in addrs[8];
int i, fileno, num_ip, flags, domain, port;
VALUE v_addresses, v_port, v_flags, v_address, v_options;
@@ -194,19 +386,24 @@
return INT2NUM(port);
}
/*
+ * call-seq:
+ * SCTP::Socket#connectx(options)
+ *
* Connect the socket to a multihomed peer via the provided array of addresses
* using the domain specified in the constructor. You must also specify the port.
*
* Example:
*
* socket = SCTP::Socket.new
* socket.connectx(:port => 62354, :addresses => ['10.0.4.5', '10.0.5.5'])
*
- * Note that this will also set/update the object's association_id.
+ * Note that this will also set/update the object's association_id. Also note that
+ * this method is not strictly necessary on the client side, since the various send
+ * methods will automatically establish associations.
*/
static VALUE rsctp_connectx(int argc, VALUE* argv, VALUE self){
struct sockaddr_in addrs[8];
int i, num_ip, fileno;
sctp_assoc_t assoc;
@@ -249,10 +446,13 @@
return self;
}
/*
+ * call-seq:
+ * SCTP::Socket#close
+ *
* Close the socket. You should always do this.
*
* Example:
*
* socket = SCTP::Socket.new
@@ -266,26 +466,29 @@
return self;
}
/*
- * Return an array of all addresses of a peer of the current socket
- * and association number.
+ * call-seq:
+ * SCTP::Socket#getpeernames
*
- * You may optionally pass a assocation fileno and association ID. Typically
- * this information would come from the peeloff method.
+ * Return an array of all addresses of a peer of the current socket
+ * and association number.
*
- * Example:
+ * You may optionally pass a assocation fileno and association ID. Typically
+ * this information would come from the peeloff method.
*
- * socket = SCTP::Socket.new
- * # ...
- * p socket.getpeernames
+ * Example:
*
- * info = socket.recvmsg
- * association_fileno = socket.peeloff(info.association_id)
+ * socket = SCTP::Socket.new
+ * # ...
+ * p socket.getpeernames
+ *
+ * info = socket.recvmsg
+ * association_fileno = socket.peeloff(info.association_id)
*
- * p socket.getpeernames(association_fileno, info.association_id)
+ * p socket.getpeernames(association_fileno, info.association_id)
*/
static VALUE rsctp_getpeernames(int argc, VALUE* argv, VALUE self){
sctp_assoc_t assoc_id;
struct sockaddr* addrs;
int i, fileno, num_addrs;
@@ -324,10 +527,13 @@
return v_array;
}
/*
+ * call-seq:
+ * SCTP::Socket#getlocalnames
+ *
* Return an array of local addresses that are part of the association.
*
* Example:
*
* socket = SCTP::Socket.new
@@ -379,10 +585,13 @@
return v_array;
}
#ifdef HAVE_SCTP_SENDV
/*
+ * call-seq:
+ * SCTP::Socket#sendv(options)
+ *
* Transmit a message to an SCTP endpoint using a gather-write. The following
* hash of options is permitted:
*
* * message - An array of strings that will be joined into a single message.
* * addresses - An array of IP addresses to setup an association to send the message.
@@ -390,42 +599,43 @@
*
* Example:
*
* socket = SCTP::Socket.new
*
+ * # You can specify addresses here or in an earlier connectx call.
* socket.sendv
* :message => ['Hello ', 'World.'],
* :addresses => ['10.0.5.4', '10.0.6.4'],
* :info_type => SCTP::Socket:::SCTP_SENDV_SNDINFO
* )
*
- * CAVEAT: Currently addresses does not work, and info_type is not yet supported.
+ * CAVEAT: Currently info_type is not yet supported.
*
* Returns the number of bytes sent.
*/
static VALUE rsctp_sendv(VALUE self, VALUE v_options){
VALUE v_msg, v_message, v_addresses;
struct iovec iov[IOV_MAX];
struct sockaddr_in* addrs;
- struct sctp_sndinfo info;
+ struct sctp_sendv_spa spa;
int i, fileno, num_bytes, size, num_ip;
Check_Type(v_options, T_HASH);
bzero(&iov, sizeof(iov));
- bzero(&info, sizeof(info));
+ bzero(&spa, sizeof(spa));
v_message = rb_hash_aref2(v_options, "message");
v_addresses = rb_hash_aref2(v_options, "addresses");
if(!NIL_P(v_message))
Check_Type(v_message, T_ARRAY);
if(!NIL_P(v_addresses)){
Check_Type(v_addresses, T_ARRAY);
num_ip = RARRAY_LEN(v_addresses);
- addrs = (struct sockaddr_in*)alloca(sizeof(struct sockaddr_in) * num_ip);
+ addrs = (struct sockaddr_in*)alloca(num_ip * sizeof(*addrs));
}
else{
addrs = NULL;
num_ip = 0;
}
@@ -437,30 +647,32 @@
rb_raise(rb_eArgError, "Must contain at least one message");
if(size > IOV_MAX)
rb_raise(rb_eArgError, "Array size is greater than IOV_MAX");
- info.snd_flags = SCTP_UNORDERED;
- info.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ // TODO: Make this configurable
+ spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
+ spa.sendv_sndinfo.snd_assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
if(!NIL_P(v_addresses)){
- int i, port;
+ int i, port, domain;
VALUE v_address, v_port;
- v_port = NUM2INT(rb_iv_get(self, "@port"));
+ v_port = rb_iv_get(self, "@port");
if(NIL_P(v_port))
port = 0;
else
port = NUM2INT(v_port);
+ domain = NUM2INT(rb_iv_get(self, "@domain"));
+
for(i = 0; i < num_ip; i++){
v_address = RARRAY_PTR(v_addresses)[i];
- addrs->sin_family = NUM2INT(rb_iv_get(self, "@domain"));
- addrs->sin_port = htons(port);
- addrs->sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
- addrs += sizeof(struct sockaddr_in);
+ addrs[i].sin_family = domain;
+ addrs[i].sin_port = htons(port);
+ addrs[i].sin_addr.s_addr = inet_addr(StringValueCStr(v_address));
}
}
for(i = 0; i < size; i++){
v_msg = RARRAY_PTR(v_message)[i];
@@ -472,13 +684,13 @@
fileno,
iov,
size,
(struct sockaddr*)addrs,
num_ip,
- &info,
- sizeof(info),
- SCTP_SENDV_SNDINFO,
+ &spa,
+ sizeof(spa),
+ SCTP_SENDV_SPA,
0
);
if(num_bytes < 0)
rb_raise(rb_eSystemCallError, "sctp_sendv: %s", strerror(errno));
@@ -554,10 +766,13 @@
}
}
#endif
/*
+ * call-seq:
+ * SCTP::Socket.send(options)
+ *
* Send a message on an already-connected socket to a specific association.
*
* Example:
*
* socket = SCTP::Socket.new
@@ -647,10 +862,13 @@
return INT2NUM(num_bytes);
}
/*
+ * call-seq:
+ * SCTP::Socket#sendmsg(options)
+ *
* Transmit a message to an SCTP endpoint. The following hash of options
* is permitted:
*
* :message -> The message to send to the endpoint. Mandatory.
* :stream -> The SCTP stream number you wish to send the message on.
@@ -770,10 +988,13 @@
return INT2NUM(num_bytes);
}
/*
+ * call-seq:
+ * SCTP::Socket#recvmsg(flags=0)
+ *
* Receive a message from another SCTP endpoint.
*
* Example:
*
* begin
@@ -825,192 +1046,13 @@
if(bytes < 0)
rb_raise(rb_eSystemCallError, "sctp_recvmsg: %s", strerror(errno));
v_notification = Qnil;
- if(flags & MSG_NOTIFICATION){
- uint32_t i;
- char str[16];
- union sctp_notification* snp;
- VALUE v_str;
- VALUE* v_temp;
+ if(flags & MSG_NOTIFICATION)
+ v_notification = get_notification_info(buffer);
- snp = (union sctp_notification*)buffer;
-
- switch(snp->sn_header.sn_type){
- case SCTP_ASSOC_CHANGE:
- switch(snp->sn_assoc_change.sac_state){
- case SCTP_COMM_LOST:
- v_str = rb_str_new2("comm lost");
- break;
- case SCTP_COMM_UP:
- v_str = rb_str_new2("comm up");
- break;
- case SCTP_RESTART:
- v_str = rb_str_new2("restart");
- break;
- case SCTP_SHUTDOWN_COMP:
- v_str = rb_str_new2("shutdown complete");
- break;
- case SCTP_CANT_STR_ASSOC:
- v_str = rb_str_new2("association setup failed");
- break;
- default:
- v_str = rb_str_new2("unknown");
- }
-
- v_notification = rb_struct_new(v_assoc_change_struct,
- UINT2NUM(snp->sn_assoc_change.sac_type),
- UINT2NUM(snp->sn_assoc_change.sac_length),
- UINT2NUM(snp->sn_assoc_change.sac_state),
- UINT2NUM(snp->sn_assoc_change.sac_error),
- UINT2NUM(snp->sn_assoc_change.sac_outbound_streams),
- UINT2NUM(snp->sn_assoc_change.sac_inbound_streams),
- UINT2NUM(snp->sn_assoc_change.sac_assoc_id),
- v_str
- );
- break;
- case SCTP_PEER_ADDR_CHANGE:
- switch(snp->sn_paddr_change.spc_state){
- case SCTP_ADDR_AVAILABLE:
- v_str = rb_str_new2("available");
- break;
- case SCTP_ADDR_UNREACHABLE:
- v_str = rb_str_new2("unreachable");
- break;
- case SCTP_ADDR_REMOVED:
- v_str = rb_str_new2("removed from association");
- break;
- case SCTP_ADDR_ADDED:
- v_str = rb_str_new2("added to association");
- break;
- case SCTP_ADDR_MADE_PRIM:
- v_str = rb_str_new2("primary destination");
- break;
- default:
- v_str = rb_str_new2("unknown");
- }
-
- inet_ntop(
- ((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_family,
- &(((struct sockaddr_in *)&snp->sn_paddr_change.spc_aaddr)->sin_addr),
- str,
- sizeof(str)
- );
-
- v_notification = rb_struct_new(v_peeraddr_change_struct,
- UINT2NUM(snp->sn_paddr_change.spc_type),
- UINT2NUM(snp->sn_paddr_change.spc_length),
- rb_str_new2(str),
- UINT2NUM(snp->sn_paddr_change.spc_state),
- UINT2NUM(snp->sn_paddr_change.spc_error),
- UINT2NUM(snp->sn_paddr_change.spc_assoc_id),
- v_str
- );
- break;
- case SCTP_REMOTE_ERROR:
- v_temp = ALLOCA_N(VALUE, snp->sn_remote_error.sre_length);
-
- for(i = 0; i < snp->sn_remote_error.sre_length; i++){
- v_temp[i] = UINT2NUM(snp->sn_remote_error.sre_data[i]);
- }
-
- v_notification = rb_struct_new(v_remote_error_struct,
- UINT2NUM(snp->sn_remote_error.sre_type),
- UINT2NUM(snp->sn_remote_error.sre_flags),
- UINT2NUM(snp->sn_remote_error.sre_length),
- UINT2NUM(snp->sn_remote_error.sre_error),
- UINT2NUM(snp->sn_remote_error.sre_assoc_id),
- rb_ary_new4(snp->sn_remote_error.sre_length, v_temp)
- );
- break;
-#ifdef SCTP_SEND_FAILED_EVENT
- case SCTP_SEND_FAILED_EVENT:
- v_temp = ALLOCA_N(VALUE, snp->sn_send_failed_event.ssf_length);
-
- for(i = 0; i < snp->sn_send_failed_event.ssf_length; i++){
- v_temp[i] = UINT2NUM(snp->sn_send_failed_event.ssf_data[i]);
- }
-
- v_notification = rb_struct_new(v_send_failed_event_struct,
- UINT2NUM(snp->sn_send_failed_event.ssf_type),
- UINT2NUM(snp->sn_send_failed_event.ssf_length),
- UINT2NUM(snp->sn_send_failed_event.ssf_error),
- rb_struct_new(v_sndinfo_struct,
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_sid),
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_flags),
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_ppid),
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_context),
- UINT2NUM(snp->sn_send_failed_event.ssfe_info.snd_assoc_id)
- ),
- UINT2NUM(snp->sn_send_failed_event.ssf_assoc_id),
- rb_ary_new4(snp->sn_send_failed_event.ssf_length, v_temp)
- );
- break;
-#else
- case SCTP_SEND_FAILED:
- v_temp = ALLOCA_N(VALUE, snp->sn_send_failed.ssf_length);
-
- for(i = 0; i < snp->sn_send_failed.ssf_length; i++){
- v_temp[i] = UINT2NUM(snp->sn_send_failed.ssf_data[i]);
- }
-
- v_notification = rb_struct_new(v_send_failed_event_struct,
- UINT2NUM(snp->sn_send_failed.ssf_type),
- UINT2NUM(snp->sn_send_failed.ssf_length),
- UINT2NUM(snp->sn_send_failed.ssf_error),
- Qnil,
- UINT2NUM(snp->sn_send_failed.ssf_assoc_id),
- rb_ary_new4(snp->sn_send_failed.ssf_length, v_temp)
- );
- break;
-#endif
- case SCTP_SHUTDOWN_EVENT:
- v_notification = rb_struct_new(v_shutdown_event_struct,
- UINT2NUM(snp->sn_shutdown_event.sse_type),
- UINT2NUM(snp->sn_shutdown_event.sse_length),
- UINT2NUM(snp->sn_shutdown_event.sse_assoc_id)
- );
- break;
- case SCTP_ADAPTATION_INDICATION:
- v_notification = rb_struct_new(v_adaptation_event_struct,
- UINT2NUM(snp->sn_adaptation_event.sai_type),
- UINT2NUM(snp->sn_adaptation_event.sai_length),
- UINT2NUM(snp->sn_adaptation_event.sai_adaptation_ind),
- UINT2NUM(snp->sn_adaptation_event.sai_assoc_id)
- );
- break;
- case SCTP_PARTIAL_DELIVERY_EVENT:
- v_notification = rb_struct_new(v_partial_delivery_event_struct,
- UINT2NUM(snp->sn_pdapi_event.pdapi_type),
- UINT2NUM(snp->sn_pdapi_event.pdapi_length),
- UINT2NUM(snp->sn_pdapi_event.pdapi_indication),
- UINT2NUM(snp->sn_pdapi_event.pdapi_stream),
- UINT2NUM(snp->sn_pdapi_event.pdapi_seq),
- UINT2NUM(snp->sn_pdapi_event.pdapi_assoc_id)
- );
- break;
- case SCTP_AUTHENTICATION_EVENT:
- v_notification = rb_struct_new(v_auth_event_struct,
- UINT2NUM(snp->sn_authkey_event.auth_type),
- UINT2NUM(snp->sn_authkey_event.auth_length),
- UINT2NUM(snp->sn_authkey_event.auth_keynumber),
- UINT2NUM(snp->sn_authkey_event.auth_indication),
- UINT2NUM(snp->sn_authkey_event.auth_assoc_id)
- );
- break;
- case SCTP_SENDER_DRY_EVENT:
- v_notification = rb_struct_new(v_sender_dry_event_struct,
- UINT2NUM(snp->sn_sender_dry_event.sender_dry_type),
- UINT2NUM(snp->sn_sender_dry_event.sender_dry_flags),
- UINT2NUM(snp->sn_sender_dry_event.sender_dry_length),
- UINT2NUM(snp->sn_sender_dry_event.sender_dry_assoc_id)
- );
- break;
- }
- }
-
if(NIL_P(v_notification))
v_message = rb_str_new(buffer, bytes);
else
v_message = Qnil;
@@ -1026,10 +1068,13 @@
convert_sockaddr_in_to_struct(&clientaddr)
);
}
/*
+ * call-seq:
+ * SCTP::Socket#set_initmsg(options)
+ *
* Set the initial parameters used by the socket when sending out the INIT message.
*
* Example:
*
* socket = SCTP::Socket.new
@@ -1075,10 +1120,13 @@
return self;
}
/*
+ * call-seq:
+ * SCTP::Socket#subscribe(options)
+ *
* Subscribe to various notification type events, which will generate additional
* data that the socket may receive. The possible notification type events are
* as follows:
*
* :association
@@ -1159,10 +1207,13 @@
return self;
}
/*
+ * call-seq:
+ * SCTP::Socket#listen(backlog=128)
+ *
* Marks the socket referred to by sockfd as a passive socket, i.e. a socket that
* will be used to accept incoming connection requests.
*
* The backlog argument defines the maximum length to which the queue of
* pending connections for sockfd may grow. The default value is 128. The
@@ -1202,10 +1253,13 @@
return self;
}
/*
+ * call-seq:
+ * SCTP::Socket#peeloff(association_id)
+ *
* Extracts an association contained by a one-to-many socket connection into
* a one-to-one style socket. Returns the socket descriptor (fileno).
*
* Example:
*
@@ -1232,10 +1286,13 @@
return INT2NUM(assoc_fileno);
}
/*
+ * call-seq:
+ * SCTP::Socket#get_default_send_params
+ *
* Returns the default set of parameters that a call to the sendto function
* uses on this association. This is a struct that contains the following
* members:
*
* * stream
@@ -1276,10 +1333,13 @@
INT2NUM(sndrcv.sinfo_assoc_id)
);
}
/*
+ * call-seq:
+ * SCTP::Socket#get_association_info
+ *
* Returns the association specific parameters. This is a struct
* that contains the following members:
*
* * association_id
* * max_retransmission_count
@@ -1315,10 +1375,13 @@
INT2NUM(assoc.sasoc_cookie_life)
);
}
/*
+ * call-seq:
+ * SCTP::Socket#shutdown
+ *
* Shuts down socket send and receive operations.
*
* Optionally accepts an argument that specifieds the type of shutdown.
* This can be one of the following values:
*
@@ -1349,10 +1412,13 @@
return self;
}
/*
+ * call-seq:
+ * SCTP::Socket#get_retransmission_info
+ *
* Returns the protocol parameters that are used to initialize and bind the
* retransmission timeout (RTO) tunable. This is a struct with the following
* members:
*
* * association_id
@@ -1383,10 +1449,13 @@
INT2NUM(rto.srto_min)
);
}
/*
+ * call-seq:
+ * SCTP::Socket#get_status
+ *
* Get the status of a connected socket.
*
* Example:
*
* socket = SCTP::Socket.new
@@ -1447,10 +1516,13 @@
rb_str_new2(tmpname)
);
}
/*
+ * call-seq:
+ * SCTP::Socket#get_subscriptions
+ *
* Returns a struct of events detailing which events have been
* subscribed to by the socket. The struct contains the following
* members:
*
* * data_io
@@ -1499,10 +1571,31 @@
(events.sctp_stream_change_event ? Qtrue : Qfalse),
(events.sctp_send_failure_event_event ? Qtrue : Qfalse)
);
}
+/*
+ * call-seq:
+ * SCTP::Socket#get_peer_address_params
+ *
+ * Applications can enable or disable heartbeats for any peer address of
+ * an association, modify an address's heartbeat interval, force a
+ * heartbeat to be sent immediately, and adjust the address's maximum
+ * number of retransmissions sent before an address is considered
+ * unreachable.
+ *
+ * This method returns a struct that contains this information. It contains
+ * the following struct members.
+ *
+ * * association_id
+ * * address
+ * * heartbeat_interval
+ * * max_retransmission_count
+ * * path_mtu
+ * * flags
+ * * ipv6_flowlabel
+ */
static VALUE rsctp_get_peer_address_params(VALUE self){
int fileno;
char str[16];
socklen_t size;
sctp_assoc_t assoc_id;
@@ -1523,14 +1616,451 @@
return rb_struct_new(
v_sctp_peer_addr_params_struct,
INT2NUM(paddr.spp_assoc_id),
rb_str_new2(str),
INT2NUM(paddr.spp_hbinterval),
- INT2NUM(paddr.spp_pathmaxrxt)
+ INT2NUM(paddr.spp_pathmaxrxt),
+ INT2NUM(paddr.spp_pathmtu),
+ INT2NUM(paddr.spp_flags),
+ INT2NUM(paddr.spp_ipv6_flowlabel)
);
}
+/*
+ * call-seq:
+ * SCTP::Socket#get_init_msg
+ *
+ * Returns a structure that contains various initialization parameters.
+ *
+ * * num_ostreams: A number representing the number of streams that the
+ * application wishes to be able to send to.
+ *
+ * * max_instreams: The maximum number of inbound streams the application
+ * is prepared to support.
+ *
+ * * max_attempts: The number of attempts the SCTP endpoint should make at
+ * resending the INIT.
+ *
+ * * max_init_timeout: This value represents the largest Timeout or RTO value
+ * (in milliseconds) to use in attempting an INIT.
+ */
+static VALUE rsctp_get_init_msg(VALUE self){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ struct sctp_initmsg initmsg;
+
+ bzero(&initmsg, sizeof(initmsg));
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ size = sizeof(struct sctp_initmsg);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_INITMSG, (void*)&initmsg, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return rb_struct_new(
+ v_sctp_initmsg_struct,
+ INT2NUM(initmsg.sinit_num_ostreams),
+ INT2NUM(initmsg.sinit_max_instreams),
+ INT2NUM(initmsg.sinit_max_attempts),
+ INT2NUM(initmsg.sinit_max_init_timeo)
+ );
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#nodelay?
+ *
+ * Returns whether or not the nodelay option has been set.
+ */
+static VALUE rsctp_get_nodelay(VALUE self){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ int value;
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ size = sizeof(int);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ if(value)
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#nodelay=(bool)
+ *
+ * Turn on/off any Nagle-like algorithm. This means that packets are generally
+ * sent as soon as possible and no unnecessary delays are introduced, at the
+ * cost of more packets in the network.
+ */
+static VALUE rsctp_set_nodelay(VALUE self, VALUE v_bool){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ int value;
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ size = sizeof(int);
+
+ if(NIL_P(v_bool) || v_bool == Qfalse)
+ value = 0;
+ else
+ value = 1;
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_NODELAY, (void*)&value, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ if(value)
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#autoclose
+ *
+ * Returns the number of seconds before socket associations automatically
+ * shut down.
+ */
+static VALUE rsctp_get_autoclose(VALUE self){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ int value;
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ size = sizeof(int);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return INT2NUM(value);
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#autoclose=(seconds=0)
+ *
+ * When set it will cause associations that are idle for more than the specified
+ * number of seconds to automatically close using the graceful shutdown
+ * procedure. An association being idle is defined as an association that has
+ * NOT sent or received user data.
+ *
+ * The special value of 0 indicates that no automatic close of any associations
+ * should be performed, this is the default value. The option expects an integer
+ * defining the number of seconds of idle time before an association is closed.
+ *
+ * An application using this option should enable receiving the association
+ * change notification. This is the only mechanism an application is informed
+ * about the closing of an association. After an association is closed, the
+ * association ID assigned to it can be reused. An application should be aware
+ * of this to avoid the possible problem of sending data to an incorrect peer
+ * end point.
+ *
+ * This socket option is applicable to the one-to-many style socket only.
+ */
+static VALUE rsctp_set_autoclose(VALUE self, VALUE v_seconds){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ int value;
+
+ value = NUM2INT(v_seconds);
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ size = sizeof(int);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTOCLOSE, (void*)&value, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return v_seconds;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#enable_auth_support(association_id=nil)
+ *
+ * Enables auth for future associations.
+ */
+static VALUE rsctp_enable_auth_support(int argc, VALUE* argv, VALUE self){
+ int fileno;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ struct sctp_assoc_value assoc_value;
+ VALUE v_assoc_id;
+
+ rb_scan_args(argc, argv, "01", &v_assoc_id);
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ size = sizeof(struct sctp_assoc_value);
+
+ if(NIL_P(v_assoc_id))
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ else
+ assoc_id = NUM2INT(v_assoc_id);
+
+ assoc_value.assoc_id = assoc_id;
+ assoc_value.assoc_value = 1;
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_SUPPORTED, (void*)&assoc_value, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#set_shared_key(key, keynum, association_id=nil)
+ *
+ * This option will set a shared secret key which is used to build an
+ * association shared key.
+ *
+ * The +key+ parameter should be a string (converted to an array of bytes
+ * internally) that is to be used by the endpoint (or association) as the
+ * shared secret key. If an empty string is used, then a null key is set.
+ *
+ * The +keynum+ parameter is the shared key identifier by which the
+ * application will refer to this key. If a key of the specified index already
+ * exists, then this new key will replace the old existing key. Note that
+ * shared key identifier '0' defaults to a null key.
+ *
+ * The +association_id+, if non-zero, indicates what association that the shared
+ * key is being set upon. If this argument is zero, then the shared key is set
+ * upon the endpoint and all future associations will use this key (if not
+ * changed by subsequent calls). By default this is the result of the
+ * SCTP::Socket#association_id method.
+ *
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
+ * option will set a key on the association if the socket is connected,
+ * otherwise this will set a key on the endpoint.
+*/
+static VALUE rsctp_set_shared_key(int argc, VALUE* argv, VALUE self){
+ int fileno, len;
+ char* key;
+ uint keynum;
+ socklen_t size;
+ sctp_assoc_t assoc_id;
+ struct sctp_authkey* auth_key;
+ VALUE v_key, v_keynumber, v_assoc_id;
+
+ rb_scan_args(argc, argv, "12", &v_key, &v_keynumber, &v_assoc_id);
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ key = StringValuePtr(v_key);
+ len = strlen(key);
+ unsigned char byte_array[len+1];
+
+ for(int i = 0; i < len; i++)
+ byte_array[i] = key[i];
+
+ byte_array[len] = '\0';
+
+ auth_key = malloc(sizeof(auth_key) + sizeof(char[strlen(key)+1]));
+ size = sizeof(auth_key);
+
+ if(NIL_P(v_assoc_id))
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ else
+ assoc_id = NUM2INT(v_assoc_id);
+
+ if(NIL_P(v_keynumber))
+ keynum = 1;
+ else
+ keynum = NUM2INT(v_keynumber);
+
+ auth_key->sca_assoc_id = assoc_id;
+ auth_key->sca_keynumber = keynum;
+ auth_key->sca_keylength = strlen(key);
+ memcpy(auth_key->sca_key, byte_array, sizeof(byte_array));
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_KEY, (void*)auth_key, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#get_active_shared_key(keynum, association_id=nil)
+ *
+ * Gets the active shared key to be used to build the association shared key.
+ */
+static VALUE rsctp_get_active_shared_key(int argc, VALUE* argv, VALUE self){
+ int fileno;
+ socklen_t size;
+ struct sctp_authkeyid authkey;
+ sctp_assoc_t assoc_id;
+ VALUE v_assoc_id, v_keynum;
+ uint keynum;
+
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
+
+ bzero(&authkey, sizeof(authkey));
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ keynum = NUM2UINT(v_keynum);
+
+ if(NIL_P(v_assoc_id))
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ else
+ assoc_id = NUM2INT(v_assoc_id);
+
+ authkey.scact_assoc_id = assoc_id;
+ authkey.scact_keynumber = keynum;
+
+ size = sizeof(struct sctp_authkeyid);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return INT2NUM(authkey.scact_keynumber);
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#set_active_shared_key(keynum, association_id=nil)
+ *
+ * Sets the active shared key to be used to build the association shared key.
+ *
+ * Th +keynum+ parameter is the shared key identifier which the application is
+ * requesting to become the active shared key to be used for sending
+ * authenticated chunks. The key identifier MUST correspond to an existing
+ * shared key. Note that shared key identifier '0' defaults to a null key.
+ *
+ * The association_idparameter, if non-zero, indicates what association that
+ * the shared key identifier is being set active upon. If this element contains
+ * zero, then the activation applies to the endpoint and all future
+ * associations will use the specified shared key identifier.
+ *
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
+ * option will set the active key on the association if the socket is connected,
+ * otherwise this will set the default active key for the endpoint.
+ *
+ * By default, the association_id is the result of SCTP::Socket#association_id.
+ */
+static VALUE rsctp_set_active_shared_key(int argc, VALUE* argv, VALUE self){
+ int fileno;
+ socklen_t size;
+ struct sctp_authkeyid authkey;
+ sctp_assoc_t assoc_id;
+ VALUE v_assoc_id, v_keynum;
+ uint keynum;
+
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
+
+ keynum = NUM2UINT(v_keynum);
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+
+ if(NIL_P(v_assoc_id))
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ else
+ assoc_id = NUM2INT(v_assoc_id);
+
+ authkey.scact_assoc_id = assoc_id;
+ authkey.scact_keynumber = keynum;
+ size = sizeof(struct sctp_authkeyid);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_ACTIVE_KEY, (void*)&authkey, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#delete_shared_key(keynum, association_id=nil)
+ *
+ * Delete a shared secret key from use.
+ *
+ * The +keynum+ parameter is the shared key identifier which the application
+ * is requesting to be deleted. The key identifier MUST correspond to an
+ * existing shared key and MUST NOT be the current active key.
+ *
+ * If this parameter is zero, use of the null key identifier '0' is disabled
+ * on the endpoint and/or association.
+ *
+ * The +association_id+ parameter, if non-zero, indicates what association that
+ * the shared key identifier is being deleted from. By default this is the
+ * association that's returned via SCTP::Socket#association_id.
+ *
+ * If set to zero, then the shared key is deleted from the endpoint and
+ * and ALL associations will no longer use the specified shared key identifier
+ * (unless otherwise set on the association using SCTP_AUTH_KEY).
+ *
+ * For one-to-one sockets, this parameter is ignored. Note, however, that this
+ * option will delete the key from the association if the socket is connected,
+ * otherwise this will delete the key from the endpoint.
+ */
+static VALUE rsctp_delete_shared_key(int argc, VALUE* argv, VALUE self){
+ int fileno;
+ socklen_t size;
+ struct sctp_authkeyid authkey;
+ sctp_assoc_t assoc_id;
+ VALUE v_assoc_id, v_keynum;
+ uint keynum;
+
+ rb_scan_args(argc, argv, "11", &v_keynum, &v_assoc_id);
+
+ bzero(&authkey, sizeof(authkey));
+
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ keynum = NUM2UINT(v_keynum);
+
+ if(NIL_P(v_assoc_id))
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+ else
+ assoc_id = NUM2INT(v_assoc_id);
+
+ authkey.scact_assoc_id = assoc_id;
+ authkey.scact_keynumber = keynum;
+
+ size = sizeof(struct sctp_authkeyid);
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_AUTH_DELETE_KEY, (void*)&authkey, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return INT2NUM(authkey.scact_keynumber);
+}
+
+/*
+ * call-seq:
+ * SCTP::Socket#map_ipv4=(bool)
+ *
+ * If set to true and the socket is type PF_INET6, then IPv4 addresses will be
+ * mapped to V6 representation. If set to false (the default), then no mapping
+ * will be done of V4 addresses and a user will receive both PF_INET6 and
+ * PF_INET type addresses on the socket.
+ */
+static VALUE rsctp_map_ipv4(VALUE self, VALUE v_bool){
+ int fileno, boolean;
+ sctp_assoc_t assoc_id;
+ socklen_t size;
+
+ boolean = 0;
+ fileno = NUM2INT(rb_iv_get(self, "@fileno"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
+
+ if(v_bool == Qtrue)
+ boolean = 1;
+
+ if(sctp_opt_info(fileno, assoc_id, SCTP_I_WANT_MAPPED_V4_ADDR, (void*)&boolean, &size) < 0)
+ rb_raise(rb_eSystemCallError, "sctp_opt_info: %s", strerror(errno));
+
+ return v_bool;
+}
+
void Init_socket(void){
mSCTP = rb_define_module("SCTP");
cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
v_sndrcv_struct = rb_struct_define(
@@ -1617,27 +2147,41 @@
"cumtsn", "context", "assocation_id", NULL
);
v_sctp_peer_addr_params_struct = rb_struct_define(
"PeerAddressParams", "association_id", "address", "heartbeat_interval",
- "max_retransmission_count", NULL
+ "max_retransmission_count", "path_mtu", "flags",
+ "ipv6_flowlabel", NULL
);
+ v_sctp_initmsg_struct = rb_struct_define(
+ "InitMsg", "num_ostreams", "max_instreams", "max_attempts", "max_init_timeout", NULL
+ );
+
rb_define_method(cSocket, "initialize", rsctp_init, -1);
+ rb_define_method(cSocket, "autoclose=", rsctp_set_autoclose, 1);
rb_define_method(cSocket, "bindx", rsctp_bindx, -1);
rb_define_method(cSocket, "close", rsctp_close, 0);
rb_define_method(cSocket, "connectx", rsctp_connectx, -1);
+ rb_define_method(cSocket, "delete_shared_key", rsctp_delete_shared_key, -1);
+ rb_define_method(cSocket, "enable_auth_support", rsctp_enable_auth_support, -1);
rb_define_method(cSocket, "getpeernames", rsctp_getpeernames, -1);
rb_define_method(cSocket, "getlocalnames", rsctp_getlocalnames, -1);
- rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
+ rb_define_method(cSocket, "get_active_shared_key", rsctp_get_active_shared_key, -1);
+ rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
+ rb_define_method(cSocket, "get_autoclose", rsctp_get_autoclose, 0);
rb_define_method(cSocket, "get_default_send_params", rsctp_get_default_send_params, 0);
+ rb_define_method(cSocket, "get_initmsg", rsctp_get_init_msg, 0);
+ rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
rb_define_method(cSocket, "get_retransmission_info", rsctp_get_retransmission_info, 0);
- rb_define_method(cSocket, "get_association_info", rsctp_get_association_info, 0);
+ rb_define_method(cSocket, "get_status", rsctp_get_status, 0);
rb_define_method(cSocket, "get_subscriptions", rsctp_get_subscriptions, 0);
- rb_define_method(cSocket, "get_peer_address_params", rsctp_get_peer_address_params, 0);
rb_define_method(cSocket, "listen", rsctp_listen, -1);
+ rb_define_method(cSocket, "map_ipv4=", rsctp_map_ipv4, 1);
+ rb_define_method(cSocket, "nodelay?", rsctp_get_nodelay, 0);
+ rb_define_method(cSocket, "nodelay=", rsctp_set_nodelay, 1);
rb_define_method(cSocket, "peeloff", rsctp_peeloff, 1);
rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
rb_define_method(cSocket, "send", rsctp_send, 1);
#ifdef HAVE_SCTP_SENDV
@@ -1647,21 +2191,24 @@
#ifdef HAVE_SCTP_RECVV
rb_define_method(cSocket, "recvv", rsctp_recvv, -1);
#endif
rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
+ rb_define_method(cSocket, "set_active_shared_key", rsctp_set_active_shared_key, -1);
rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 1);
+ //rb_define_method(cSocket, "set_retransmission_info", rsctp_set_retransmission_info, -1);
+ rb_define_method(cSocket, "set_shared_key", rsctp_set_shared_key, -1);
rb_define_method(cSocket, "shutdown", rsctp_shutdown, -1);
rb_define_method(cSocket, "subscribe", rsctp_subscribe, 1);
rb_define_attr(cSocket, "domain", 1, 1);
rb_define_attr(cSocket, "type", 1, 1);
rb_define_attr(cSocket, "fileno", 1, 1);
rb_define_attr(cSocket, "association_id", 1, 1);
rb_define_attr(cSocket, "port", 1, 1);
- /* 0.1.0: The version of this library */
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.0"));
+ /* 0.1.1: The version of this library */
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.1.1"));
/* send flags */
/* Message is unordered */
rb_define_const(cSocket, "SCTP_UNORDERED", INT2NUM(SCTP_UNORDERED));