bool InboundRTMPSDiscriminatorProtocol::BindSSL(IOBuffer &buffer) { //1. Create the RTMP protocol BaseProtocol *pRTMP = new InboundRTMPProtocol(); if (!pRTMP->Initialize(GetCustomParameters())) { FATAL("Unable to create RTMP protocol"); pRTMP->EnqueueForDelete(); return false; } //2. Destroy the link BaseProtocol *pFar = _pFarProtocol; pFar->ResetNearProtocol(); ResetFarProtocol(); //3. Create the new links pFar->SetNearProtocol(pRTMP); pRTMP->SetFarProtocol(pFar); //4. Set the application pRTMP->SetApplication(GetApplication()); //5. Enqueue for delete this protocol EnqueueForDelete(); //6. Process the data if (!pRTMP->SignalInputData(buffer)) { FATAL("Unable to process data"); pRTMP->EnqueueForDelete(); } return true; }
BaseProtocol *InboundHTTP4RTMP::Bind(string sid) { BaseProtocol *pResult = NULL; if (_pNearProtocol == NULL) { //14. This might be a new connection. Do we have that sid generated? if (!MAP_HAS1(_generatedSids, sid)) { FATAL("Invalid sid: %s", STR(sid)); return false; } //15. See if we have to generate a new connection or we just pick up //a disconnected one if (MAP_HAS1(_protocolsBySid, sid)) { pResult = ProtocolManager::GetProtocol(_protocolsBySid[sid]); } else { pResult = new InboundRTMPProtocol(); pResult->Initialize(GetCustomParameters()); pResult->SetApplication(GetApplication()); _protocolsBySid[sid] = pResult->GetId(); SetNearProtocol(pResult); pResult->SetFarProtocol(this); } } else { pResult = _pNearProtocol; } return pResult; }
bool TSAppProtocolHandler::DoHTTPRequest(BaseProtocol *pProtocol) { //1. Get the paramaters Variant ¶meters = pProtocol->GetCustomParameters(); //2. Get the http protocol OutboundHTTPProtocol *pHTTP = NULL; BaseProtocol *pTemp = pProtocol; while (pTemp != NULL) { if (pTemp->GetType() == PT_OUTBOUND_HTTP) { pHTTP = (OutboundHTTPProtocol *) pTemp; break; } pTemp = pTemp->GetFarProtocol(); } if (pHTTP == NULL) { FATAL("This is not a HTTP based protocol chain"); return false; } //3. We wish to disconnect after the transfer is complete pHTTP->SetDisconnectAfterTransfer(true); //4. This is a GET request pHTTP->Method(HTTP_METHOD_GET); //5. Our document and the host pHTTP->Document(parameters["document"]); pHTTP->Host(parameters["host"]); //6. Done return pHTTP->EnqueueForOutbound(); }
void HTTPBuffAppProtocolHandler::RegisterProtocol(BaseProtocol *pProtocol) { //1. Get the TS protocol ID from the parameters uint32_t tsId = pProtocol->GetCustomParameters()["payload"]["tsId"]; //2. Get the TS protocol BaseProtocol *pTSProtocol = ProtocolManager::GetProtocol(tsId); if (pTSProtocol == NULL) { FATAL("Unable to get TS protocol by id: %u", tsId); pProtocol->EnqueueForDelete(); return; } //3. Link them pProtocol->SetNearProtocol(pTSProtocol); pTSProtocol->SetFarProtocol(pProtocol); //4. make sure that upper protocols survive AES protocol death pProtocol->DeleteNearProtocol(false); //5. Do the HTTP request if (!((GenericProtocol *) pProtocol)->DoHTTPRequest()) { FATAL("Unable to do HTTP request"); pProtocol->EnqueueForDelete(); return; } }
void OutboundConnectivity::SignalDetachedFromInStream() { BaseProtocol *pProtocol = ProtocolManager::GetProtocol(_rtpClient.protocolId); if (pProtocol != NULL) { pProtocol->EnqueueForDelete(); } _pRTSPProtocol = NULL; }
bool OutboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) { switch (_rtmpState) { case RTMP_STATE_NOT_INITIALIZED: { _encrypted = (VariantType) _customParameters[CONF_PROTOCOL] == V_STRING && _customParameters[CONF_PROTOCOL] == CONF_PROTOCOL_OUTBOUND_RTMPE; _usedScheme = _encrypted ? 1 : 0; if ((VariantType) _customParameters[CONF_PROTOCOL] == V_STRING && _customParameters[CONF_PROTOCOL] == CONF_PROTOCOL_OUTBOUND_RTMPE) { return PerformHandshakeStage1(true); } else { return PerformHandshakeStage1(false); } } case RTMP_STATE_CLIENT_REQUEST_SENT: { if (GETAVAILABLEBYTESCOUNT(buffer) < 3073) return true; if (!PerformHandshakeStage2(buffer, _encrypted)) { FATAL("Unable to handshake"); return false; } if (_pFarProtocol != NULL) { if (!_pFarProtocol->EnqueueForOutbound()) { FATAL("Unable to signal output data"); return false; } } if (_pKeyIn != NULL && _pKeyOut != NULL) { //insert the RTMPE protocol in the current protocol stack BaseProtocol *pFarProtocol = GetFarProtocol(); RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut, GETAVAILABLEBYTESCOUNT(_outputBuffer)); ResetFarProtocol(); pFarProtocol->SetNearProtocol(pRTMPE); pRTMPE->SetNearProtocol(this); //FINEST("New protocol chain: %s", STR(*pFarProtocol)); } if (!buffer.Ignore(3073)) { FATAL("Unable to ignore 3073 bytes"); return false; } _handshakeCompleted = true; return true; } default: { FATAL("Invalid RTMP state: %d", _rtmpState); return false; } } }
bool InboundHTTP4RTMP::ProcessIdle(vector<string> &parts) { BaseProtocol *pProtocol = Bind(parts[2]); if (pProtocol == NULL) { FATAL("Unable to bind protocol"); return false; } _outputBuffer.ReadFromByte(1); IOBuffer *pBuffer = pProtocol->GetOutputBuffer(); if (pBuffer != NULL) { _outputBuffer.ReadFromBuffer(GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer)); pBuffer->IgnoreAll(); } return BaseProtocol::EnqueueForOutbound(); }
void AppleStreamingClientApplication::SignalStreamUnRegistered(BaseStream *pStream) { if (pStream->GetType() != ST_IN_NET_TS) return; BaseProtocol *pProtocol = pStream->GetProtocol(); if (pProtocol == NULL) { ASSERT("Protocol is NULL!!!"); } uint32_t contextId = pProtocol->GetCustomParameters()["contextId"]; ClientContext *pContext = ClientContext::GetContext(contextId, 0, 0); if (pContext == NULL) { WARN("Context not available anymore"); pProtocol->EnqueueForDelete(); return; } pContext->SignalStreamUnRegistered(pStream); }
bool UnixDomainSocketAcceptor::Accept() { struct sockaddr_un remoteAddress; memset(&remoteAddress, 0, sizeof (struct sockaddr_un)); socklen_t len = sizeof (struct sockaddr_un); int32_t fd; int32_t error; //1. Accept the connection fd = accept(_inboundFd, (sockaddr *)&remoteAddress, &len); error = LASTSOCKETERROR; if (fd < 0) { FATAL("Unable to accept UX client connection: %s (%d)", strerror(error), error); return false; } if (!_enabled) { CLOSE_SOCKET(fd); _droppedCount++; WARN("Acceptor is not enabled. UX Client dropped: %s", STR(_sockPath)); return true; } INFO("Client connected: %s", STR(_sockPath)); //if (!setFdOptions(fd, false)) { // FATAL("Unable to set unix socket options"); // CLOSE_SOCKET(fd); // return false; //} //2. Create the chain BaseProtocol *pProtocol = ProtocolFactoryManager::CreateProtocolChain( _protocolChain, _parameters); if (pProtocol == NULL) { FATAL("Unable to create protocol chain"); CLOSE_SOCKET(fd); return false; } //3. Create the carrier and bind it UnixDomainSocketCarrier *pUnixDomainSocketCarrier = new UnixDomainSocketCarrier(fd, _sockPath); pUnixDomainSocketCarrier->SetProtocol(pProtocol->GetFarEndpoint()); pProtocol->GetFarEndpoint()->SetIOHandler(pUnixDomainSocketCarrier); //4. Register protocol for thread access UnixDomainSocketManager::RegisterUXThreadProtocol(pUnixDomainSocketCarrier->GetSocketName(), (UnixDomainSocketProtocol *)pUnixDomainSocketCarrier->GetProtocol()); //5. Register the protocol stack with an application if (_pApplication != NULL) { pProtocol = pProtocol->GetNearEndpoint(); pProtocol->SetApplication(_pApplication); } if (pProtocol->GetNearEndpoint()->GetOutputBuffer() != NULL) pProtocol->GetNearEndpoint()->EnqueueForOutbound(); _acceptedCount++; return true; }
BaseProtocol *ProtocolFactory::SpawnProtocol(uint64_t type, Variant ¶meters) { BaseProtocol *pResult = NULL; switch (type) { #ifdef HAS_MS_TIMER case PT_FINE_TIMER: pResult = new FineTimer(); break; #endif /* HAS_MS_TIMER */ case PT_INBOUND_MASTER_M3U8: pResult = new MasterM3U8Protocol(); break; case PT_INBOUND_CHILD_M3U8: pResult = new ChildM3U8Protocol(); break; case PT_INBOUND_KEY: pResult = new InboundKeyProtocol(); break; case PT_HTTP_BUFF: pResult = new HTTPBufferProtocol(); break; case PT_INBOUND_AES: pResult = new InboundAESProtocol(); break; default: FATAL("Spawning protocol %s not yet implemented", STR(tagToString(type))); break; } if (pResult != NULL) { if (!pResult->Initialize(parameters)) { FATAL("Unable to initialize protocol %s", STR(tagToString(type))); delete pResult; pResult = NULL; } } return pResult; }
BaseProtocol *DefaultProtocolFactory::SpawnProtocol(uint64_t type, Variant ¶meters) { BaseProtocol *pResult = NULL; switch (type) { case PT_TCP: pResult = new TCPProtocol(); break; case PT_UDP: pResult = new UDPProtocol(); break; case PT_INBOUND_SSL: pResult = new InboundSSLProtocol(); break; case PT_OUTBOUND_SSL: pResult = new OutboundSSLProtocol(); break; #ifdef HAS_PROTOCOL_DNS case PT_INBOUND_DNS: pResult = new InboundDNSResolverProtocol(); break; case PT_OUTBOUND_DNS: pResult = new OutboundDNSResolverProtocol(); break; #endif /* HAS_PROTOCOL_DNS */ #ifdef HAS_PROTOCOL_RTMP case PT_INBOUND_RTMP: pResult = new InboundRTMPProtocol(); break; case PT_INBOUND_RTMPS_DISC: pResult = new InboundRTMPSDiscriminatorProtocol(); break; case PT_OUTBOUND_RTMP: pResult = new OutboundRTMPProtocol(); break; #ifdef HAS_PROTOCOL_HTTP case PT_INBOUND_HTTP_FOR_RTMP: pResult = new InboundHTTP4RTMP(); break; #endif /* HAS_PROTOCOL_HTTP */ #endif /* HAS_PROTOCOL_RTMP */ #ifdef HAS_PROTOCOL_TS case PT_INBOUND_TS: pResult = new InboundTSProtocol(); break; #endif /* HAS_PROTOCOL_TS */ #ifdef HAS_PROTOCOL_HTTP case PT_INBOUND_HTTP: pResult = new InboundHTTPProtocol(); break; case PT_OUTBOUND_HTTP: pResult = new OutboundHTTPProtocol(); break; #endif /* HAS_PROTOCOL_HTTP */ #ifdef HAS_PROTOCOL_LIVEFLV case PT_INBOUND_LIVE_FLV: pResult = new InboundLiveFLVProtocol(); break; #endif /* HAS_PROTOCOL_LIVEFLV */ #ifdef HAS_PROTOCOL_VAR case PT_XML_VAR: pResult = new XmlVariantProtocol(); break; case PT_BIN_VAR: pResult = new BinVariantProtocol(); break; case PT_JSON_VAR: pResult = new JsonVariantProtocol(); break; #endif /* HAS_PROTOCOL_VAR */ #ifdef HAS_PROTOCOL_RTP case PT_RTSP: pResult = new RTSPProtocol(); break; case PT_RTCP: pResult = new RTCPProtocol(); break; case PT_INBOUND_RTP: pResult = new InboundRTPProtocol(); break; case PT_RTP_NAT_TRAVERSAL: pResult = new NATTraversalProtocol(); break; #endif /* HAS_PROTOCOL_RTP */ #ifdef HAS_PROTOCOL_CLI case PT_INBOUND_JSONCLI: pResult = new InboundJSONCLIProtocol(); break; case PT_HTTP_4_CLI: pResult = new HTTP4CLIProtocol(); break; #endif /* HAS_PROTOCOL_CLI */ #ifdef HAS_PROTOCOL_MMS case PT_OUTBOUND_MMS: pResult = new MMSProtocol(); break; #endif /* HAS_PROTOCOL_MMS */ #ifdef HAS_PROTOCOL_RAWHTTPSTREAM case PT_INBOUND_RAW_HTTP_STREAM: pResult = new InboundRawHTTPStreamProtocol(); break; #endif /* HAS_PROTOCOL_RAWHTTPSTREAM */ default: FATAL("Spawning protocol %s not yet implemented", STR(tagToString(type))); break; } if (pResult != NULL) { if (!pResult->Initialize(parameters)) { FATAL("Unable to initialize protocol %s", STR(tagToString(type))); delete pResult; pResult = NULL; } } return pResult; }
bool TCPAcceptor::Accept() { sockaddr address; memset(&address, 0, sizeof (sockaddr)); socklen_t len = sizeof (sockaddr); int32_t fd; int32_t error; //1. Accept the connection fd = accept(_inboundFd, &address, &len); error = errno; if (fd < 0) { FATAL("Unable to accept client connection: %s (%d)", strerror(error), error); return false; } if (!_enabled) { CLOSE_SOCKET(fd); _droppedCount++; WARN("Acceptor is not enabled. Client dropped: %s:%"PRIu16" -> %s:%"PRIu16, inet_ntoa(((sockaddr_in *) & address)->sin_addr), ENTOHS(((sockaddr_in *) & address)->sin_port), STR(_ipAddress), _port); return true; } INFO("Client connected: %s:%"PRIu16" -> %s:%"PRIu16, inet_ntoa(((sockaddr_in *) & address)->sin_addr), ENTOHS(((sockaddr_in *) & address)->sin_port), STR(_ipAddress), _port); if (!setFdOptions(fd)) { FATAL("Unable to set socket options"); CLOSE_SOCKET(fd); return false; } //4. Create the chain BaseProtocol *pProtocol = ProtocolFactoryManager::CreateProtocolChain(_protocolChain, _parameters); if (pProtocol == NULL) { FATAL("Unable to create protocol chain"); CLOSE_SOCKET(fd); return false; } //5. Create the carrier and bind it TCPCarrier *pTCPCarrier = new TCPCarrier(fd); pTCPCarrier->SetProtocol(pProtocol->GetFarEndpoint()); pProtocol->GetFarEndpoint()->SetIOHandler(pTCPCarrier); //6. Register the protocol stack with an application if (_pApplication != NULL) { pProtocol = pProtocol->GetNearEndpoint(); pProtocol->SetApplication(_pApplication); } if (pProtocol->GetNearEndpoint()->GetOutputBuffer() != NULL) pProtocol->GetNearEndpoint()->EnqueueForOutbound(); _acceptedCount++; //7. Done return true; }
bool InboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) { switch (_rtmpState) { case RTMP_STATE_NOT_INITIALIZED: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1537) { return true; } uint8_t handshakeType = GETIBPOINTER(buffer)[0]; if (!buffer.Ignore(1)) { FATAL("Unable to ignore one byte"); return false; } _currentFPVersion = ENTOHLP(GETIBPOINTER(buffer) + 4); switch (handshakeType) { case 3: //plain { return PerformHandshake(buffer, false); } case 6: //encrypted { return PerformHandshake(buffer, true); } default: { FATAL("Handshake type not implemented: %hhu", handshakeType); return false; } } } case RTMP_STATE_SERVER_RESPONSE_SENT: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1536) { return true; } else { //ignore the client's last handshake part if (!buffer.Ignore(1536)) { FATAL("Unable to ignore inbound data"); return false; } _handshakeCompleted = true; _rtmpState = RTMP_STATE_DONE; if (_pKeyIn != NULL && _pKeyOut != NULL) { //insert the RTMPE protocol in the current protocol stack BaseProtocol *pFarProtocol = GetFarProtocol(); RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); ResetFarProtocol(); pFarProtocol->SetNearProtocol(pRTMPE); pRTMPE->SetNearProtocol(this); FINEST("New protocol chain: %s", STR(*pFarProtocol)); //decrypt the leftovers RC4(_pKeyIn, GETAVAILABLEBYTESCOUNT(buffer), GETIBPOINTER(buffer), GETIBPOINTER(buffer)); } return true; } } default: { FATAL("Invalid RTMP state: %d", _rtmpState); return false; } } }
FOR_MAP(_clients, uint32_t, RTPClient, i) { BaseProtocol *pProtocol = ProtocolManager::GetProtocol(MAP_KEY(i)); if (pProtocol != NULL) pProtocol->EnqueueForDelete(); }
void EnvRun(string ip, uint16_t port, int logLevel) #endif /* ANDROID */ { //1. Initialize the logger logLevel = logLevel < 0 ? 0 : logLevel; logLevel = logLevel >= _FINEST_ ? _FINEST_ : logLevel; Logger::Init(); BaseLogLocation *pLogLocation = NULL; #ifdef ANDROID pLogLocation = new LogCatLogLocation(); pLogLocation->SetLevel(logLevel); Logger::AddLogLocation(pLogLocation); #else pLogLocation = new ConsoleLogLocation(true); pLogLocation->SetLevel(logLevel); Logger::AddLogLocation(pLogLocation); #endif /* ANDROID */ #ifdef BUILD_SIGNATURE //1.1 Create the settings string FATAL("Build signature:\n%s", BUILD_SIGNATURE); #endif /* BUILD_SIGNATURE */ //2. Create the default protocol factory DefaultProtocolFactory *pFactory = new DefaultProtocolFactory(); if (!ProtocolFactoryManager::RegisterProtocolFactory(pFactory)) { ASSERT("Unable to register default protocols factory"); } //3. Initialize the I/O IOHandlerManager::Initialize(); //4. Create the AppleStreamingClientApplication application Variant configuration; configuration[CONF_APPLICATION_NAME] = "applestreaminclient"; configuration[CONF_APPLICATION_ALIASES].PushToArray("asc"); configuration[CONF_APPLICATION_DEFAULT] = (bool)true; configuration[CONF_APPLICATION_VALIDATEHANDSHAKE] = (bool)true; configuration[CONF_APPLICATION_KEYFRAMESEEK] = (bool)true; configuration[CONF_APPLICATION_CLIENTSIDEBUFFER] = (int32_t) 15; configuration[CONF_APPLICATION_SEEKGRANULARITY] = 1.00; configuration[CONF_APPLICATION_MEDIAFOLDER] = "./"; configuration[CONF_APPLICATION_GENERATE_META_FILES] = (bool)false; configuration["rtspHost"] = format("rtsp://127.0.0.1:%hu/", port); AppleStreamingClientApplication *pApp = new AppleStreamingClientApplication( configuration); #ifdef ANDROID pApp->SetJavaCallBackInterface(ci); #endif /* ANDROID */ if (!pApp->Initialize()) { ASSERT("Unable to initialize the application"); } //6. Register it to the app manager if (!ClientApplicationManager::RegisterApplication(pApp)) { ASSERT("Unable to register application"); } //7. Create the RTSP acceptor Variant acceptorConfig; acceptorConfig[CONF_IP] = ip; acceptorConfig[CONF_PORT] = (uint16_t) port; acceptorConfig[CONF_PROTOCOL] = CONF_PROTOCOL_INBOUND_RTSP; vector<uint64_t> chain; chain = ProtocolFactoryManager::ResolveProtocolChain(acceptorConfig[CONF_PROTOCOL]); if (chain.size() == 0) { ASSERT("Invalid protocol chain: %s", STR(acceptorConfig[CONF_PROTOCOL])); } TCPAcceptor *pAcceptor = new TCPAcceptor(acceptorConfig[CONF_IP], (uint16_t) acceptorConfig[CONF_PORT], acceptorConfig, chain); if (!pAcceptor->StartAccept(pApp)) { ASSERT("Unable to fire up acceptor"); } //8. Create the bin variant acceptor acceptorConfig[CONF_PORT] = (uint16_t) (port + 1); acceptorConfig[CONF_PROTOCOL] = CONF_PROTOCOL_INBOUND_BIN_VARIANT; chain = ProtocolFactoryManager::ResolveProtocolChain(acceptorConfig[CONF_PROTOCOL]); if (chain.size() == 0) { ASSERT("Invalid protocol chain: %s", STR(acceptorConfig[CONF_PROTOCOL])); } pAcceptor = new TCPAcceptor(acceptorConfig[CONF_IP], (uint16_t) acceptorConfig[CONF_PORT], acceptorConfig, chain); if (!pAcceptor->StartAccept(pApp)) { ASSERT("Unable to fire up acceptor"); } //9. Create the xml variant acceptor acceptorConfig[CONF_PORT] = (uint16_t) (port + 2); acceptorConfig[CONF_PROTOCOL] = CONF_PROTOCOL_INBOUND_XML_VARIANT; chain = ProtocolFactoryManager::ResolveProtocolChain(acceptorConfig[CONF_PROTOCOL]); if (chain.size() == 0) { ASSERT("Invalid protocol chain: %s", STR(acceptorConfig[CONF_PROTOCOL])); } pAcceptor = new TCPAcceptor(acceptorConfig[CONF_IP], (uint16_t) acceptorConfig[CONF_PORT], acceptorConfig, chain); if (!pAcceptor->StartAccept(pApp)) { ASSERT("Unable to fire up acceptor"); } #ifdef HAS_PROTOCOL_RTMP //9. Create the RTMP acceptor acceptorConfig[CONF_PORT] = (uint16_t) (1935); acceptorConfig[CONF_PROTOCOL] = CONF_PROTOCOL_INBOUND_RTMP; chain = ProtocolFactoryManager::ResolveProtocolChain(acceptorConfig[CONF_PROTOCOL]); if (chain.size() == 0) { ASSERT("Invalid protocol chain: %s", STR(acceptorConfig[CONF_PROTOCOL])); } pAcceptor = new TCPAcceptor(acceptorConfig[CONF_IP], (uint16_t) acceptorConfig[CONF_PORT], acceptorConfig, chain); if (!pAcceptor->StartAccept(pApp)) { ASSERT("Unable to fire up acceptor"); } #endif /* HAS_PROTOCOL_RTMP */ //10. Create the timer UDP protocol #ifdef HAS_MS_TIMER acceptorConfig[CONF_PORT] = (uint16_t) (port + 3); acceptorConfig[CONF_PROTOCOL] = "fineTimer"; acceptorConfig["FineTimerPeriod"] = 0.2; chain = ProtocolFactoryManager::ResolveProtocolChain(acceptorConfig[CONF_PROTOCOL]); if (chain.size() == 0) { ASSERT("Invalid protocol chain: %s", STR(acceptorConfig[CONF_PROTOCOL])); } UDPCarrier *pUDPCarrier = UDPCarrier::Create(acceptorConfig[CONF_IP], (uint16_t) acceptorConfig[CONF_PORT]); if (pUDPCarrier == NULL) { ASSERT("Unable to bind on udp://%s:%hu", STR(acceptorConfig[CONF_IP]), (uint16_t) acceptorConfig[CONF_PORT]); } BaseProtocol *pTimer = ProtocolFactoryManager::CreateProtocolChain(chain, acceptorConfig); pTimer->GetFarEndpoint()->SetIOHandler(pUDPCarrier); pUDPCarrier->SetProtocol(pTimer->GetFarEndpoint()); pApp->SetFineTimerId(pTimer->GetId()); #endif /* HAS_MS_TIMER */ inet_aton("127.0.0.1", &gAddress.sin_addr); memset(&gAddress, 0, sizeof (gAddress)); gAddress.sin_family = AF_INET; gAddress.sin_port = EHTONS(port + 1); //10. Run while (IOHandlerManager::Pulse()) { IOHandlerManager::DeleteDeadHandlers(); ProtocolManager::CleanupDeadProtocols(); } //11. Shutting down protocols manager; ProtocolManager::Shutdown(); ProtocolManager::CleanupDeadProtocols(); //12. Shutting down I/O handlers manager IOHandlerManager::ShutdownIOHandlers(); IOHandlerManager::DeleteDeadHandlers(); IOHandlerManager::Shutdown(); //13. Unregister and delete default protocol handler ProtocolFactoryManager::UnRegisterProtocolFactory(pFactory); delete pFactory; pFactory = NULL; //14. Shutting down applications ClientApplicationManager::Shutdown(); //15. Shutting down the logger leaving you in the dark. Bye bye Logger::Free(true); }