summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
Diffstat (limited to 'ext/socket')
-rw-r--r--ext/socket/ancdata.c82
-rw-r--r--ext/socket/basicsocket.c7
-rw-r--r--ext/socket/lib/socket.rb50
-rw-r--r--ext/socket/rubysocket.h14
4 files changed, 75 insertions, 78 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 877975e4df..7e0441c042 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -3,7 +3,7 @@
#include <time.h>
int rsock_cmsg_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
-static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
+static VALUE sym_wait_readable, sym_wait_writable;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
static VALUE rb_cAncillaryData;
@@ -1128,14 +1128,13 @@ rb_sendmsg(int fd, const struct msghdr *msg, int flags)
}
static VALUE
-bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
+bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex,
+ int nonblock)
{
rb_io_t *fptr;
- VALUE data, vflags, dest_sockaddr;
struct msghdr mh;
struct iovec iov;
- VALUE opts = Qnil;
- VALUE controls = Qnil;
int controls_num;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
VALUE controls_str = 0;
@@ -1149,15 +1148,11 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
family = rsock_getfamily(fptr);
#endif
- data = vflags = dest_sockaddr = Qnil;
-
- if (argc == 0)
- rb_raise(rb_eArgError, "mesg argument required");
-
- rb_scan_args(argc, argv, "12*:", &data, &vflags, &dest_sockaddr, &controls,
- &opts);
-
StringValue(data);
+
+ if (!RB_TYPE_P(controls, T_ARRAY)) {
+ controls = rb_ary_new();
+ }
controls_num = RARRAY_LENINT(controls);
if (controls_num) {
@@ -1285,7 +1280,7 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
goto retry;
}
if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN)) {
- if (rsock_opt_false_p(opts, sym_exception)) {
+ if (ex == Qfalse) {
return sym_wait_writable;
}
rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE,
@@ -1302,64 +1297,22 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
#endif
#if defined(HAVE_SENDMSG)
-/*
- * call-seq:
- * basicsocket.sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) => numbytes_sent
- *
- * sendmsg sends a message using sendmsg(2) system call in blocking manner.
- *
- * _mesg_ is a string to send.
- *
- * _flags_ is bitwise OR of MSG_* constants such as Socket::MSG_OOB.
- *
- * _dest_sockaddr_ is a destination socket address for connection-less socket.
- * It should be a sockaddr such as a result of Socket.sockaddr_in.
- * An Addrinfo object can be used too.
- *
- * _controls_ is a list of ancillary data.
- * The element of _controls_ should be Socket::AncillaryData or
- * 3-elements array.
- * The 3-element array should contains cmsg_level, cmsg_type and data.
- *
- * The return value, _numbytes_sent_ is an integer which is the number of bytes sent.
- *
- * sendmsg can be used to implement send_io as follows:
- *
- * # use Socket::AncillaryData.
- * ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, io.fileno)
- * sock.sendmsg("a", 0, nil, ancdata)
- *
- * # use 3-element array.
- * ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")]
- * sock.sendmsg("\0", 0, nil, ancdata)
- *
- */
VALUE
-rsock_bsock_sendmsg(int argc, VALUE *argv, VALUE sock)
+rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, VALUE dest_sockaddr,
+ VALUE controls)
{
- return bsock_sendmsg_internal(argc, argv, sock, 0);
+ return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr, controls,
+ Qtrue, 0);
}
#endif
#if defined(HAVE_SENDMSG)
-/*
- * call-seq:
- * basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent
- *
- * sendmsg_nonblock sends a message using sendmsg(2) system call in non-blocking manner.
- *
- * It is similar to BasicSocket#sendmsg
- * but the non-blocking flag is set before the system call
- * and it doesn't retry the system call.
- *
- * By specifying `exception: false`, the _opts_ hash allows you to indicate
- * that sendmsg_nonblock should not raise an IO::WaitWritable exception, but
- * return the symbol :wait_writable instead.
- */
VALUE
-rsock_bsock_sendmsg_nonblock(int argc, VALUE *argv, VALUE sock)
+rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex)
{
- return bsock_sendmsg_internal(argc, argv, sock, 1);
+ return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr,
+ controls, ex, 1);
}
#endif
@@ -1773,7 +1726,6 @@ rsock_init_ancdata(void)
rb_define_method(rb_cAncillaryData, "ipv6_pktinfo_ifindex", ancillary_ipv6_pktinfo_ifindex, 0);
#endif
#undef rb_intern
- sym_exception = ID2SYM(rb_intern("exception"));
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
}
diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c
index 1a0120cb27..eef66d4803 100644
--- a/ext/socket/basicsocket.c
+++ b/ext/socket/basicsocket.c
@@ -724,10 +724,11 @@ rsock_init_basicsocket(void)
rb_define_private_method(rb_cBasicSocket,
"__recv_nonblock", bsock_recv_nonblock, 4);
- rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1); /* in ancdata.c */
- rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1); /* in ancdata.c */
-
/* in ancdata.c */
+ rb_define_private_method(rb_cBasicSocket, "__sendmsg",
+ rsock_bsock_sendmsg, 4);
+ rb_define_private_method(rb_cBasicSocket, "__sendmsg_nonblock",
+ rsock_bsock_sendmsg_nonblock, 5);
rb_define_private_method(rb_cBasicSocket, "__recvmsg",
rsock_bsock_recvmsg, 4);
rb_define_private_method(rb_cBasicSocket, "__recvmsg_nonblock",
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index 9e85318c1b..705a0b8459 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -276,6 +276,56 @@ class BasicSocket < IO
end
# call-seq:
+ # basicsocket.sendmsg(mesg, flags=0, dest_sockaddr=nil, *controls) => numbytes_sent
+ #
+ # sendmsg sends a message using sendmsg(2) system call in blocking manner.
+ #
+ # _mesg_ is a string to send.
+ #
+ # _flags_ is bitwise OR of MSG_* constants such as Socket::MSG_OOB.
+ #
+ # _dest_sockaddr_ is a destination socket address for connection-less socket.
+ # It should be a sockaddr such as a result of Socket.sockaddr_in.
+ # An Addrinfo object can be used too.
+ #
+ # _controls_ is a list of ancillary data.
+ # The element of _controls_ should be Socket::AncillaryData or
+ # 3-elements array.
+ # The 3-element array should contains cmsg_level, cmsg_type and data.
+ #
+ # The return value, _numbytes_sent_ is an integer which is the number of bytes sent.
+ #
+ # sendmsg can be used to implement send_io as follows:
+ #
+ # # use Socket::AncillaryData.
+ # ancdata = Socket::AncillaryData.int(:UNIX, :SOCKET, :RIGHTS, io.fileno)
+ # sock.sendmsg("a", 0, nil, ancdata)
+ #
+ # # use 3-element array.
+ # ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")]
+ # sock.sendmsg("\0", 0, nil, ancdata)
+ def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
+ __sendmsg(mesg, flags, dest_sockaddr, controls)
+ end
+
+ # call-seq:
+ # basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent
+ #
+ # sendmsg_nonblock sends a message using sendmsg(2) system call in non-blocking manner.
+ #
+ # It is similar to BasicSocket#sendmsg
+ # but the non-blocking flag is set before the system call
+ # and it doesn't retry the system call.
+ #
+ # By specifying `exception: false`, the _opts_ hash allows you to indicate
+ # that sendmsg_nonblock should not raise an IO::WaitWritable exception, but
+ # return the symbol :wait_writable instead.
+ def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
+ exception: true)
+ __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception)
+ end
+
+ # call-seq:
# basicsocket.recv_nonblock(maxlen [, flags [, buf [, options ]]]) => mesg
#
# Receives up to _maxlen_ bytes from +socket+ using recvfrom(2) after
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index 652876cc89..2135ea4a0b 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -361,8 +361,10 @@ VALUE rsock_sock_listen(VALUE sock, VALUE log);
VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data);
#if defined(HAVE_SENDMSG)
-VALUE rsock_bsock_sendmsg(int argc, VALUE *argv, VALUE sock);
-VALUE rsock_bsock_sendmsg_nonblock(int argc, VALUE *argv, VALUE sock);
+VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls);
+VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags,
+ VALUE dest_sockaddr, VALUE controls, VALUE ex);
#else
#define rsock_bsock_sendmsg rb_f_notimplement
#define rsock_bsock_sendmsg_nonblock rb_f_notimplement
@@ -437,12 +439,4 @@ static inline void rsock_maybe_wait_fd(int fd) { }
# define MSG_DONTWAIT_RELIABLE 0
#endif
-static inline int
-rsock_opt_false_p(VALUE opt, VALUE sym)
-{
- if (!NIL_P(opt) && Qfalse == rb_hash_lookup2(opt, sym, Qundef))
- return 1;
- return 0;
-}
-
#endif