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);
	}
}
Beispiel #2
0
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");
}
Beispiel #3
0
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;
}