From c1c1837bec5abb2079b139c66da44c568d20f608 Mon Sep 17 00:00:00 2001 From: shanth96 Date: Tue, 12 Sep 2023 23:43:32 +0400 Subject: [PATCH] allow setting tcp nodelay --- contrib/ruby/ext/trilogy-ruby/cext.c | 13 +++++++++---- inc/trilogy/socket.h | 2 ++ src/socket.c | 8 ++++++++ test/client/connect_test.c | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/contrib/ruby/ext/trilogy-ruby/cext.c b/contrib/ruby/ext/trilogy-ruby/cext.c index 7e128e1a..d5cf610d 100644 --- a/contrib/ruby/ext/trilogy-ruby/cext.c +++ b/contrib/ruby/ext/trilogy-ruby/cext.c @@ -22,10 +22,10 @@ static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLErro static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows, id_connect_timeout, id_read_timeout, id_write_timeout, id_keepalive_enabled, id_keepalive_idle, id_keepalive_interval, id_keepalive_count, - id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, id_ivar_query_time, id_password, - id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key, - id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement, id_multi_result, - id_from_code, id_from_errno, id_connection_options, id_max_allowed_packet; + id_tcp_nodelay_enabled, id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, + id_ivar_query_time, id_password, id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, + id_ssl_crlpath, id_ssl_key, id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, + id_multi_statement, id_multi_result, id_from_code, id_from_errno, id_connection_options, id_max_allowed_packet; struct trilogy_ctx { trilogy_conn_t conn; @@ -470,6 +470,10 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA connopt.keepalive_interval = NUM2USHORT(val); } + if (RTEST(rb_hash_aref(opts, ID2SYM(id_tcp_nodelay_enabled)))) { + connopt.tcp_nodelay_enabled = true; + } + if ((val = rb_hash_lookup(opts, ID2SYM(id_max_allowed_packet))) != Qnil) { Check_Type(val, T_FIXNUM); connopt.max_allowed_packet = NUM2SIZET(val); @@ -1190,6 +1194,7 @@ RUBY_FUNC_EXPORTED void Init_cext() id_keepalive_idle = rb_intern("keepalive_idle"); id_keepalive_count = rb_intern("keepalive_count"); id_keepalive_interval = rb_intern("keepalive_interval"); + id_tcp_nodelay_enabled = rb_intern("tcp_nodelay_enabled"); id_database = rb_intern("database"); id_ssl_ca = rb_intern("ssl_ca"); id_ssl_capath = rb_intern("ssl_capath"); diff --git a/inc/trilogy/socket.h b/inc/trilogy/socket.h index 967b5615..608d642f 100644 --- a/inc/trilogy/socket.h +++ b/inc/trilogy/socket.h @@ -66,6 +66,8 @@ typedef struct { uint16_t keepalive_count; uint16_t keepalive_interval; + bool tcp_nodelay_enabled; + TRILOGY_CAPABILITIES_t flags; size_t max_allowed_packet; diff --git a/src/socket.c b/src/socket.c index fc0eb624..8a1ce9e7 100644 --- a/src/socket.c +++ b/src/socket.c @@ -195,6 +195,14 @@ static int raw_connect_internal(struct trilogy_sock *sock, const struct addrinfo return TRILOGY_SYSERR; } +#ifdef TCP_NODELAY + if (sock->base.opts.tcp_nodelay_enabled) { + int flags = 1; + if (setsockopt(sock->fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0) { + goto fail; + } + } +#endif if (sock->base.opts.keepalive_enabled) { int flags = 1; if (setsockopt(sock->fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)) < 0) { diff --git a/test/client/connect_test.c b/test/client/connect_test.c index 46dc0c83..b275bd41 100644 --- a/test/client/connect_test.c +++ b/test/client/connect_test.c @@ -71,11 +71,29 @@ TEST test_connect_recv_after_close() PASS(); } +TEST test_connect_send_tcp_nodelay() +{ + trilogy_conn_t conn; + + int err = trilogy_init(&conn); + ASSERT_OK(err); + + trilogy_sockopt_t connopt = *get_connopt(); + connopt.tcp_nodelay_enabled = true; + + err = trilogy_connect_send(&conn, &connopt); + ASSERT_OK(err); + + trilogy_free(&conn); + PASS(); +} + int client_connect_test() { RUN_TEST(test_connect_send); RUN_TEST(test_connect_recv); RUN_TEST(test_connect_recv_after_close); + RUN_TEST(test_connect_send_tcp_nodelay); return 0; }