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")); }