From 13e9fdfd75a549cf922077a94588a68a1e456dd9 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Sun, 8 May 2011 12:00:04 +0000 Subject: [PATCH] work on errorhandling for the smtp event client - add states for the mx lookup phases - return the propper states - close filedescriptors if we fail one attempt - say which connection type we have: immediate, e_again, fail - say which NS-lookup whe do (a/aaaa) --- citadel/event_client.c | 43 +++++++++++++++++---- citadel/event_client.h | 5 +++ citadel/modules/smtp/serv_smtpeventclient.c | 15 ++++++- citadel/modules/smtp/smtp_clienthandlers.h | 2 +- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/citadel/event_client.c b/citadel/event_client.c index 11aabf963..a7ea8003d 100644 --- a/citadel/event_client.c +++ b/citadel/event_client.c @@ -123,12 +123,8 @@ void FreeAsyncIOContents(AsyncIO *IO) } -void ShutDownCLient(AsyncIO *IO) +void StopClientWatchers(AsyncIO *IO) { - CtdlLogPrintf(CTDL_DEBUG, "EVENT x %d\n", IO->SendBuf.fd); - - ev_cleanup_stop(event_base, &IO->abort_by_shutdown); - ev_timer_stop(event_base, &IO->conn_fail); ev_io_stop(event_base, &IO->conn_event); ev_idle_stop(event_base, &IO->unwind_stack); @@ -142,6 +138,15 @@ void ShutDownCLient(AsyncIO *IO) IO->SendBuf.fd = 0; IO->RecvBuf.fd = 0; } +} + +void ShutDownCLient(AsyncIO *IO) +{ + CtdlLogPrintf(CTDL_DEBUG, "EVENT x %d\n", IO->SendBuf.fd); + ev_cleanup_stop(event_base, &IO->abort_by_shutdown); + + StopClientWatchers(IO); + if (IO->DNSChannel != NULL) { ares_destroy(IO->DNSChannel); ev_io_stop(event_base, &IO->dns_recv_event); @@ -269,6 +274,9 @@ IO_send_callback(struct ev_loop *loop, ev_io *watcher, int revents) } break; + case eSendDNSQuery: + case eReadDNSReply: + case eConnect: case eTerminateConnection: case eAbort: break; @@ -293,6 +301,9 @@ set_start_callback(struct ev_loop *loop, AsyncIO *IO, int revents) become_session(IO->CitContext); IO_send_callback(loop, &IO->send_event, revents); break; + case eSendDNSQuery: + case eReadDNSReply: + case eConnect: case eTerminateConnection: case eAbort: /// TODO: WHUT? @@ -301,13 +312,16 @@ set_start_callback(struct ev_loop *loop, AsyncIO *IO, int revents) } static void -IO_Timout_callback(struct ev_loop *loop, ev_timer *watcher, int revents) +IO_Timeout_callback(struct ev_loop *loop, ev_timer *watcher, int revents) { AsyncIO *IO = watcher->data; ev_timer_stop (event_base, &IO->rw_timeout); become_session(IO->CitContext); + close(IO->SendBuf.fd); + IO->SendBuf.fd = IO->RecvBuf.fd = 0; + assert(IO->Timeout); switch (IO->Timeout(IO)) { @@ -323,7 +337,12 @@ IO_connfail_callback(struct ev_loop *loop, ev_timer *watcher, int revents) AsyncIO *IO = watcher->data; ev_timer_stop (event_base, &IO->conn_fail); + ev_io_stop(loop, &IO->conn_event); + + close(IO->SendBuf.fd); + IO->SendBuf.fd = IO->RecvBuf.fd = 0; + become_session(IO->CitContext); assert(IO->ConnFail); @@ -378,7 +397,13 @@ IO_postdns_callback(struct ev_loop *loop, ev_idle *watcher, int revents) CtdlLogPrintf(CTDL_DEBUG, "event: %s\n", __FUNCTION__); become_session(IO->CitContext); - IO->DNSQuery->PostDNS(IO); + switch (IO->DNSQuery->PostDNS(IO)) + { + case eAbort: + ShutDownCLient(IO); + default: + break; + } } eNextState event_connect_socket(AsyncIO *IO, double conn_timeout, double first_rw_timeout) @@ -426,7 +451,7 @@ eNextState event_connect_socket(AsyncIO *IO, double conn_timeout, double first_r ev_timer_init(&IO->conn_fail, IO_connfail_callback, conn_timeout, 0); IO->conn_fail.data = IO; - ev_timer_init(&IO->rw_timeout, IO_Timout_callback, first_rw_timeout, 0); + ev_timer_init(&IO->rw_timeout, IO_Timeout_callback, first_rw_timeout, 0); IO->rw_timeout.data = IO; if (IO->ConnectMe->IPv6) @@ -435,12 +460,14 @@ eNextState event_connect_socket(AsyncIO *IO, double conn_timeout, double first_r rc = connect(IO->SendBuf.fd, (struct sockaddr_in *)&IO->ConnectMe->Addr, sizeof(struct sockaddr_in)); if (rc >= 0){ + CtdlLogPrintf(CTDL_DEBUG, "connect() immediate success.\n"); //// freeaddrinfo(res); set_start_callback(event_base, IO, 0); ev_timer_start(event_base, &IO->rw_timeout); return IO->NextState; } else if (errno == EINPROGRESS) { + CtdlLogPrintf(CTDL_DEBUG, "connect() have to wait now.\n"); ev_io_init(&IO->conn_event, IO_connestd_callback, IO->SendBuf.fd, EV_READ|EV_WRITE); IO->conn_event.data = IO; diff --git a/citadel/event_client.h b/citadel/event_client.h index 33a4d0b90..52e3de5ac 100644 --- a/citadel/event_client.h +++ b/citadel/event_client.h @@ -8,6 +8,9 @@ typedef struct AsyncIO AsyncIO; typedef enum _eNextState { + eSendDNSQuery, + eReadDNSReply, + eConnect, eSendReply, eSendMore, eReadMessage, @@ -99,6 +102,8 @@ void QueryCbDone(AsyncIO *IO); void StopClient(AsyncIO *IO); +void StopClientWatchers(AsyncIO *IO); + void SetNextTimeout(AsyncIO *IO, double timeout); void InitC_ares_dns(AsyncIO *IO); diff --git a/citadel/modules/smtp/serv_smtpeventclient.c b/citadel/modules/smtp/serv_smtpeventclient.c index fcec898cb..a523f9347 100644 --- a/citadel/modules/smtp/serv_smtpeventclient.c +++ b/citadel/modules/smtp/serv_smtpeventclient.c @@ -101,6 +101,7 @@ void DeleteSmtpOutMsg(void *v) Msg->HostLookup.DNSReplyFree(Msg->HostLookup.VParsedDNSReply); FreeStrBuf(&Msg->msgtext); FreeAsyncIOContents(&Msg->IO); + memset (Msg, 0, sizeof(SmtpOutMsg)); /* just to be shure... */ free(Msg); } @@ -171,6 +172,8 @@ eNextState FailOneAttempt(AsyncIO *IO) * - connection timeout * - */ + StopClientWatchers(IO); + if (SendMsg->pCurrRelay != NULL) SendMsg->pCurrRelay = SendMsg->pCurrRelay->Next; @@ -222,6 +225,7 @@ void SetConnectStatus(AsyncIO *IO) SendMsg->mx_host, buf, SendMsg->IO.ConnectMe->Port); + SendMsg->IO.NextState = eConnect; } /***************************************************************************** @@ -297,8 +301,9 @@ eNextState get_one_mx_host_ip(AsyncIO *IO) CtdlLogPrintf(CTDL_DEBUG, "SMTP: %s\n", __FUNCTION__); CtdlLogPrintf(CTDL_DEBUG, - "SMTP client[%ld]: looking up %s : %d ...\n", + "SMTP client[%ld]: looking up %s-Record %s : %d ...\n", SendMsg->n, + (SendMsg->pCurrRelay->IPv6)? "aaaa": "a", SendMsg->pCurrRelay->Host, SendMsg->pCurrRelay->Port); @@ -311,8 +316,10 @@ eNextState get_one_mx_host_ip(AsyncIO *IO) SendMsg->MyQEntry->Status = 5; StrBufPrintf(SendMsg->MyQEntry->StatusMessage, "No MX hosts found for <%s>", SendMsg->node); + SendMsg->IO.NextState = eTerminateConnection; return IO->NextState; } + IO->NextState = eReadDNSReply; return IO->NextState; } @@ -397,7 +404,8 @@ eNextState resolve_mx_records(AsyncIO *IO) "No MX hosts found for <%s>", SendMsg->node); return IO->NextState; } - return eAbort; + SendMsg->IO.NextState = eReadDNSReply; + return IO->NextState; } @@ -519,6 +527,9 @@ void SMTPSetTimeout(eNextState NextTCPState, SmtpOutMsg *pMsg) Timeout += StrLength(pMsg->msgtext) / 1024; } break; + case eSendDNSQuery: + case eReadDNSReply: + case eConnect: case eTerminateConnection: case eAbort: return; diff --git a/citadel/modules/smtp/smtp_clienthandlers.h b/citadel/modules/smtp/smtp_clienthandlers.h index ce7f7b9e6..57ade0c60 100644 --- a/citadel/modules/smtp/smtp_clienthandlers.h +++ b/citadel/modules/smtp/smtp_clienthandlers.h @@ -1,5 +1,5 @@ typedef enum _eSMTP_C_States { - eConnect, + eConnectMX, eEHLO, eHELO, eSMTPAuth, -- 2.30.2