void CSteamProto::PollingThread(void*) { debugLog(_T("CSteamProto::PollingThread: entering")); ptrA token(getStringA("TokenSecret")); ptrA umqId(getStringA("UMQID")); UINT32 messageId = getDword("MessageID", 0); //PollApi::PollResult pollResult; int errors = 0; bool breaked = false; while (!isTerminated && !breaked && errors < POLLING_ERRORS_LIMIT) { PollRequest *request = new PollRequest(token, umqId, messageId, IdleSeconds()); //request->nlc = m_pollingConnection; HttpResponse *response = request->Send(m_hNetlibUser); delete request; if (response == NULL || response->resultCode != HTTP_CODE_OK) { if (response != NULL) delete response; errors++; continue; } else errors = 0; JSONROOT root(response->pData); JSONNode *node = json_get(root, "error"); ptrT error(json_as_string(node)); if (!lstrcmpi(error, _T("OK"))) { node = json_get(root, "messagelast"); messageId = json_as_int(node); node = json_get(root, "messages"); JSONNode *nroot = json_as_array(node); if (nroot != NULL) { ParsePollData(nroot); json_delete(nroot); } m_pollingConnection = response->nlc; } else if (!lstrcmpi(error, _T("Timeout"))) { continue; } /*else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now { if (!IsOnline()) { // need to relogin debugLog(_T("CSteamProto::PollingThread: not logged on")); SetStatus(ID_STATUS_OFFLINE); } breaked = true; }*/ else { // something wrong debugLog(_T("CSteamProto::PollingThread: %s (%d)"), error, response->resultCode); // token has expired if (response->resultCode == HTTP_CODE_UNAUTHORIZED) delSetting("TokenSecret"); // too low timeout? node = json_get(root, "sectimeout"); int timeout = json_as_int(node); if (timeout < STEAM_API_TIMEOUT) debugLog(_T("CSteamProto::PollingThread: Timeout is too low (%d)"), timeout); breaked = true; } delete response; } setDword("MessageID", messageId); m_hPollingThread = NULL; debugLog(_T("CSteamProto::PollingThread: leaving")); if (!isTerminated) { debugLog(_T("CSteamProto::PollingThread: unexpected termination; switching protocol to offline")); SetStatus(ID_STATUS_OFFLINE); } }
void CSkypeProto::PollingThread(void*) { debugLogA(__FUNCTION__ ": entering"); int nErrors = 0; while (!m_bThreadsTerminated) { m_hPollingEvent.Wait(); nErrors = 0; while ((nErrors < POLLING_ERRORS_LIMIT) && m_iStatus != ID_STATUS_OFFLINE) { PollRequest *request = new PollRequest(li); request->nlc = m_pollingConnection; NLHR_PTR response(request->Send(m_hNetlibUser)); delete request; if (response == NULL) { nErrors++; m_pollingConnection = nullptr; continue; } if (response->resultCode == 200) { if (response->pData) { char *pData = mir_strdup(response->pData); if (pData != NULL) { ForkThread(&CSkypeProto::ParsePollData, pData); } else { debugLogA(__FUNCTION__ ": memory overflow !!!"); break; } } } else { nErrors++; if (response->pData) { JSONNode root = JSONNode::parse(response->pData); const JSONNode &error = root["errorCode"]; if (error != NULL) { int errorCode = error.as_int(); if (errorCode == 729) { break; } } } } m_pollingConnection = response->nlc; } if (m_iStatus != ID_STATUS_OFFLINE) { debugLogA(__FUNCTION__ ": unexpected termination; switching protocol to offline"); SetStatus(ID_STATUS_OFFLINE); } } m_hPollingThread = NULL; m_pollingConnection = NULL; debugLogA(__FUNCTION__ ": leaving"); }
result_t BusHandler::handleSymbol() { long timeout = SYN_TIMEOUT; unsigned char sendSymbol = ESC; bool sending = false; BusRequest* startRequest = NULL; // check if another symbol has to be sent and determine timeout for receive switch (m_state) { case bs_noSignal: timeout = m_generateSynInterval>0 ? m_generateSynInterval : SIGNAL_TIMEOUT; break; case bs_skip: timeout = SYN_TIMEOUT; break; case bs_ready: if (m_currentRequest != NULL) setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up if (m_remainLockCount == 0 && m_currentRequest == NULL) { startRequest = m_nextRequests.next(false); if (startRequest == NULL && m_pollInterval > 0) { // check for poll/scan time_t now; time(&now); if (m_lastPoll == 0 || difftime(now, m_lastPoll) > m_pollInterval) { Message* message = m_messages->getNextPoll(); if (message != NULL) { m_lastPoll = now; PollRequest* request = new PollRequest(message); result_t ret = request->prepare(m_ownMasterAddress); if (ret != RESULT_OK) { logError(lf_bus, "prepare poll message: %s", getResultCode(ret)); delete request; } else { startRequest = request; m_nextRequests.add(request); } } } } if (startRequest != NULL) { // initiate arbitration sendSymbol = m_ownMasterAddress; sending = true; } } break; case bs_recvCmd: case bs_recvCmdAck: timeout = m_slaveRecvTimeout; break; case bs_recvRes: if (m_response.size() > 0 || m_slaveRecvTimeout > SYN_TIMEOUT) timeout = m_slaveRecvTimeout; else timeout = SYN_TIMEOUT; break; case bs_recvResAck: timeout = m_slaveRecvTimeout; break; case bs_sendCmd: if (m_currentRequest != NULL) { sendSymbol = m_currentRequest->m_master[m_nextSendPos]; // escaped command sending = true; } break; case bs_sendResAck: if (m_currentRequest != NULL) { sendSymbol = m_responseCrcValid ? ACK : NAK; sending = true; } break; case bs_sendCmdAck: if (m_currentRequest != NULL) { sendSymbol = m_commandCrcValid ? ACK : NAK; sending = true; } break; case bs_sendRes: if (m_currentRequest != NULL) { sendSymbol = m_response[m_nextSendPos]; // escaped response sending = true; } break; case bs_sendSyn: sendSymbol = SYN; sending = true; break; } // send symbol if necessary result_t result; if (sending) { result = m_device->send(sendSymbol); if (result == RESULT_OK) if (m_state == bs_ready) timeout = m_busAcquireTimeout; else timeout = SEND_TIMEOUT; else { sending = false; timeout = SYN_TIMEOUT; if (startRequest != NULL && m_nextRequests.remove(startRequest)) { m_currentRequest = startRequest; // force the failed request to be notified } setState(bs_skip, result); } } // receive next symbol (optionally check reception of sent symbol) unsigned char recvSymbol; result = m_device->recv(timeout, recvSymbol); if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0 && timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) { // check if acting as AUTO-SYN generator is required result = m_device->send(SYN); if (result == RESULT_OK) { recvSymbol = ESC; result = m_device->recv(SEND_TIMEOUT, recvSymbol); if (result == RESULT_ERR_TIMEOUT) { return setState(bs_noSignal, result); } if (result != RESULT_OK) logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); else if (recvSymbol != SYN) { logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol); } else if (m_generateSynInterval != SYN_TIMEOUT) { // received own AUTO-SYN symbol back again: act as AUTO-SYN generator now m_generateSynInterval = SYN_TIMEOUT; logNotice(lf_bus, "acting as AUTO-SYN generator"); } } return setState(bs_skip, result); } time_t now; time(&now); if (result != RESULT_OK) { if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1) // at least one full second has passed since last received symbol || m_state == bs_noSignal) return setState(bs_noSignal, result); return setState(bs_skip, result); } m_lastReceive = now; if (recvSymbol == SYN) { if (!sending && m_remainLockCount > 0 && m_command.size() != 1) m_remainLockCount--; else if (!sending && m_remainLockCount == 0 && m_command.size() == 1) m_remainLockCount = 1; // wait for next AUTO-SYN after SYN / address / SYN (bus locked for own priority) return setState(bs_ready, RESULT_ERR_SYN); } unsigned int headerLen, crcPos; switch (m_state) { case bs_noSignal: return setState(bs_skip, RESULT_OK); case bs_skip: return RESULT_OK; case bs_ready: if (startRequest != NULL && sending) { if (!m_nextRequests.remove(startRequest)) { // request already removed (e.g. due to timeout) return setState(bs_skip, RESULT_ERR_TIMEOUT); } m_currentRequest = startRequest; // check arbitration if (recvSymbol == sendSymbol) { // arbitration successful m_nextSendPos = 1; m_repeat = false; return setState(bs_sendCmd, RESULT_OK); } // arbitration lost. if same priority class found, try again after next AUTO-SYN m_remainLockCount = isMaster(recvSymbol) ? 2 : 1; // number of SYN to wait for before next send try if ((recvSymbol & 0x0f) != (sendSymbol & 0x0f) && m_lockCount > m_remainLockCount) // if different priority class found, try again after N AUTO-SYN symbols (at least next AUTO-SYN) m_remainLockCount = m_lockCount; setState(m_state, RESULT_ERR_BUS_LOST); // try again later } result = m_command.push_back(recvSymbol, false); // expect no escaping for master address if (result < RESULT_OK) return setState(bs_skip, result); m_repeat = false; return setState(bs_recvCmd, RESULT_OK); case bs_recvCmd: headerLen = 4; crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff; // header symbols are never escaped result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos); if (result < RESULT_OK) return setState(bs_skip, result); if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received unsigned char dstAddress = m_command[1]; m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); // header symbols are never escaped if (m_commandCrcValid) { if (dstAddress == BROADCAST) { receiveCompleted(); return setState(bs_skip, RESULT_OK); } if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) return setState(bs_sendCmdAck, RESULT_OK); return setState(bs_recvCmdAck, RESULT_OK); } if (dstAddress == BROADCAST) return setState(bs_skip, RESULT_ERR_CRC); if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) { return setState(bs_sendCmdAck, RESULT_ERR_CRC); } if (m_repeat) return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_recvCmdAck, RESULT_ERR_CRC); } return RESULT_OK; case bs_recvCmdAck: if (recvSymbol == ACK) { if (!m_commandCrcValid) return setState(bs_skip, RESULT_ERR_ACK); if (m_currentRequest != NULL) { if (isMaster(m_currentRequest->m_master[1])) { return setState(bs_sendSyn, RESULT_OK); } } else if (isMaster(m_command[1])) { // header symbols are never escaped receiveCompleted(); return setState(bs_skip, RESULT_OK); } m_repeat = false; return setState(bs_recvRes, RESULT_OK); } if (recvSymbol == NAK) { if (!m_repeat) { m_repeat = true; m_nextSendPos = 0; m_command.clear(); if (m_currentRequest != NULL) return setState(bs_sendCmd, RESULT_ERR_NAK, true); return setState(bs_recvCmd, RESULT_ERR_NAK); } return setState(bs_skip, RESULT_ERR_NAK); } return setState(bs_skip, RESULT_ERR_ACK); case bs_recvRes: headerLen = 0; crcPos = m_response.size() > headerLen ? headerLen + 1 + m_response[headerLen] : 0xff; result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos); if (result < RESULT_OK) return setState(bs_skip, result); if (result == RESULT_OK && crcPos != 0xff && m_response.size() == crcPos + 1) { // CRC received m_responseCrcValid = m_response[headerLen + 1 + m_response[headerLen]] == m_response.getCRC(); if (m_responseCrcValid) { if (m_currentRequest != NULL) return setState(bs_sendResAck, RESULT_OK); return setState(bs_recvResAck, RESULT_OK); } if (m_repeat) { if (m_currentRequest != NULL) return setState(bs_sendSyn, RESULT_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC); } if (m_currentRequest != NULL) return setState(bs_sendResAck, RESULT_ERR_CRC); return setState(bs_recvResAck, RESULT_ERR_CRC); } return RESULT_OK; case bs_recvResAck: if (recvSymbol == ACK) { if (!m_responseCrcValid) return setState(bs_skip, RESULT_ERR_ACK); receiveCompleted(); return setState(bs_skip, RESULT_OK); } if (recvSymbol == NAK) { if (!m_repeat) { m_repeat = true; m_response.clear(); return setState(bs_recvRes, RESULT_ERR_NAK, true); } return setState(bs_skip, RESULT_ERR_NAK); } return setState(bs_skip, RESULT_ERR_ACK); case bs_sendCmd: if (m_currentRequest != NULL && sending) { if (recvSymbol == sendSymbol) { // successfully sent m_nextSendPos++; if (m_nextSendPos >= m_currentRequest->m_master.size()) { // master data completely sent if (m_currentRequest->m_master[1] == BROADCAST) return setState(bs_sendSyn, RESULT_OK); m_commandCrcValid = true; return setState(bs_recvCmdAck, RESULT_OK); } return RESULT_OK; } } return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendResAck: if (m_currentRequest != NULL && sending) { if (recvSymbol == sendSymbol) { // successfully sent if (!m_responseCrcValid) { if (!m_repeat) { m_repeat = true; m_response.clear(); return setState(bs_recvRes, RESULT_ERR_NAK, true); } return setState(bs_sendSyn, RESULT_ERR_ACK); } return setState(bs_sendSyn, RESULT_OK); } } return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendCmdAck: if (sending && m_answer) { if (recvSymbol == sendSymbol) { // successfully sent if (!m_commandCrcValid) { if (!m_repeat) { m_repeat = true; m_command.clear(); return setState(bs_recvCmd, RESULT_ERR_NAK, true); } return setState(bs_skip, RESULT_ERR_ACK); } if (isMaster(m_command[1])) receiveCompleted(); // decode command and store value return setState(bs_skip, RESULT_OK); m_nextSendPos = 0; m_repeat = false; Message* message = m_messages->find(m_command); if (message == NULL || !message->isPassive() || message->isWrite()) return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny // build response and store in m_response for sending back to requesting master m_response.clear(true); // escape while sending response result = message->prepareSlave(m_response); if (result != RESULT_OK) return setState(bs_skip, result); return setState(bs_sendRes, RESULT_OK); } } return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendRes: if (sending && m_answer) { if (recvSymbol == sendSymbol) { // successfully sent m_nextSendPos++; if (m_nextSendPos >= m_response.size()) { // slave data completely sent return setState(bs_recvResAck, RESULT_OK); } return RESULT_OK; } } return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendSyn: if (sending) { if (recvSymbol == sendSymbol) { // successfully sent return setState(bs_skip, RESULT_OK); } } return setState(bs_skip, RESULT_ERR_INVALID_ARG); } return RESULT_OK; }