bool CrossfireServer::processHandshake(wchar_t* msg) {
	std::wstring string(msg);
	size_t start = wcslen(HANDSHAKE);
	size_t index = string.find_first_of(std::wstring(L"\r\n"), start);
	if (index == std::wstring::npos) {
		Logger::error("Invalid handshake packet, does not contain terminating '\\r\\n'");
		return false;
	}
	if (index != string.length() - 2) {
		Logger::error("Invalid handshake packet, length extends beyond terminating '\\r\\n'");
		return false;
	}

	std::wstring tools = string.substr(start, index - start);
	m_handshakeReceived = true;

	std::wstring handshake(HANDSHAKE);
	/* for now don't claim support for any tools */
	handshake.append(std::wstring(L"\r\n"));
	m_connection->send(handshake.c_str());

	/*
	* Some events may have been queued in the interval between the initial connection
	* and the handshake.  These events can be sent now that the handshake is complete.
	*/
	sendPendingEvents();

	return true;
}
Exemple #2
0
void ResourceManager::decodeResource( ResourceLoadOptions& options )
{
	Task* task = Allocate(GetResourcesAllocator(), Task);
	
	ResourceLoadOptions* taskOptions = Allocate(GetResourcesAllocator(),
		ResourceLoadOptions);

	*taskOptions = options;

	task->callback.Bind(ResourceTaskRun);
	task->userdata = taskOptions;

	numResourcesQueuedLoad.increment();

#ifdef ENABLE_THREADED_LOADING
	if( taskPool && asynchronousLoading && options.asynchronousLoad )
	{
		taskPool->add(task, options.isHighPriority);
		return;
	}
#endif

	task->run();
	sendPendingEvents();
}
Exemple #3
0
void ResourceManager::update()
{
	sendPendingEvents();

	// Update the archive watches.
	archive->monitor();

	removeUnusedResources();
}
void CrossfireServer::received(wchar_t* msg) {
	if (!m_handshakeReceived) {
		if (wcsncmp(msg, HANDSHAKE, wcslen(HANDSHAKE)) == 0) {
			processHandshake(msg);
			m_lastRequestSeq = -1;
		} else {
			Logger::error("Crossfire content received before handshake, not processing it");
		}
		return;
	}

	m_inProgressPacket->append(std::wstring(msg));
	std::wstring packet;
	do {
		wchar_t* parseErrorMessage = NULL;
		bool errorMessageRequiresFree = false;
		int code = CODE_OK;
		packet.clear();

		if (m_inProgressPacket->find(HEADER_CONTENTLENGTH) != 0) {
			code = CODE_MALFORMED_PACKET;
			parseErrorMessage = L"request packet does not start with 'Content-Length:', not processing it";
			m_inProgressPacket->clear();
			break;
		}

		size_t endIndex = m_inProgressPacket->find(wchar_t('\r'));
		if (endIndex == std::wstring::npos) {
			code = CODE_MALFORMED_PACKET;
			parseErrorMessage = L"request packet does not contain '\r', not processing it";
			m_inProgressPacket->clear();
			break;
		}

		size_t headerLength = wcslen(HEADER_CONTENTLENGTH);
		std::wstring lengthString = m_inProgressPacket->substr(headerLength, endIndex - headerLength);
		int lengthValue = _wtoi(lengthString.c_str());
		if (!lengthValue) {
			code = CODE_MALFORMED_PACKET;
			parseErrorMessage = L"request packet does not have a valid 'Content-Length' value, not processing it";
			m_inProgressPacket->clear();
			break;
		}

		if (m_inProgressPacket->find(L"\r\n", endIndex) != endIndex) {
			code = CODE_MALFORMED_PACKET;
			parseErrorMessage = L"request packet does not follow initial '\\r' with '\\n', not processing it";
			m_inProgressPacket->clear();
			break;
		}

		// TODO for now just skip over "tool:" lines, though these should really be validated

		size_t toolEnd = m_inProgressPacket->find(L"\r\n\r\n", endIndex);
		if (toolEnd == std::wstring::npos) {
			code = CODE_MALFORMED_PACKET;
			parseErrorMessage = L"request packet does not contain '\\r\\n\\r\\n' to delimit its header, not processing it";
			m_inProgressPacket->clear();
			break;
		}
		size_t toolsLength = toolEnd - endIndex;
		size_t targetLength = wcslen(HEADER_CONTENTLENGTH) + lengthString.length() + 3 * LINEBREAK_LENGTH + toolsLength + lengthValue;

		if (targetLength <= m_inProgressPacket->length()) {
			packet.assign(m_inProgressPacket->substr(0, targetLength));
			m_inProgressPacket->erase(0, targetLength);
		}

		if (packet.length()) {
			CrossfireRequest* request = NULL;
			code = m_processor->parseRequestPacket(&packet, &request, &parseErrorMessage);
			if (code != CODE_OK) {
				errorMessageRequiresFree = true;
			} else {
				unsigned int seq = request->getSeq();
				if (!(m_lastRequestSeq == -1 || seq == m_lastRequestSeq + 1)) {
					// TODO handle out-of-order packets
					Logger::log("packet received out of sequence, still processing it");
				}
				m_lastRequestSeq = seq;
				m_processingRequest = true;
				if (!performRequest(request)) {
					/*
					 * the request's command was not handled by the server,
					 * so try to delegate to the specified context, if any
					 */
					CrossfireContext* context = getRequestContext(request);
					if (!context) {
						Logger::error("request command was unknown to the server and a valid context id was not provided, not processing it");
					} else {
						if (!context->performRequest(request)) {
							Logger::error("request command was unknown to the server and to the specified context, not processing it");
						}
					}
				}
				m_processingRequest = false;
				delete request;

				/*
				 * Debugger events may have been received in response to the request that was
				 * just processed.  These events can be sent now that processing of the request
				 * is complete.
				 */
				sendPendingEvents();
			}
		}

		if (code) {
			CrossfireResponse response;
			response.setCode(CODE_MALFORMED_PACKET);
			response.setMessage(parseErrorMessage);
			if (errorMessageRequiresFree) {
				free(parseErrorMessage);
			}
			Value emptyBody;
			emptyBody.setType(TYPE_OBJECT);
			response.setBody(&emptyBody);
			sendResponse(&response);
		}
	} while (packet.length() > 0 && m_inProgressPacket->length() > 0);
}