ext/sctp/socket.c in sctp-socket-0.0.1 vs ext/sctp/socket.c in sctp-socket-0.0.2
- old
+ new
@@ -213,61 +213,80 @@
rb_raise(rb_eSystemCallError, "close: %s", strerror(errno));
return self;
}
+/*
+ * Return an array of all addresses of a peer.
+ */
static VALUE rsctp_getpeernames(VALUE self){
- VALUE v_assoc_id = rb_iv_get(self, "@assocation_id");
sctp_assoc_t assoc_id;
struct sockaddr* addrs;
int i, sock_fd, num_addrs;
+ char str[16];
+ VALUE v_array = rb_ary_new();
bzero(&addrs, sizeof(addrs));
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
- assoc_id = NUM2INT(v_assoc_id);
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
num_addrs = sctp_getpaddrs(sock_fd, assoc_id, &addrs);
if(num_addrs < 0){
sctp_freepaddrs(addrs);
rb_raise(rb_eSystemCallError, "sctp_getpaddrs: %s", strerror(errno));
}
for(i = 0; i < num_addrs; i++){
- // TODO: Create and return array of IpAddr objects
+ inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
+ rb_ary_push(v_array, rb_str_new2(str));
+ bzero(&str, sizeof(str));
}
sctp_freepaddrs(addrs);
- return self;
+ return v_array;
}
+/*
+ * Return an array of local addresses that are part of the association.
+ *
+ * Example:
+ *
+ * socket = SCTP::Socket.new
+ * socket.bind(:addresses => ['10.0.4.5', '10.0.5.5'])
+ * socket.getlocalnames # => ['10.0.4.5', '10.0.5.5'])
+ */
static VALUE rsctp_getlocalnames(VALUE self){
sctp_assoc_t assoc_id;
struct sockaddr* addrs;
int i, sock_fd, num_addrs;
+ char str[16];
+ VALUE v_array = rb_ary_new();
bzero(&addrs, sizeof(addrs));
sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
- assoc_id = NUM2INT(rb_iv_get(self, "@assocation_id"));
+ assoc_id = NUM2INT(rb_iv_get(self, "@association_id"));
num_addrs = sctp_getladdrs(sock_fd, assoc_id, &addrs);
if(num_addrs < 0){
sctp_freeladdrs(addrs);
rb_raise(rb_eSystemCallError, "sctp_getladdrs: %s", strerror(errno));
}
for(i = 0; i < num_addrs; i++){
- // TODO: Create and return array of IpAddr objects
+ inet_ntop(AF_INET, &(((struct sockaddr_in *)&addrs[i])->sin_addr), str, sizeof(str));
+ rb_ary_push(v_array, rb_str_new2(str));
+ bzero(&str, sizeof(str));
}
sctp_freeladdrs(addrs);
- return self;
+ return v_array;
}
/*
* Transmit a message to an SCTP endpoint. The following hash of options
* is permitted:
@@ -472,16 +491,25 @@
UINT2NUM(sndrcvinfo.sinfo_assoc_id)
);
}
/*
- * {
- * :output_streams => 2,
- * :input_streams => 3,
- * :max_attempts => 5,
- * :timeout => 30
- * }
+ * Set the initial parameters used by the socket when sending out the INIT message.
+ *
+ * Example:
+ *
+ * socket = SCTP::Socket.new
+ * socket.set_initmsg(:output_streams => 5, :input_streams => 5, :max_attempts => 4, :timeout => 30)
+ *
+ * The following parameters can be configured:
+ *
+ * :output_streams - The number of outbound SCTP streams an application would like to request.
+ * :input_streams - The maximum number of inbound streams an application is prepared to allow.
+ * :max_attempts - How many times the the SCTP stack should send the initial INIT message before it's considered unreachable.
+ * :timeout - The maximum RTO value for the INIT timer.
+ *
+ * By default these values are set to zero (i.e. ignored).
*/
static VALUE rsctp_set_initmsg(VALUE self, VALUE v_options){
int sock_fd;
struct sctp_initmsg initmsg;
VALUE v_output, v_input, v_attempts, v_timeout;
@@ -643,17 +671,39 @@
rb_iv_set(self, "@sock_fd", INT2NUM(new_sock_fd));
return self;
}
+static VALUE rsctp_shutdown(int argc, VALUE* argv, VALUE self){
+ int how, sock_fd;
+ VALUE v_how;
+
+ sock_fd = NUM2INT(rb_iv_get(self, "@sock_fd"));
+
+ rb_scan_args(argc, argv, "01", &v_how);
+
+ if(NIL_P(v_how)){
+ how = SHUT_RDWR;
+ }
+ else{
+ Check_Type(v_how, T_FIXNUM);
+ how = NUM2INT(v_how);
+ }
+
+ if(shutdown(sock_fd, how) < 0)
+ rb_raise(rb_eSystemCallError, "shutdown: %s", strerror(errno));
+
+ return self;
+}
+
void Init_socket(){
mSCTP = rb_define_module("SCTP");
cSocket = rb_define_class_under(mSCTP, "Socket", rb_cObject);
v_sndrcv_struct = rb_struct_define(
"SndRecvInfo", "message", "stream", "flags",
- "ppid", "context", "ttl", "assoc_id", NULL
+ "ppid", "context", "ttl", "association_id", NULL
);
rb_define_method(cSocket, "initialize", rsctp_init, -1);
rb_define_method(cSocket, "bind", rsctp_bind, -1);
@@ -664,16 +714,17 @@
rb_define_method(cSocket, "listen", rsctp_listen, -1);
rb_define_method(cSocket, "peeloff!", rsctp_peeloff, 1);
rb_define_method(cSocket, "recvmsg", rsctp_recvmsg, -1);
rb_define_method(cSocket, "sendmsg", rsctp_sendmsg, 1);
rb_define_method(cSocket, "set_initmsg", rsctp_set_initmsg, 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, "sock_fd", 1, 1);
rb_define_attr(cSocket, "association_id", 1, 1);
rb_define_attr(cSocket, "port", 1, 1);
- /* 0.0.1: The version of this library */
- rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.1"));
+ /* 0.0.2: The version of this library */
+ rb_define_const(cSocket, "VERSION", rb_str_new2("0.0.2"));
}