///////////////////////////////////////////////////////////////////// // Select the text color based on the severity of a message. QRGBX CoxFromSeverity(ESeverity eSeverity) { switch (eSeverity) { case eSeverityNoise: return d_coGray; case eSeverityComment: return d_coGreen; case eSeverityInfoTextBlue: return d_coBlue; case eSeverityInfoTextBlueDark: return d_coBlueDark; case eSeverityNull: // A 'null' severity is displayed in black, although it is typically an empty message case eSeverityInfoTextBlack: return d_coBlack; case eSeverityWarning: return COX_MakeBold(d_coOrange); case eSeverityWarningToErrorLog: return COX_MakeBold(d_coOrangeDark); case eSeverityErrorWarning: return COX_MakeBold(d_coRed); case eSeverityErrorAssert: /* case eSeverityErrorCritical: */ return COX_MakeBold(d_coRedHot); default: Assert(FALSE && "Unknown severity level"); return COX_MakeBold(d_coRedHot); } // switch } // CoxFromSeverity()
// Append the error if the log is created and visible void CMessageLog::AppendTextError(const SErrorLogEntry * pError) { Assert(pError != NULL); QString sDateTimeError = QDateTime::fromMSecsSinceEpoch(pError->tsError).toLocalTime().toString("yyyy-MM-dd hh:mm:ss"); AppendTextFormat(d_coBlack, "[$Q] ", &sDateTimeError); PSZUC pszmError = pError->szmError; AppendTextU(COX_MakeBold(d_coRedDark), pszmError, ":\n"); AppendTextU(strcmpU(pszmError, c_szInternalErrorDetected) ? d_coRedDark : COX_MakeBold(d_coAssert), pszmError + CbAllocUtoU(pszmError), c_szNewLine); } // AppendTextError()
void TAccountXmpp::Contact_RosterUnsubscribe(INOUT TContact * pContact) { Assert(pContact != NULL); if (m_paSocket == NULL) return; if (m_paSocket->Socket_FuIsReadyToSendMessages()) { MessageLog_AppendTextFormatCo(COX_MakeBold(d_coOrange), "Unsubscribing from contact ^j...\n", pContact); m_paSocket->Socket_WriteXmlFormatted("<iq type='set'><query xmlns='jabber:iq:roster'><item jid='^j' subscription='remove'></item></query></iq>", pContact); } }
void ErrorLog_Show() { g_oErrorLog.Show(); g_oErrorLog.Empty(); // Empty any previous content of the Error Log // Populate the errors SErrorLogEntry ** ppErrorStop; SErrorLogEntry ** ppError = g_arraypErrors.PrgpGetErrorsStop(OUT &ppErrorStop); while (ppError != ppErrorStop) g_oErrorLog.AppendTextError(*ppError++); // Just for fun, display statistics regarding the number of assertions g_oErrorLog.AppendTextU(COX_MakeBold(d_coBlack), (PSZUC)"Summary of Errors:\n"); g_oErrorLog.AppendTextFormat(g_cAssertionsFailed ? COX_MakeBold(d_coAssert) : d_coGreen, "Total number of internal errors: $L\n", g_cAssertionsFailed); #ifdef Q_OS_WIN extern UINT g_cTimerFailures; if (g_cTimerFailures > 0) g_oErrorLog.AppendTextFormat(d_coAssert, "Total number of timer failures: $I\n", g_cTimerFailures); #endif g_oErrorLog.AppendTextFormat(d_coGreen, "Total number of successful internal sanity checks: $L\n", g_cAssertionsTotalExecuted - g_cAssertionsFailed); }
// Delete the task matching the ID, and if not found, do nothing. void CListTasksSendReceive::DeleteTaskMatchingID(TIMESTAMP tsTaskID, BOOL fDeleteTaskToSend) { CTaskSendReceive ** ppTaskPrevious = &m_plistTasks; CTaskSendReceive * pTask = m_plistTasks; while (pTask != NULL) { if ((pTask->m_tsTaskID == tsTaskID) && (pTask->FIsTaskSend() == fDeleteTaskToSend)) { MessageLog_AppendTextFormatCo(d_coPurple, "DeleteTaskMatchingID() - Task ID $t is now deleted ($I bytes)\n", tsTaskID, pTask->m_binXmlData.CbGetData()); *ppTaskPrevious = pTask->m_pNext; // Remove the task to delete from the linked list delete pTask; return; } ppTaskPrevious = &pTask->m_pNext; pTask = pTask->m_pNext; } MessageLog_AppendTextFormatCo(COX_MakeBold(d_coPurple), "DeleteTaskMatchingID() - Cannot delete Task ID $t because its ID cannot be found!\n", tsTaskID); }
void CListTasksSendReceive::UnserializeFromXml(const CXmlNode * pXmlNodeElementTask) { Assert(m_plistTasks == NULL); CTaskSendReceive ** ppaTask = &m_plistTasks; while (pXmlNodeElementTask != NULL) { //MessageLog_AppendTextFormatCo(d_coRed, "Unserializing Task ^N", pXmlNodeElementTask); CTaskSendReceive * paTask = new CTaskSendReceive; *ppaTask = paTask; ppaTask = &paTask->m_pNext; // Pointer to append the next task at the end of the linked list paTask->m_tsTaskID = pXmlNodeElementTask->TsGetAttributeValueTimestamp_ML('i'); paTask->m_cbTotal = pXmlNodeElementTask->UFindAttributeValueDecimal_ZZR('s'); paTask->m_binXmlData.BinAppendBinaryDataFromBase85SCb_ML(pXmlNodeElementTask->PszuFindAttributeValue('d')); pXmlNodeElementTask = pXmlNodeElementTask->m_pNextSibling; } MessageLog_AppendTextFormatCo(COX_MakeBold(d_coGreen), "CListTasksSendReceive::UnserializeFromXml():\n"); DisplayTasksToMessageLog(); }
// For debugging void CListTasksSendReceive::DisplayTasksToMessageLog() { int cTasks = 0; TIMESTAMP tsNow = Timestamp_GetCurrentDateTime(); CTaskSendReceive * pTask = m_plistTasks; while (pTask != NULL) { TIMESTAMP_DELTA dts = tsNow - pTask->m_tsTaskID; const int cbXmlData = pTask->m_binXmlData.CbGetData(); if (pTask->FIsTaskSend()) MessageLog_AppendTextFormatCo(d_coPurple, "\t [$T] Sending Task ID $t: $I bytes\n", dts, pTask->m_tsTaskID, cbXmlData); else MessageLog_AppendTextFormatCo(d_coPurple, "\t [$T] Downloading Task ID $t: cbTotalToDownload = $I, cbDownloadedSoFar = $I\n", dts, pTask->m_tsTaskID, pTask->m_cbTotal, cbXmlData); if (cbXmlData > 0) // && cbXmlData < 200) MessageLog_AppendTextFormatCo(d_coGray, "\t\t {Bm}\n", &pTask->m_binXmlData); pTask = pTask->m_pNext; cTasks++; } // while if (cTasks >= 3) MessageLog_AppendTextFormatCo(COX_MakeBold(d_coPurple), "\t\t Total of $i tasks\n", cTasks); }
void TAccountXmpp::Contact_RosterSubscribe(INOUT TContact * pContact) { Assert(pContact != NULL); if (m_paSocket == NULL) return; if (pContact->TreeItemFlags_FuIsInvisible()) return; // Don't add invisible contacts to the roster /* if (pContact->m_strJidBare.FStringBeginsWith("temp")) { MessageLog_AppendTextFormatSev(eSeverityErrorAssert, "Removing contact ^j from roster...\n", pContact); m_paSocket->Socket_WriteXmlFormatted("<iq type='set'><query xmlns='jabber:iq:roster'><item jid='^S' subscription='remove'></item></query></iq>", &pContact->m_strJidBare); return; } */ #if 1 MessageLog_AppendTextFormatCo(COX_MakeBold(d_coOrange), "Adding contact ^j to roster...\n", pContact); m_paSocket->Socket_WriteXmlFormatted("<iq id='$p' type='set'><query xmlns='jabber:iq:roster'><item jid='^j'></item></query></iq>", pContact, pContact); #endif //m_paSocket->Socket_WriteXmlFormatted("<presence to='^j' type='subscribe'/>", pContact); //m_paSocket->Socket_WriteXmlFormatted("<presence ^:jc from='^J' to='^j' type='subscribe'/>", this, pContact); }
// Find the contact matching the JID and update the contact resource (if any). // If the JID is not in the contact list, the method will create a new contact to the list according to the value of eFindContact. // This method may return NULL if the JID is empty/invalid because a new contact cannot not be created. // // IMPLEMENTATION NOTES // This method should use a hash table to quickly find a contact from its JID and/or use a pointer to cache the last contact found. TContact * TAccountXmpp::Contact_PFindByJID(PSZUC pszContactJID, EFindContact eFindContact) { Assert(pszContactJID != NULL); if (pszContactJID != NULL) { // Find the resource PSZUC pszResource = pszContactJID; while (TRUE) { if (*pszResource == '/') break; if (*pszResource == '\0') break; pszResource++; } // while const int cchJID = pszResource - pszContactJID; if (cchJID > 0) { TContact * pContact; TContact ** ppContactStop; TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop); while (ppContact != ppContactStop) { pContact = *ppContact++; // Assert(!m_strJID.FCompareStringsJIDs(pContact->m_strJidBare) && "Contact should not have the same JID as its parent XMPP account!"); //MessageLog_AppendTextFormatCo(d_coBlack, "Comparing $s with $S\n", pszContactJID, &pContact->m_strJidBare); if (pContact->m_strJidBare.FCompareStringsNoCaseCch(pszContactJID, cchJID)) { // We have found our contact if (pContact->TreeItemFlags_FuIsInvisible()) { Endorse(pContact->m_paTreeItemW_YZ != NULL); // Typically an invisible contact should not appear in the Navigation Tree, however there are situations where it is. For instance, if the contact was just deleted, or if displayed into the list of "Deleted Items" if (eFindContact & eFindContact_kfMakeVisible) pContact->TreeItemContact_DisplayWithinNavigationTreeAndClearInvisibleFlag(); } if (*pszResource != '\0') { // Update the contact resource if (!pContact->m_strRessource.FCompareStringsExactCase(pszResource)) { if (pContact->m_strRessource.FIsEmptyString()) MessageLog_AppendTextFormatCo(d_coBlack, "Contact $S: Assigning resource '$s' (m_uFlagsTreeItem = 0x$x)\n", &pContact->m_strJidBare, pszResource, m_uFlagsTreeItem); else MessageLog_AppendTextFormatCo(COX_MakeBold(d_coBlack), "Contact $S: Updating resource from '$S' to '$s'\n", &pContact->m_strJidBare, &pContact->m_strRessource, pszResource); //pContact->Xcp_ServiceDiscovery(); // The resource changed, therefore query the remote client for its capabilities pContact->SetFlagXcpComposingSendTimestampsOfLastKnownEvents(); // Each time the resource change, re-send the timestamps of the last known events so we give an opportunity to synchronize //pContact->m_cVersionXCP = 0; // Also, reset the XCP version, to make sure the device connects properly } pContact->m_strRessource.InitFromStringU(pszResource); } return pContact; } } // while // We could not find the contact, so create a new one if the JID meets the minimal conditions if ((eFindContact & eFindContact_kfCreateNew) && PcheValidateJID(pszContactJID) == NULL && // Make sure the JID is somewhat valid to create a new contact !m_strJID.FCompareStringsJIDs(pszContactJID)) // Make sure the JID is not the same as the account. It makes no sense to create a contact with the same JID as its parent account. This situation occurs rarely when the server sends a stanza where the 'from' contains the JID of the account. { MessageLog_AppendTextFormatSev(eSeverityInfoTextBlack, "Contact_PFindByJID('$s') - Creating contact for account $S\n", pszContactJID, &m_strJID); pContact = TreeItemAccount_PContactAllocateNewToNavigationTree_NZ(IN pszContactJID); if (eFindContact & eFindContact_kfCreateAsUnsolicited) pContact->SetFlagContactAsUnsolicited(); return pContact; } } // if } // if return NULL; } // Contact_PFindByJID()
void OSocketWeb::SL_DataAvailable() { g_oMutex.lock(); // Make sure all signals SI_MessageAvailable() are synchronized int cbDataAvailable = bytesAvailable(); // Read only once the number of bytes available. This is important to prevent 'thread starvation' in the case the socket data arrives faster than the web socket can handle it. By readin the bytes available once, we are guaranteed this 'state machine' method will eventually exit. switch (m_eSocketState) { case eSocketState_WaitingForHandshake: readAll(); // Flush the handshake m_eSocketState = eSocketState_WaitingForFrameHeader; // Fall Through // case eSocketState_WaitingForFrameHeader: WaitingForFrameHeader: cbDataAvailable -= 2; if (cbDataAvailable >= 0) { BYTE rgbFrameHeader[2]; read(OUT (char *)rgbFrameHeader, sizeof(rgbFrameHeader)); m_bFrameHeader0_kfFragmentFinal = (rgbFrameHeader[0] & d_bFrameHeader0_kfFragmentFinal); const BYTE bOpcode = (rgbFrameHeader[0] & d_bFrameHeader0_kmFragmentOpcode); if (bOpcode != eOpcode_zContinue) m_bFrameHeader0_eOpcode = bOpcode; m_bFrameHeader1_kfPayloadMasked = (rgbFrameHeader[1] & d_bFrameHeader1_kfPayloadMasked); m_cblFrameData = (rgbFrameHeader[1] & d_bFrameHeader1_kmPayloadLength); // MessageLog_AppendTextFormatCo(COX_MakeBold(d_coBlue), "WebSocket Header: [0]=0x$x [1]=0x$x (Frame = $L bytes, $L bytes remaining)\n", rgbFrameHeader[0], rgbFrameHeader[1], m_cblFrameData, bytesAvailable()); switch (m_cblFrameData) { case d_bFrameHeader1_kePayloadLength16: m_eSocketState = eSocketState_WaitingForFrameHeaderPayload16; goto WaitingForFrameHeaderPayload16; case d_bFrameHeader1_kePayloadLength64: m_eSocketState = eSocketState_WaitingForFrameHeaderPayload64; goto WaitingForFrameHeaderPayload64; } // switch m_eSocketState = eSocketState_WaitingForFrameHeaderMask; goto WaitingForFrameHeaderMask; } break; case eSocketState_WaitingForFrameHeaderPayload16: WaitingForFrameHeaderPayload16: cbDataAvailable -= sizeof(quint16); if (cbDataAvailable >= 0) { quint16 cbwFrameData; read(OUT (char *)&cbwFrameData, sizeof(cbwFrameData)); m_cblFrameData = qFromBigEndian(cbwFrameData); m_eSocketState = eSocketState_WaitingForFrameHeaderMask; //MessageLog_AppendTextFormatCo(COX_MakeBold(d_coRed), "WebSocket Payload16: $L bytes\n", m_cblFrameData); goto WaitingForFrameHeaderMask; } break; case eSocketState_WaitingForFrameHeaderPayload64: WaitingForFrameHeaderPayload64: cbDataAvailable -= sizeof(quint64); if (cbDataAvailable >= 0) { quint64 cblFrameData; read(OUT (char *)&cblFrameData, sizeof(cblFrameData)); m_cblFrameData = qFromBigEndian(cblFrameData); MessageLog_AppendTextFormatCo(COX_MakeBold(d_coRed), "WebSocket Payload64: $L bytes\n", m_cblFrameData); m_eSocketState = eSocketState_WaitingForFrameHeaderMask; goto WaitingForFrameHeaderMask; } break; case eSocketState_WaitingForFrameHeaderMask: WaitingForFrameHeaderMask: if (m_bFrameHeader1_kfPayloadMasked) { MessageLog_AppendTextFormatCo(d_coRed, "Frame is masked\n"); cbDataAvailable -= sizeof(m_rgbFrameMask); if (cbDataAvailable < 0) break; read(OUT (char *)m_rgbFrameMask, sizeof(m_rgbFrameMask)); } m_eSocketState = eSocketState_WaitingForFrameDataPayload; // Fall Through // case eSocketState_WaitingForFrameDataPayload: cbDataAvailable -= m_cblFrameData; if (cbDataAvailable >= 0) { BYTE * pbData = m_binFrameData.PbeAllocateExtraDataWithVirtualNullTerminator(m_cblFrameData); const int cbDataRead = read(OUT (char *)pbData, m_cblFrameData); // Read the data from the socket if (cbDataRead != m_cblFrameData) MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "WebSocket: cbDataRead=$I, m_cblFrameData=$L\n", cbDataRead, m_cblFrameData); // MessageLog_AppendTextFormatCo(d_coBlueDark, "$s\n", pbData); if (m_bFrameHeader0_kfFragmentFinal) { // Check if there are any special opcodes the socket can handle automatically switch (m_bFrameHeader0_eOpcode) { case eOpcode_DataText: case eOpcode_DataBinary: emit SI_MessageAvailable(INOUT m_binFrameData); // Both text and binary are treated the same, as Cambrian uses UTF-8 for text break; case eOpcode_Ping: DataWrite(INOUT m_binFrameData, eOpcode_Pong); // Respond to the ping request break; case eOpcode_Close: // Close the socket break; } // switch m_binFrameData.Empty(); } // if m_eSocketState = eSocketState_WaitingForFrameHeader; goto WaitingForFrameHeader; } break; } // switch g_oMutex.unlock(); } // SL_DataAvailable()