diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-02 23:53:55 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-02 23:53:55 +0000 |
commit | 3aec3589a45dd71191f47da93656b6b5614903de (patch) | |
tree | ed846a6325d6754faf2ad6b6ab0d38e2c3a19a35 /contrib/librdns/util.c | |
parent | be5153fa1b8cc23b03e616fc0288b9f1994754d8 (diff) | |
download | rspamd-3aec3589a45dd71191f47da93656b6b5614903de.tar.gz rspamd-3aec3589a45dd71191f47da93656b6b5614903de.zip |
[Project] Rdns: Add reaper for inactive TCP connections
Diffstat (limited to 'contrib/librdns/util.c')
-rw-r--r-- | contrib/librdns/util.c | 124 |
1 files changed, 101 insertions, 23 deletions
diff --git a/contrib/librdns/util.c b/contrib/librdns/util.c index e33ab709c..61c244199 100644 --- a/contrib/librdns/util.c +++ b/contrib/librdns/util.c @@ -515,8 +515,15 @@ rdns_ioc_free (struct rdns_io_channel *ioc) ioc->resolver->async->del_read (ioc->resolver->async->data, ioc->async_io); kh_destroy(rdns_requests_hash, ioc->requests); - close (ioc->sock); - free (ioc->saddr); + + if (ioc->sock != -1) { + close(ioc->sock); + } + + if (ioc->saddr != NULL) { + free(ioc->saddr); + } + free (ioc); } @@ -553,28 +560,12 @@ rdns_ioc_new (struct rdns_server *serv, if (is_tcp) { /* We also need to connect a TCP channel and set a TCP buffer */ nioc->tcp = (struct rdns_tcp_channel *)(((unsigned char *)nioc) + sizeof(*nioc)); - int r = connect (nioc->sock, nioc->saddr, nioc->slen); - - if (r == -1) { - if (errno != EAGAIN && errno != EINTR && errno != EINPROGRESS) { - rdns_err ("cannot connect a TCP socket: %s for server %s", - strerror(errno), serv->name); - close(nioc->sock); - free(nioc); - return NULL; - } - else { - /* We need to wait for write readiness here */ - nioc->async_io = resolver->async->add_write (resolver->async->data, - nioc->sock, nioc); - } - } - else { - /* Always be ready to read from a TCP socket */ - nioc->flags |= RDNS_CHANNEL_CONNECTED|RDNS_CHANNEL_ACTIVE; - nioc->tcp->async_read = resolver->async->add_read(resolver->async->data, - nioc->sock, nioc); + if (!rdns_ioc_tcp_connect(nioc)) { + rdns_err ("cannot connect TCP socket to %s: %s", serv->name, + strerror (errno)); + free (nioc); + return NULL; } nioc->flags |= RDNS_CHANNEL_TCP; @@ -636,6 +627,93 @@ rdns_request_release (struct rdns_request *req) REF_RELEASE (req); } +void +rdns_ioc_tcp_reset (struct rdns_io_channel *ioc) +{ + struct rdns_resolver *resolver = ioc->resolver; + + if (IS_CHANNEL_CONNECTED(ioc)) { + if (ioc->tcp->async_write) { + resolver->async->del_write (resolver->async->data, ioc->tcp->async_write); + ioc->tcp->async_write = NULL; + } + if (ioc->tcp->async_read) { + resolver->async->del_read (resolver->async->data, ioc->tcp->async_read); + ioc->tcp->async_read = NULL; + } + + ioc->flags &= ~RDNS_CHANNEL_CONNECTED; + } + + if (ioc->sock != -1) { + close (ioc->sock); + ioc->sock = -1; + } + if (ioc->saddr) { + free (ioc->saddr); + ioc->saddr = NULL; + } +} + +bool +rdns_ioc_tcp_connect (struct rdns_io_channel *ioc) +{ + struct rdns_resolver *resolver = ioc->resolver; + + if (IS_CHANNEL_CONNECTED(ioc)) { + rdns_err ("trying to connect already connected IO channel!"); + return false; + } + + if (ioc->sock == -1) { + ioc->sock = rdns_make_client_socket (ioc->srv->name, ioc->srv->port, + SOCK_STREAM, &ioc->saddr, &ioc->slen); + if (ioc->sock == -1) { + rdns_err ("cannot open socket to %s: %s", ioc->srv->name, + strerror (errno)); + + if (ioc->saddr) { + free (ioc->saddr); + ioc->saddr = NULL; + } + + return false; + } + } + + int r = connect (ioc->sock, ioc->saddr, ioc->slen); + + if (r == -1) { + if (errno != EAGAIN && errno != EINTR && errno != EINPROGRESS) { + rdns_err ("cannot connect a TCP socket: %s for server %s", + strerror(errno), ioc->srv->name); + close (ioc->sock); + + if (ioc->saddr) { + free (ioc->saddr); + ioc->saddr = NULL; + } + + ioc->sock = -1; + + return false; + } + else { + /* We need to wait for write readiness here */ + ioc->tcp->async_write = resolver->async->add_write (resolver->async->data, + ioc->sock, ioc); + } + } + else { + /* Always be ready to read from a TCP socket */ + ioc->flags |= RDNS_CHANNEL_CONNECTED|RDNS_CHANNEL_ACTIVE; + ioc->tcp->async_read = resolver->async->add_read(resolver->async->data, + ioc->sock, ioc); + } + + return true; +} + static bool rdns_resolver_conf_process_line (struct rdns_resolver *resolver, const char *line, rdns_resolv_conf_cb cb, void *ud) |