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; }
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(); }
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); }