/*
 * 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 rb_str_subseq(str, w, a.buflen - w);
}