+const long POP3_C_ConnTimeout = 1000;
+const long DefaultPOP3Port = 110;
+
+Pop3ClientHandler POP3C_ReadHandlers[] = {
+ POP3C_ReadGreeting,
+ POP3C_GetUserState,
+ POP3C_GetPassState,
+ POP3C_GetListCommandState,
+ POP3C_GetListOneLine,
+ POP3C_GetOneMessageIDState,
+ POP3C_ReadMessageBodyFollowing,
+ POP3C_ReadMessageBody,
+ POP3C_ReadDeleteState,
+ POP3C_ReadQuitState,
+};
+
+const long POP3_C_SendTimeouts[POP3C_MaxRead] = {
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100
+};
+const ConstStr POP3C_ReadErrors[POP3C_MaxRead] = {
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")},
+ {HKEY("Connection broken during ")}
+};
+
+Pop3ClientHandler POP3C_SendHandlers[] = {
+ NULL, /* we don't send a greeting */
+ POP3C_SendUser,
+ POP3C_SendPassword,
+ POP3C_SendListCommand,
+ NULL,
+ POP3C_GetOneMessagID,
+ POP3C_SendGetOneMsg,
+ NULL,
+ POP3C_SendDelete,
+ POP3C_SendQuit
+};
+
+const long POP3_C_ReadTimeouts[] = {
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100
+};
+/*****************************************************************************/
+/* POP3 CLIENT DISPATCHER */
+/*****************************************************************************/
+
+void POP3SetTimeout(eNextState NextTCPState, pop3aggr *pMsg)
+{
+ AsyncIO *IO = &pMsg->IO;
+ double Timeout = 0.0;
+
+ EVP3C_syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+
+ switch (NextTCPState) {
+ case eSendFile:
+ case eSendReply:
+ case eSendMore:
+ Timeout = POP3_C_SendTimeouts[pMsg->State];
+/*
+ if (pMsg->State == eDATABody) {
+ / * if we're sending a huge message, we need more time. * /
+ Timeout += StrLength(pMsg->msgtext) / 1024;
+ }
+*/
+ break;
+ case eReadFile:
+ case eReadMessage:
+ Timeout = POP3_C_ReadTimeouts[pMsg->State];
+/*
+ if (pMsg->State == eDATATerminateBody) {
+ / *
+ * some mailservers take a nap before accepting the message
+ * content inspection and such.
+ * /
+ Timeout += StrLength(pMsg->msgtext) / 1024;
+ }
+*/
+ break;
+ case eReadPayload:
+ Timeout = 100000;
+ /* TODO!!! */
+ break;
+ case eSendDNSQuery:
+ case eReadDNSReply:
+ case eConnect:
+ case eTerminateConnection:
+ case eDBQuery:
+ case eAbort:
+ case eReadMore://// TODO
+ return;
+ }
+ SetNextTimeout(&pMsg->IO, Timeout);
+}
+eNextState POP3_C_DispatchReadDone(AsyncIO *IO)
+{
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ pop3aggr *pMsg = IO->Data;
+ eNextState rc;
+
+ rc = POP3C_ReadHandlers[pMsg->State](pMsg);
+ if (rc != eReadMore)
+ pMsg->State++;
+ POP3SetTimeout(rc, pMsg);
+ return rc;
+}
+eNextState POP3_C_DispatchWriteDone(AsyncIO *IO)
+{
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ pop3aggr *pMsg = IO->Data;
+ eNextState rc;
+
+ rc = POP3C_SendHandlers[pMsg->State](pMsg);
+ POP3SetTimeout(rc, pMsg);
+ return rc;
+}
+
+
+/*****************************************************************************/
+/* POP3 CLIENT ERROR CATCHERS */
+/*****************************************************************************/
+eNextState POP3_C_Terminate(AsyncIO *IO)
+{
+/// pop3aggr *pMsg = (pop3aggr *)IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ FinalizePOP3AggrRun(IO);
+ return eAbort;
+}
+eNextState POP3_C_TerminateDB(AsyncIO *IO)
+{
+/// pop3aggr *pMsg = (pop3aggr *)IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ FinalizePOP3AggrRun(IO);
+ return eAbort;
+}
+eNextState POP3_C_Timeout(AsyncIO *IO)
+{
+ pop3aggr *pMsg = IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ StrBufPlain(IO->ErrMsg, CKEY(POP3C_ReadErrors[pMsg->State]));
+ return FailAggregationRun(IO);
+}
+eNextState POP3_C_ConnFail(AsyncIO *IO)
+{
+ pop3aggr *pMsg = (pop3aggr *)IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ StrBufPlain(IO->ErrMsg, CKEY(POP3C_ReadErrors[pMsg->State]));
+ return FailAggregationRun(IO);
+}
+eNextState POP3_C_DNSFail(AsyncIO *IO)
+{
+ pop3aggr *pMsg = (pop3aggr *)IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+ StrBufPlain(IO->ErrMsg, CKEY(POP3C_ReadErrors[pMsg->State]));
+ return FailAggregationRun(IO);
+}
+eNextState POP3_C_Shutdown(AsyncIO *IO)
+{
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+//// pop3aggr *pMsg = IO->Data;
+
+////pMsg->MyQEntry->Status = 3;
+///StrBufPlain(pMsg->MyQEntry->StatusMessage, HKEY("server shutdown during message retrieval."));
+ FinalizePOP3AggrRun(IO);
+ return eAbort;
+}
+
+
+/**
+ * @brief lineread Handler; understands when to read more POP3 lines,
+ * and when this is a one-lined reply.
+ */
+eReadState POP3_C_ReadServerStatus(AsyncIO *IO)
+{
+ eReadState Finished = eBufferNotEmpty;
+
+ switch (IO->NextState) {
+ case eSendDNSQuery:
+ case eReadDNSReply:
+ case eDBQuery:
+ case eConnect:
+ case eTerminateConnection:
+ case eAbort:
+ Finished = eReadFail;
+ break;
+ case eSendFile:
+ case eSendReply:
+ case eSendMore:
+ case eReadMore:
+ case eReadMessage:
+ Finished = StrBufChunkSipLine(IO->IOBuf, &IO->RecvBuf);
+ break;
+ case eReadFile:
+ case eReadPayload:
+ Finished = CtdlReadMessageBodyAsync(IO);
+ break;
+ }
+ return Finished;
+}
+
+/*****************************************************************************
+ * So we connect our Server IP here. *
+ *****************************************************************************/
+eNextState POP3_C_ReAttachToFetchMessages(AsyncIO *IO)
+{
+ pop3aggr *cpptr = IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+////??? cpptr->State ++;
+ if (cpptr->Pos == NULL)
+ cpptr->Pos = GetNewHashPos(cpptr->MsgNumbers, 0);
+
+ POP3_C_DispatchWriteDone(IO);
+ ReAttachIO(IO, cpptr, 0);
+ IO->NextState = eReadMessage;
+ return IO->NextState;
+}
+
+eNextState pop3_connect_ip(AsyncIO *IO)
+{
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+
+ return EvConnectSock(IO,
+ POP3_C_ConnTimeout,
+ POP3_C_ReadTimeouts[0],
+ 1);
+}
+
+eNextState pop3_get_one_host_ip_done(AsyncIO *IO)
+{
+ pop3aggr *cpptr = IO->Data;
+ struct hostent *hostent;
+
+ QueryCbDone(IO);
+
+ hostent = cpptr->HostLookup.VParsedDNSReply;
+ if ((cpptr->HostLookup.DNSStatus == ARES_SUCCESS) &&
+ (hostent != NULL) ) {
+ memset(&cpptr->IO.ConnectMe->Addr, 0, sizeof(struct in6_addr));
+ if (cpptr->IO.ConnectMe->IPv6) {
+ memcpy(&cpptr->IO.ConnectMe->Addr.sin6_addr.s6_addr,
+ &hostent->h_addr_list[0],
+ sizeof(struct in6_addr));
+
+ cpptr->IO.ConnectMe->Addr.sin6_family =
+ hostent->h_addrtype;
+ cpptr->IO.ConnectMe->Addr.sin6_port =
+ htons(DefaultPOP3Port);
+ }
+ else {
+ struct sockaddr_in *addr =
+ (struct sockaddr_in*)
+ &cpptr->IO.ConnectMe->Addr;
+
+ memcpy(&addr->sin_addr.s_addr,
+ hostent->h_addr_list[0],
+ sizeof(uint32_t));
+
+ addr->sin_family = hostent->h_addrtype;
+ addr->sin_port = htons(DefaultPOP3Port);
+ }
+ return pop3_connect_ip(IO);
+ }
+ else
+ return eAbort;
+}
+
+eNextState pop3_get_one_host_ip(AsyncIO *IO)
+{
+ pop3aggr *cpptr = IO->Data;
+
+ syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
+
+ syslog(LOG_DEBUG,
+ "POP3 client[%ld]: looking up %s-Record %s : %d ...\n",
+ cpptr->n,
+ (cpptr->IO.ConnectMe->IPv6)? "aaaa": "a",
+ cpptr->IO.ConnectMe->Host,
+ cpptr->IO.ConnectMe->Port);
+
+ QueueQuery((cpptr->IO.ConnectMe->IPv6)? ns_t_aaaa : ns_t_a,
+ cpptr->IO.ConnectMe->Host,
+ &cpptr->IO,
+ &cpptr->HostLookup,
+ pop3_get_one_host_ip_done);
+ IO->NextState = eReadDNSReply;
+ return IO->NextState;
+}
+
+
+
+int pop3_do_fetching(pop3aggr *cpptr)
+{
+ AsyncIO *IO = &cpptr->IO;
+
+ InitIOStruct(IO,
+ cpptr,
+ eReadMessage,
+ POP3_C_ReadServerStatus,
+ POP3_C_DNSFail,
+ POP3_C_DispatchWriteDone,
+ POP3_C_DispatchReadDone,
+ POP3_C_Terminate,
+ POP3_C_TerminateDB,
+ POP3_C_ConnFail,
+ POP3_C_Timeout,
+ POP3_C_Shutdown);
+
+ safestrncpy(((CitContext *)cpptr->IO.CitContext)->cs_host,
+ ChrPtr(cpptr->Url),
+ sizeof(((CitContext *)cpptr->IO.CitContext)->cs_host));
+
+ if (cpptr->IO.ConnectMe->IsIP) {
+ QueueEventContext(&cpptr->IO,
+ pop3_connect_ip);
+ }
+ else {
+ QueueEventContext(&cpptr->IO,
+ pop3_get_one_host_ip);
+ }
+ return 1;
+}