* AF_UNSPEC
* @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
* @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
+ * @tfo: flag to enable TCP Fast Open
+ * @ba_ret: BIO_ADDR that was connected to for TFO, to be freed by caller
*
* This will create a socket and use it to connect to a host:port, or if
* family == AF_UNIX, to the path found in host.
*/
int init_client(int *sock, const char *host, const char *port,
const char *bindhost, const char *bindport,
- int family, int type, int protocol)
+ int family, int type, int protocol, int tfo,
+ BIO_ADDR **ba_ret)
{
BIO_ADDRINFO *res = NULL;
BIO_ADDRINFO *bindaddr = NULL;
const BIO_ADDRINFO *bi = NULL;
int found = 0;
int ret;
+ int options = 0;
+
+ if (tfo && ba_ret != NULL)
+ *ba_ret = NULL;
if (BIO_sock_init() != 1)
return 0;
BIO_free(tmpbio);
}
#endif
+ if (BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP) {
+ options |= BIO_SOCK_NODELAY;
+ if (tfo)
+ options |= BIO_SOCK_TFO;
+ }
- if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
- BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
+ if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), options)) {
BIO_closesocket(*sock);
*sock = INVALID_SOCKET;
continue;
}
+ /* Save the address */
+ if (tfo && ba_ret != NULL)
+ *ba_ret = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
+
/* Success, don't try any more addresses */
break;
}
*/
int do_server(int *accept_sock, const char *host, const char *port,
int family, int type, int protocol, do_server_cb cb,
- unsigned char *context, int naccept, BIO *bio_s_out)
+ unsigned char *context, int naccept, BIO *bio_s_out,
+ int tfo)
{
int asock = 0;
int sock;
sock_protocol = BIO_ADDRINFO_protocol(res);
sock_address = BIO_ADDRINFO_address(res);
next = BIO_ADDRINFO_next(res);
+ if (tfo && sock_type == SOCK_STREAM)
+ sock_options |= BIO_SOCK_TFO;
#ifdef AF_INET6
if (sock_family == AF_INET6)
sock_options |= BIO_SOCK_V6_ONLY;