/* * call-seq: * unixsocket.peeraddr => [address_family, unix_path] * * Returns the remote address as an array which contains * address_family and unix_path. * * Example * serv = UNIXServer.new("/tmp/sock") * c = UNIXSocket.new("/tmp/sock") * p c.peeraddr #=> ["AF_UNIX", "/tmp/sock"] */ static VALUE unix_peeraddr(VALUE sock) { rb_io_t *fptr; struct sockaddr_un addr; socklen_t len = (socklen_t)sizeof addr; GetOpenFile(sock, fptr); if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getpeername(2)"); return rsock_unixaddr(&addr, len); }
/* * call-seq: * unixsocket.addr => [address_family, unix_path] * * Returns the local address as an array which contains * address_family and unix_path. * * Example * serv = UNIXServer.new("/tmp/sock") * p serv.addr #=> ["AF_UNIX", "/tmp/sock"] */ static VALUE unix_addr(VALUE sock) { rb_io_t *fptr; struct sockaddr_un addr; socklen_t len = (socklen_t)sizeof addr; socklen_t len0 = len; GetOpenFile(sock, fptr); if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rsock_sys_fail_path("getsockname(2)", fptr->pathv); if (len0 < len) len = len0; return rsock_unixaddr(&addr, len); }
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) { rb_io_t *fptr; VALUE str, klass; struct recvfrom_arg arg; VALUE len, flg; long buflen; long slen; rb_scan_args(argc, argv, "11", &len, &flg); if (flg == Qnil) arg.flags = 0; else arg.flags = NUM2INT(flg); buflen = NUM2INT(len); GetOpenFile(sock, fptr); if (rb_io_read_pending(fptr)) { rb_raise(rb_eIOError, "recv for buffered IO"); } arg.fd = fptr->fd; arg.alen = (socklen_t)sizeof(arg.buf); arg.str = str = rb_tainted_str_new(0, buflen); klass = RBASIC(str)->klass; rb_obj_hide(str); while (rb_io_check_closed(fptr), rsock_maybe_wait_fd(arg.fd), (slen = BLOCKING_REGION_FD(recvfrom_blocking, &arg)) < 0) { if (!rb_io_wait_readable(fptr->fd)) { rb_sys_fail("recvfrom(2)"); } if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) { rb_raise(rb_eRuntimeError, "buffer string modified"); } } rb_obj_reveal(str, klass); if (slen < RSTRING_LEN(str)) { rb_str_set_len(str, slen); } rb_obj_taint(str); switch (from) { case RECV_RECV: return str; case RECV_IP: #if 0 if (arg.alen != sizeof(struct sockaddr_in)) { rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); } #endif if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP)); else return rb_assoc_new(str, Qnil); #ifdef HAVE_SYS_UN_H case RECV_UNIX: return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen)); #endif case RECV_SOCKET: return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, &arg.buf.addr, arg.alen)); default: rb_bug("rsock_s_recvfrom called with bad value"); } }