/*
* call-seq:
*
* s = Kgio::Socket.new(:INET, :STREAM)
* addr = Socket.pack_sockaddr_in(80, "example.com")
* s.kgio_fastopen("hello world", addr) -> nil
*
* Starts a TCP connection using TCP Fast Open. This uses a blocking
* sendto() syscall and is only available on Ruby 1.9 or later.
* This raises exceptions (including Errno::EINPROGRESS/Errno::EAGAIN)
* on errors. Using this is only recommended for blocking sockets.
*
* Timeouts may be set with setsockopt:
*
* s.setsockopt(:SOCKET, :SNDTIMEO, [1,0].pack("l_l_"))
*/
static VALUE fastopen(VALUE sock, VALUE buf, VALUE addr)
{
struct tfo_args a;
VALUE str = (TYPE(buf) == T_STRING) ? buf : rb_obj_as_string(buf);
ssize_t w;
a.fd = my_fileno(sock);
a.buf = RSTRING_PTR(str);
a.buflen = (size_t)RSTRING_LEN(str);
a.addr = sockaddr_from(&a.addrlen, addr);
/* n.b. rb_thread_blocking_region preserves errno */
w = (ssize_t)rb_thread_io_blocking_region(tfo_sendto, &a, a.fd);
if (w < 0)
rb_sys_fail("sendto");
if ((size_t)w == a.buflen)
return Qnil;
return MY_STR_SUBSEQ(str, w, a.buflen - w);
}