// ------------------------------------------------------------------- // Send // ------------------------------------------------------------------- void UDPManager::Send(boost::shared_ptr<ByteArray> binaryData) { if (initSuccess) { try { udpSocket->Write(binaryData->Bytes()); if (sfs->Debug()) { boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back("UDP Data written: "); logMessages->push_back(*(DefaultObjectDumpFormatter::HexDump(binaryData))); log->Info(logMessages); } } catch(exception ex) { boost::shared_ptr<string> message (new string(ex.what())); char buffer[512]; sprintf (buffer, "WriteUDP operation failed due to Error: %s", message->c_str()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); log->Error(logMessages); } } else { boost::shared_ptr<vector<string> > messages (new vector<string>()); messages->push_back("UDP protocol is not initialized yet. Pleas use the initUDP() method."); log->Warn(messages); } }
void logging(std::string message, LogType type, LogStatus status) { static std::ofstream _logFile; static std::string _logFileName; static int _logIndex = 1; openLog(_logFile, _logFileName); assert(logType(type)!=LOG_ASSERT_FAILURE); //raise if type is wrongly inputted _logFile << _logIndex << LOGGING_INDEX_BRACKET << getTimeStamp(Current) << logMessages(LOGGING_FORMAT, message) << logType(type) << logStatus(status); _logIndex++; }
// ------------------------------------------------------------------- // OnUDPError // ------------------------------------------------------------------- void UDPManager::OnUDPError(unsigned long long context, boost::shared_ptr<string> msg, SocketErrors se) { // Map context UDPManager* instance = (UDPManager*)context; char buffer[512]; sprintf (buffer, "Unexpected UDP I/O Error. %s [%ld]", msg->c_str(), se); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Warn(logMessages); }
void Log::openLog(ofstream& _logFile, string& _logFileName) { static bool isOpen = false; if(!isOpen){ createFileName(_logFileName); _logFile.open(_logFileName, std::ios::out); assert(_logFile.is_open()); //raise if file has not been opened at this point isOpen = true; _logFile << logMessages(LOGGING_STARTING); } return; }
void cleanup_s() { // If we're supposed to print out statistics, do so now. if (printStats()) statistics_s.print(pinfo, reductionFilter_s); // Close the log file, if necessary. logMessages(0); // Turn off all POOMA streams. infoMessages(false); warnMessages(false); errorMessages(false); debugLevel(Inform::off); }
// ------------------------------------------------------------------- // OnTimeout // ------------------------------------------------------------------- void UDPManager::OnTimeout(const boost::system::error_code& code) { if (code == boost::asio::error::operation_aborted) { // Timer has been stopped // Nothing to do return; } // Timer is expired if (initSuccess) return; if (currentAttempt < MAX_RETRY) { // Try again currentAttempt++; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); boost::shared_ptr<string> logMessage (new string()); boost::shared_ptr<string> format (new string("UDP Init Attempt: %d")); StringFormatter<long int> (logMessage, format, currentAttempt); logMessages->push_back(*logMessage); log->Debug(logMessages); SendInitializationRequest(); StartTimer(); } else { // If we get here all trials failed currentAttempt = 0; locked = false; boost::shared_ptr<map<string, boost::shared_ptr<void> > > evtParams (new map<string, boost::shared_ptr<void> >()); boost::shared_ptr<bool> value (new bool()); *value = false; evtParams->insert(pair<string, boost::shared_ptr<void> >("success", value)); boost::shared_ptr<SFSEvent> evt (new SFSEvent(SFSEvent::UDP_INIT, evtParams)); sfs->DispatchEvent(evt); } }
// ------------------------------------------------------------------- // OnSocketData // ------------------------------------------------------------------- void BitSwarmClient::OnSocketData(unsigned long long context, boost::shared_ptr<vector<unsigned char> > data) { BitSwarmClient* instance = (BitSwarmClient*)context; instance->lockDispose.lock(); if (instance->isDisposed == true) { instance->lockDispose.unlock(); return; } /* * Catches possible data errors... we have seen a few * http://www.smartfoxserver.com/forums/viewtopic.php?t=10314 */ try { boost::shared_ptr<ByteArray> buffer (new ByteArray(data)); instance->ioHandler->OnDataRead(buffer); } catch (exception e) { boost::shared_ptr<string> message (new string(e.what())); char buffer[512]; sprintf (buffer, "## SocketDataError: %s", message->c_str()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Error(logMessages); boost::shared_ptr<BitSwarmEvent> evt (new BitSwarmEvent(BitSwarmEvent::DATA_ERROR)); boost::shared_ptr<map<string, boost::shared_ptr<void> > > args (new map<string, boost::shared_ptr<void> >()); args->insert(pair<string, boost::shared_ptr<void> >("message", message)); evt->Params(args); instance->DispatchEvent(evt); } instance->lockDispose.unlock(); }
// ------------------------------------------------------------------- // OnBBError // ------------------------------------------------------------------- void BitSwarmClient::OnBBError(unsigned long long context, boost::shared_ptr<BaseEvent> e) { BitSwarmClient* instance = (BitSwarmClient*)context; boost::shared_ptr<BBEvent> evt = (boost::static_pointer_cast<BBEvent>)(e); boost::shared_ptr<string> evtMessage = (boost::static_pointer_cast<string>)((*(evt->Params()))["message"]); char buffer[512]; sprintf (buffer, "## BlueBox Error: %s", evtMessage->c_str()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Error(logMessages); boost::shared_ptr<BitSwarmEvent> bevt (new BitSwarmEvent(BitSwarmEvent::IO_ERROR)); boost::shared_ptr<map<string, boost::shared_ptr<void> > > args (new map<string, boost::shared_ptr<void> >()); args->insert(pair<string, boost::shared_ptr<void> >("message", evtMessage)); bevt->Params(args); instance->DispatchEvent(bevt); }
// ------------------------------------------------------------------- // OnUDPData // ------------------------------------------------------------------- void UDPManager::OnUDPData(unsigned long long context, boost::shared_ptr<vector<unsigned char> > bt) { // Map context UDPManager* instance = (UDPManager*)context; boost::shared_ptr<ByteArray> bytes (new ByteArray(bt)); // Not enough data! if (bytes->BytesAvailable() < 4) { char buffer[512]; sprintf (buffer, "Too small UDP packet. Len: %ld", bytes->Length()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Warn(logMessages); return; } if (instance->sfs->Debug()) { boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back("UDP Data Read: "); logMessages->push_back(*(DefaultObjectDumpFormatter::HexDump(bytes))); instance->log->Info(logMessages); } // Skip the header byte unsigned char header; bytes->ReadByte(header); // Get the compression and encryption flags bool compressed = (header & 0x20) > 0; bool encrypted = (header & 0x40) > 0; // Read the size of message (UDP can only use the short version) short dataSize; bytes->ReadShort(dataSize); if (dataSize != bytes->BytesAvailable()) { char buffer[512]; sprintf (buffer, "Insufficient UDP data. Expected: %ld, got: %ld", dataSize, bytes->BytesAvailable()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Warn(logMessages); return; } // Grab the message body and deserialize it boost::shared_ptr<vector<unsigned char> > data (new vector<unsigned char>()); bytes->ReadBytes(bytes->BytesAvailable(), *(data.get())); boost::shared_ptr<ByteArray> objBytes (new ByteArray(data)); // Handle encryption if (encrypted) { try { instance->packetEncrypter->Decrypt(objBytes); } catch(exception ex) { boost::shared_ptr<string> message (new string(ex.what())); char buffer[512]; sprintf (buffer, "UDP data decryption failed due to error: %s", message->c_str()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Error(logMessages); return; } } // Handle compression if (compressed) { objBytes->Uncompress(); } boost::shared_ptr<ISFSObject> reqObj = SFSObject::NewFromBinaryData(objBytes); // Check if this is an UDP Handshake response. If so, fire event and stop here. if (reqObj->ContainsKey("h")) { if (!instance->initSuccess) { // Unlock instance->StopTimer(); instance->locked = false; instance->initSuccess = true; boost::shared_ptr<map<string, boost::shared_ptr<void> > > evtParams (new map<string, boost::shared_ptr<void> >()); boost::shared_ptr<bool> value (new bool()); *value = true; evtParams->insert(pair<string, boost::shared_ptr<void> >("success", value)); boost::shared_ptr<SFSEvent> evt (new SFSEvent(SFSEvent::UDP_INIT, evtParams)); instance->sfs->DispatchEvent(evt); } return; } // Hand it to the ProtocolCodec instance->sfs->GetSocketEngine()->IoHandler()->Codec()->OnPacketRead(reqObj); }
// ------------------------------------------------------------------- // OnSocketClose // ------------------------------------------------------------------- void BitSwarmClient::OnSocketClose(unsigned long long context) { BitSwarmClient* instance = (BitSwarmClient*)context; instance->lockDispose.lock(); if (instance->isDisposed == true) { instance->lockDispose.unlock(); return; } bool isRegularDisconnection = instance->sfs==NULL || (!instance->attemptingReconnection && instance->sfs->GetReconnectionSeconds() == 0); //bool isManualDisconnection = (evt!=null) && (string)evt.Params["reason"] == ClientDisconnectionReason.MANUAL; bool isManualDisconnection = instance->manualDisconnection; /* * There are three cases in which we need to acknowledge the disconnection * * 1. We're in the middle of Reconnection Attempt: * In this case a disconnection means that there's no way we can reconnect, so end of story. * * 2. It is Regular Disconnection (no reconnection feature available) * * 3. It is a voluntary (Manual) disconnection, initiated on the client * */ if (instance->attemptingReconnection || isRegularDisconnection || isManualDisconnection) { // Reset UDP Manager if (instance->udpManager!=NULL) { instance->udpManager->Reset(); } /* * Disconnection at socket level * Dispatching the event here only in the case of manual disconnection. If it's disconnection from server * This will be dispatched from the server disconnection event handler */ if (isManualDisconnection) { boost::shared_ptr<map<string, boost::shared_ptr<void> > > args (new map<string, boost::shared_ptr<void> >()); args->insert(pair<string, boost::shared_ptr<void> >("reason", (boost::static_pointer_cast<void>)(ClientDisconnectionReason::MANUAL))); boost::shared_ptr<BitSwarmEvent> evt (new BitSwarmEvent(BitSwarmEvent::DISCONNECT, args)); instance->sfs->DispatchEvent(evt); // Don't resetting manualDisconnection flag here as there will be OnSocketError event } if (!instance->attemptingReconnection) { instance->lockDispose.unlock(); return; } } char buffer[512]; sprintf (buffer, "Attempting reconnection in %ld sec", instance->ReconnectionSeconds()); string logMessage = buffer; boost::shared_ptr<vector<string> > logMessages (new vector<string>()); logMessages->push_back(logMessage); instance->log->Debug(logMessages); //--- Attempt a reconnection to the server -------------------------------------------------------- if (instance->attemptingReconnection == false) { /* * If we aren't in any of the above three cases then it's time to attempt a * reconnection to the server. */ instance->attemptingReconnection = true; // Fire event and retry boost::shared_ptr<BitSwarmEvent> evt (new BitSwarmEvent(BitSwarmEvent::RECONNECTION_TRY)); instance->DispatchEvent(evt); // Retry connection: pause n seconds and retry // instance->RetryConnection(instance->ReconnectionSeconds()/**1000*/); instance->RetryConnection(1); } instance->lockDispose.unlock(); }