OneQueItem *DeserializeQueueItem(StrBuf *RawQItem, long QueMsgID) { OneQueItem *Item; const char *pLine = NULL; StrBuf *Line; StrBuf *Token; void *v; Item = (OneQueItem*)malloc(sizeof(OneQueItem)); memset(Item, 0, sizeof(OneQueItem)); Item->Retry = SMTP_RETRY_INTERVAL; Item->MessageID = -1; Item->QueMsgID = QueMsgID; Token = NewStrBuf(); Line = NewStrBufPlain(NULL, 128); while (pLine != StrBufNOTNULL) { const char *pItemPart = NULL; void *vHandler; StrBufExtract_NextToken(Line, RawQItem, &pLine, '\n'); if (StrLength(Line) == 0) continue; StrBufExtract_NextToken(Token, Line, &pItemPart, '|'); if (GetHash(QItemHandlers, SKEY(Token), &vHandler)) { QItemHandlerStruct *HS; HS = (QItemHandlerStruct*) vHandler; HS->H(Item, Line, &pItemPart); } } FreeStrBuf(&Line); FreeStrBuf(&Token); if (Item->Retry >= MaxRetry) Item->FailNow = 1; pthread_mutex_lock(&ActiveQItemsLock); if (GetHash(ActiveQItems, LKEY(Item->MessageID), &v)) { /* WHOOPS. somebody else is already working on this. */ pthread_mutex_unlock(&ActiveQItemsLock); FreeQueItem(&Item); return NULL; } else { /* mark our claim on this. */ Put(ActiveQItems, LKEY(Item->MessageID), Item, HFreeQueItem); pthread_mutex_unlock(&ActiveQItemsLock); } return Item; }
eNextState POP3C_GetListOneLine(pop3aggr *RecvMsg) { AsyncIO *IO = &RecvMsg->IO; #if 0 int rc; #endif const char *pch; FetchItem *OneMsg = NULL; POP3C_DBG_READ(); if ((StrLength(RecvMsg->IO.IOBuf) == 1) && (ChrPtr(RecvMsg->IO.IOBuf)[0] == '.')) { if (GetCount(RecvMsg->MsgNumbers) == 0) { //// RecvMsg->Sate = ReadQuitState; } else { RecvMsg->Pos = GetNewHashPos(RecvMsg->MsgNumbers, 0); } return eSendReply; } /* * work around buggy pop3 servers which send * empty lines in their listings. */ if ((StrLength(RecvMsg->IO.IOBuf) == 0) || !isdigit(ChrPtr(RecvMsg->IO.IOBuf)[0])) { return eReadMore; } OneMsg = (FetchItem*) malloc(sizeof(FetchItem)); memset(OneMsg, 0, sizeof(FetchItem)); OneMsg->MSGID = atol(ChrPtr(RecvMsg->IO.IOBuf)); pch = strchr(ChrPtr(RecvMsg->IO.IOBuf), ' '); if (pch != NULL) { OneMsg->MSGSize = atol(pch + 1); } #if 0 rc = TestValidateHash(RecvMsg->MsgNumbers); if (rc != 0) EVP3CCS_syslog(LOG_DEBUG, "Hash Invalid: %d\n", rc); #endif Put(RecvMsg->MsgNumbers, LKEY(OneMsg->MSGID), OneMsg, HfreeFetchItem); #if 0 rc = TestValidateHash(RecvMsg->MsgNumbers); if (rc != 0) EVP3CCS_syslog(LOG_DEBUG, "Hash Invalid: %d\n", rc); #endif //RecvMsg->State --; /* read next Line */ return eReadMore; }
void RemoveQItem(OneQueItem *MyQItem) { long len; const char* Key; void *VData; HashPos *It; pthread_mutex_lock(&ActiveQItemsLock); It = GetNewHashPos(ActiveQItems, 0); if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It)) DeleteEntryFromHash(ActiveQItems, It); else { SMTPC_syslog(LOG_WARNING, "unable to find QItem with ID[%ld]", MyQItem->MessageID); while (GetNextHashPos(ActiveQItems, It, &len, &Key, &VData)) SMTPC_syslog(LOG_WARNING, "have_: ID[%ld]", ((OneQueItem *)VData)->MessageID); } pthread_mutex_unlock(&ActiveQItemsLock); DeleteHashPos(&It); }
/* * Scan a room's netconfig to determine whether it requires POP3 aggregation */ void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG) { const RoomNetCfgLine *pLine; void *vptr; pthread_mutex_lock(&POP3QueueMutex); if (GetHash(POP3QueueRooms, LKEY(qrbuf->QRnumber), &vptr)) { pthread_mutex_unlock(&POP3QueueMutex); EVP3CQ_syslog(LOG_DEBUG, "pop3client: [%ld] %s already in progress.", qrbuf->QRnumber, qrbuf->QRname); return; } pthread_mutex_unlock(&POP3QueueMutex); if (server_shutting_down) return; pLine = OneRNCFG->NetConfigs[pop3client]; while (pLine != NULL) { pop3aggr *cptr; cptr = (pop3aggr *) malloc(sizeof(pop3aggr)); memset(cptr, 0, sizeof(pop3aggr)); ///TODO do we need this? cptr->roomlist_parts=1; cptr->RoomName = NewStrBufPlain(qrbuf->QRname, -1); cptr->pop3user = NewStrBufDup(pLine->Value[1]); cptr->pop3pass = NewStrBufDup(pLine->Value[2]); cptr->Url = NewStrBuf(); cptr->Host = NewStrBufDup(pLine->Value[0]); cptr->keep = atol(ChrPtr(pLine->Value[3])); cptr->interval = atol(ChrPtr(pLine->Value[4])); StrBufAppendBufPlain(cptr->Url, HKEY("pop3://"), 0); StrBufUrlescUPAppend(cptr->Url, cptr->pop3user, NULL); StrBufAppendBufPlain(cptr->Url, HKEY(":"), 0); StrBufUrlescUPAppend(cptr->Url, cptr->pop3pass, NULL); StrBufAppendBufPlain(cptr->Url, HKEY("@"), 0); StrBufAppendBuf(cptr->Url, cptr->Host, 0); StrBufAppendBufPlain(cptr->Url, HKEY("/"), 0); StrBufUrlescAppend(cptr->Url, cptr->RoomName, NULL); ParseURL(&cptr->IO.ConnectMe, cptr->Url, 110); #if 0 /* todo: we need to reunite the url to be shure. */ pthread_mutex_lock(&POP3ueueMutex); GetHash(POP3FetchUrls, SKEY(ptr->Url), &vptr); use_this_cptr = (pop3aggr *)vptr; if (use_this_rncptr != NULL) { /* mustn't attach to an active session */ if (use_this_cptr->RefCount > 0) { DeletePOP3Cfg(cptr); /// Count->count--; } else { long *QRnumber; StrBufAppendBufPlain( use_this_cptr->rooms, qrbuf->QRname, -1, 0); if (use_this_cptr->roomlist_parts == 1) { use_this_cptr->OtherQRnumbers = NewHash(1, lFlathash); } QRnumber = (long*)malloc(sizeof(long)); *QRnumber = qrbuf->QRnumber; Put(use_this_cptr->OtherQRnumbers, LKEY(qrbuf->QRnumber), QRnumber, NULL); use_this_cptr->roomlist_parts++; } pthread_mutex_unlock(&POP3QueueMutex); continue; } pthread_mutex_unlock(&RSSQueueMutex); #endif cptr->n = Pop3ClientID++; pthread_mutex_lock(&POP3QueueMutex); Put(POP3FetchUrls, SKEY(cptr->Url), cptr, DeletePOP3Aggregator); pthread_mutex_unlock(&POP3QueueMutex); pLine = pLine->next; } }
snew_key(31, '~', "SCROLL_FORWARD"); snew_key(32, '~', "SCROLL_START"); snew_key(33, '~', "SCROLL_END"); } #define LKEY(x, y) \ { \ char *l = get_term_capability(#x, 0, 1); \ if (l) \ snew_key_from_str(l, #y); \ } void init_keys2 (void) { /* keys bound from terminfo/termcap */ LKEY(key_up, BACKWARD_HISTORY) LKEY(key_down, FORWARD_HISTORY) LKEY(key_left, BACKWARD_CHARACTER) LKEY(key_right, FORWARD_CHARACTER) LKEY(key_ppage, SCROLL_BACKWARD) LKEY(key_npage, SCROLL_FORWARD) LKEY(key_home, SCROLL_START) LKEY(key_end, SCROLL_END) LKEY(key_ic, TOGGLE_INSERT_MODE) /*LKEY(key_dc, DELETE_CHARACTER)*/ LKEY(key_f1, CHELP) LKEY(key_f2, CHANNEL_CHOPS) LKEY(key_f3, CHANNEL_NONOPS) #ifdef WANT_CDCC LKEY(key_f4, CDCC_PLIST) #endif
/* * smtp_do_procmsg() * * Called by smtp_do_queue() to handle an individual message. */ void smtp_do_procmsg(long msgnum, void *userdata) { time_t now; int mynumsessions = num_sessions; struct CtdlMessage *msg = NULL; char *Author = NULL; char *Address = NULL; char *instr = NULL; StrBuf *PlainQItem; OneQueItem *MyQItem; char *pch; HashPos *It; void *vQE; long len; const char *Key; int HaveBuffers = 0; StrBuf *Msg =NULL; if (mynumsessions > max_sessions_for_outbound_smtp) { SMTPC_syslog(LOG_INFO, "skipping because of num jobs %d > %d max_sessions_for_outbound_smtp", mynumsessions, max_sessions_for_outbound_smtp); } SMTPC_syslog(LOG_DEBUG, "smtp_do_procmsg(%ld)\n", msgnum); ///strcpy(envelope_from, ""); msg = CtdlFetchMessage(msgnum, 1, 1); if (msg == NULL) { SMTPC_syslog(LOG_ERR, "tried %ld but no such message!\n", msgnum); return; } pch = instr = msg->cm_fields[eMesageText]; /* Strip out the headers (no not amd any other non-instruction) line */ while (pch != NULL) { pch = strchr(pch, '\n'); if ((pch != NULL) && ((*(pch + 1) == '\n') || (*(pch + 1) == '\r'))) { instr = pch + 2; pch = NULL; } } PlainQItem = NewStrBufPlain(instr, -1); CM_Free(msg); MyQItem = DeserializeQueueItem(PlainQItem, msgnum); FreeStrBuf(&PlainQItem); if (MyQItem == NULL) { SMTPC_syslog(LOG_ERR, "Msg No %ld: already in progress!\n", msgnum); return; /* s.b. else is already processing... */ } /* * Postpone delivery if we've already tried recently. */ now = time(NULL); if ((MyQItem->ReattemptWhen != 0) && (now < MyQItem->ReattemptWhen) && (run_queue_now == 0)) { SMTPC_syslog(LOG_DEBUG, "Retry time not yet reached. %ld seconds left.", MyQItem->ReattemptWhen - now); It = GetNewHashPos(MyQItem->MailQEntries, 0); pthread_mutex_lock(&ActiveQItemsLock); { if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It)) { DeleteEntryFromHash(ActiveQItems, It); } } pthread_mutex_unlock(&ActiveQItemsLock); ////FreeQueItem(&MyQItem); TODO: DeleteEntryFromHash frees this? DeleteHashPos(&It); return; } /* * Bail out if there's no actual message associated with this */ if (MyQItem->MessageID < 0L) { SMTPCM_syslog(LOG_ERR, "no 'msgid' directive found!\n"); It = GetNewHashPos(MyQItem->MailQEntries, 0); pthread_mutex_lock(&ActiveQItemsLock); { if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It)) { DeleteEntryFromHash(ActiveQItems, It); } } pthread_mutex_unlock(&ActiveQItemsLock); DeleteHashPos(&It); ////FreeQueItem(&MyQItem); TODO: DeleteEntryFromHash frees this? return; } It = GetNewHashPos(MyQItem->MailQEntries, 0); while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE)) { MailQEntry *ThisItem = vQE; SMTPC_syslog(LOG_DEBUG, "SMTP Queue: Task: <%s> %d\n", ChrPtr(ThisItem->Recipient), ThisItem->Active); } DeleteHashPos(&It); MyQItem->NotYetShutdownDeliveries = MyQItem->ActiveDeliveries = CountActiveQueueEntries(MyQItem, 1); /* failsafe against overload: * will we exceed the limit set? */ if ((MyQItem->ActiveDeliveries + mynumsessions > max_sessions_for_outbound_smtp) && /* if yes, did we reach more than half of the quota? */ ((mynumsessions * 2) > max_sessions_for_outbound_smtp) && /* if... would we ever fit into half of the quota?? */ (((MyQItem->ActiveDeliveries * 2) < max_sessions_for_outbound_smtp))) { /* abort delivery for another time. */ SMTPC_syslog(LOG_INFO, "SMTP Queue: skipping because of num jobs %d + %ld > %d max_sessions_for_outbound_smtp", mynumsessions, MyQItem->ActiveDeliveries, max_sessions_for_outbound_smtp); It = GetNewHashPos(MyQItem->MailQEntries, 0); pthread_mutex_lock(&ActiveQItemsLock); { if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It)) { DeleteEntryFromHash(ActiveQItems, It); } } pthread_mutex_unlock(&ActiveQItemsLock); return; } if (MyQItem->ActiveDeliveries > 0) { ParsedURL *RelayUrls = NULL; int nActivated = 0; int n = MsgCount++; int m = MyQItem->ActiveDeliveries; int i = 1; It = GetNewHashPos(MyQItem->MailQEntries, 0); Msg = smtp_load_msg(MyQItem, n, &Author, &Address); RelayUrls = LoadRelayUrls(MyQItem, Author, Address); if ((RelayUrls == NULL) && MyQItem->HaveRelay) { while ((i <= m) && (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE))) { int KeepBuffers = (i == m); MailQEntry *ThisItem = vQE; StrBufPrintf(ThisItem->StatusMessage, "No relay configured matching %s / %s", (Author != NULL)? Author : "", (Address != NULL)? Address : ""); ThisItem->Status = 5; nActivated++; if (i > 1) n = MsgCount++; SMTPC_syslog(LOG_INFO, "SMTPC: giving up on <%ld> <%s> %d / %d \n", MyQItem->MessageID, ChrPtr(ThisItem->Recipient), i, m); (*((int*) userdata)) ++; smtp_try_one_queue_entry(MyQItem, ThisItem, Msg, KeepBuffers, n, RelayUrls); if (KeepBuffers) HaveBuffers++; i++; } if (Author != NULL) free (Author); if (Address != NULL) free (Address); DeleteHashPos(&It); return; } if (Author != NULL) free (Author); if (Address != NULL) free (Address); while ((i <= m) && (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE))) { MailQEntry *ThisItem = vQE; if (ThisItem->Active == 1) { int KeepBuffers = (i == m); nActivated++; if (nActivated % ndelay_count == 0) usleep(delay_msec); if (i > 1) n = MsgCount++; SMTPC_syslog(LOG_DEBUG, "SMTPC: Trying <%ld> <%s> %d / %d \n", MyQItem->MessageID, ChrPtr(ThisItem->Recipient), i, m); (*((int*) userdata)) ++; smtp_try_one_queue_entry(MyQItem, ThisItem, Msg, KeepBuffers, n, RelayUrls); if (KeepBuffers) HaveBuffers++; i++; } } DeleteHashPos(&It); } else { It = GetNewHashPos(MyQItem->MailQEntries, 0); pthread_mutex_lock(&ActiveQItemsLock); { if (GetHashPosFromKey(ActiveQItems, LKEY(MyQItem->MessageID), It)) { DeleteEntryFromHash(ActiveQItems, It); } else { long len; const char* Key; void *VData; SMTPC_syslog(LOG_WARNING, "unable to find QItem with ID[%ld]", MyQItem->MessageID); while (GetNextHashPos(ActiveQItems, It, &len, &Key, &VData)) { SMTPC_syslog(LOG_WARNING, "have: ID[%ld]", ((OneQueItem *)VData)->MessageID); } } } pthread_mutex_unlock(&ActiveQItemsLock); DeleteHashPos(&It); ////FreeQueItem(&MyQItem); TODO: DeleteEntryFromHash frees this? // TODO: bounce & delete? } if (!HaveBuffers) { FreeStrBuf (&Msg); // TODO : free RelayUrls } }