void SipProtocolServerBase::shutdownClients() { // For each client request shutdown int iteratorHandle = mClientList.getIteratorHandle(); SipClient* client = NULL; while ((client = (SipClient*)mClientList.next(iteratorHandle))) { client->requestShutdown(); } mClientList.releaseIteratorHandle(iteratorHandle); }
/* ONLY for Text messages */ static void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) { Q_UNUSED(lc) Q_UNUSED(room) qDebug() << __PRETTY_FUNCTION__ << "Text Message:" << message << "received from:" << linphone_address_as_string(from); SipClient *sc = SipClient::instance(); sc->messageReceivedCb(QString(message), QString(linphone_address_as_string(from))); }
void SipProtocolServerBase::deleteClient(SipClient* sipClient) { // Find the client in the list of clients and shut it down int iteratorHandle = mClientList.getIteratorHandle(); SipClient* client = NULL; #ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::deleteClient(%p)", mProtocolString.data(), sipClient); #endif while ((client = (SipClient*)mClientList.next(iteratorHandle))) { // Remove this bad client // This used to be a little over zealous and delete any // SipClient that was not ok. It was not checking if // the SipClient was busy or not so bad things could // happen. This is now on the conservative side and // deleting only the thing it is supposed to. if(client == sipClient) { #ifdef TEST_PRINT UtlString clientNames; client->getClientNames(clientNames); OsSysLog::add(FAC_SIP, PRI_DEBUG, "Removing %s client %p names:\n%s", mProtocolString.data(), this, clientNames.data()); #endif mClientList.remove(iteratorHandle); break; } } mClientList.releaseIteratorHandle(iteratorHandle); // Delete the client outside the lock on the list as // it can create a deadlock. If the client is doing // an operation that requires the locking list, the // client gets blocked from shutting down. We then // block here trying to delete the client forever. if(client) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::deleteClient(%p) done", mProtocolString.data(), sipClient); delete client; client = NULL; } #ifdef TEST_PRINT OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::deleteClient(%p) done", mProtocolString.data(), sipClient); #endif }
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message) { Q_UNUSED(lc) Q_UNUSED(message) SipClient *sc = SipClient::instance(); sc->registrationStateChangedCb(cstate); printf("New registration state %s for user id [%s] at proxy [%s]\n", linphone_registration_state_to_string(cstate), linphone_proxy_config_get_identity(cfg), linphone_proxy_config_get_addr(cfg)); }
SipClient* SipProtocolServerBase::getClient(const char* hostAddress, int hostPort, const char* localIp) { UtlBoolean isSameHost = FALSE; UtlString hostAddressString(hostAddress ? hostAddress : ""); int iteratorHandle = mClientList.getIteratorHandle(); SipClient* client = NULL; # if TEST_CLIENT_CREATION OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::getClient( %s, %d )", hostAddress, hostPort); # endif while ((client = (SipClient*)mClientList.next(iteratorHandle))) { // Are these the same host? isSameHost = client->isConnectedTo(hostAddressString, hostPort); if(isSameHost && client->isOk() && 0 == strcmp(client->getLocalIp(), localIp)) { break; } else if(isSameHost) { if(!client->isOk()) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "%s Client matches but is not OK", mProtocolString.data()); } } } mClientList.releaseIteratorHandle(iteratorHandle); # ifdef TEST_CLIENT_CREATION if (!client) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::getClient( %s, %d ) NOT FOUND", hostAddress, hostPort); } # endif return(client); }
void SipUdpServer::shutdownListener() { SipClient* pServer = NULL; UtlHashMapIterator iterator(mServers); UtlVoidPtr* pServerContainer = NULL; UtlString* pKey = NULL; while (pKey = (UtlString*)iterator()) { pServerContainer = (UtlVoidPtr*) iterator.value(); pServer = (SipClient*)pServerContainer->getValue(); if (pServer) { pServer->requestShutdown(); } } }
void SipUdpServer::printStatus() { UtlHashMapIterator iterator(mServers); UtlString* pKey = NULL; while ((pKey = dynamic_cast <UtlString*> (iterator()))) { SipClient* pServer = dynamic_cast <SipClient*> (iterator.value()); UtlString clientNames; long clientTouchedTime = pServer->getLastTouchedTime(); UtlBoolean clientOk = pServer->isOk(); pServer->getClientNames(clientNames); osPrintf("UDP server %p last used: %ld ok: %d names: \n%s \n", this, clientTouchedTime, clientOk, clientNames.data()); SipProtocolServerBase::printStatus(); } }
UtlBoolean SipUdpServer::sendTo(const SipMessage& message, const char* address, int port, const char* szLocalSipIp) { UtlBoolean sendOk; UtlVoidPtr* pServerContainer = NULL; SipClient* pServer = NULL; if (szLocalSipIp) { UtlString localKey(szLocalSipIp); pServerContainer = (UtlVoidPtr*)this->mServers.findValue(&localKey); if (pServerContainer) { pServer = (SipClient*) pServerContainer->getValue(); } } else { // no local sip IP specified, so, use the default one UtlString defaultKey(mDefaultIp); pServerContainer = (UtlVoidPtr*) mServers.findValue(&defaultKey); if (pServerContainer) { pServer = (SipClient*) pServerContainer->getValue(); } } if (pServer) { sendOk = pServer->sendTo(message, address, port); } else { sendOk = false; } return(sendOk); }
UtlBoolean SipProtocolServerBase::isOk() { UtlBoolean bRet = true; SipClient* pServer = NULL; UtlHashMapIterator iterator(mServers); UtlVoidPtr* pServerContainer = NULL; UtlString* pKey = NULL; while ((pKey = (UtlString*)iterator())) { pServerContainer = (UtlVoidPtr*)iterator.value(); if (pServerContainer) { pServer = (SipClient*)pServerContainer->getValue(); } if (pServer) { bRet = bRet && pServer->isOk(); } } return bRet; }
void SipProtocolServerBase::removeOldClients(long oldTime) { mClientLock.acquireWrite(); // Find the old clients in the list and shut them down int iteratorHandle = mClientList.getIteratorHandle(); SipClient* client; int numClients = mClientList.getCount(); int numDelete = 0; int numBusy = 0; SipClient** deleteClientArray = NULL; UtlString clientNames; while ((client = (SipClient*)mClientList.next(iteratorHandle))) { if(client->isInUseForWrite()) numBusy++; // Remove any client with a bad socket // With TCP clients let them stay around if they are still // good as the may stay open for the session // The clients opened from this side for sending requests // get closed by the server (i.e. other side). The clients // opened as servers for requests from the remote side are // explicitly closed on this side when the final response is // sent. if( ! client->isInUseForWrite() // can't remove it if writing to it... && ( ! client->isOk() // socket is bad || client->getLastTouchedTime() < oldTime // idle for long enough ) ) { client->getClientNames(clientNames); #ifdef TEST_PRINT osPrintf("Removing %s client names:\n%s\r\n", mProtocolString.data(), clientNames.data()); #endif OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::Removing old client %p:\n%s\r", mProtocolString.data(), client, clientNames.data()); mClientList.remove(iteratorHandle); // Delete the clients after releasing the lock if(!deleteClientArray) deleteClientArray = new SipClient*[numClients]; deleteClientArray[numDelete] = client; numDelete++; client = NULL; } else { # ifdef TEST_PRINT UtlString names; client->getClientNames(names); OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::removeOldClients leaving client:\n%s", mProtocolString.data(), names.data()); # endif } } mClientList.releaseIteratorHandle(iteratorHandle); mClientLock.releaseWrite(); if ( numDelete || numBusy ) // get rid of lots of 'doing nothing when nothing to do' messages in the log { OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::removeOldClients deleting %d of %d SipClients (%d busy)", mProtocolString.data(), numDelete, numClients, numBusy); } // These have been removed from the list so delete them // after releasing the locks for(int clientIndex = 0; clientIndex < numDelete; clientIndex++) { delete deleteClientArray[clientIndex]; } if(deleteClientArray) { delete[] deleteClientArray; deleteClientArray = NULL; } }
SipClient* SipProtocolServerBase::createClient(const char* hostAddress, int hostPort, const char* localIp) { UtlString remoteHostAddr; UtlBoolean clientStarted = FALSE; mClientLock.acquireWrite(); SipClient* client = getClient(hostAddress, hostPort, localIp); if(! client) { # if TEST_CLIENT_CREATION OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::createClient( %s, %d )", hostAddress, hostPort); # endif if(!portIsValid(hostPort)) { hostPort = mDefaultPort; # if TEST_CLIENT_CREATION OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipProtocolServerBase::createClient port defaulting to %d", hostPort); # endif } OsTime time; OsDateTime::getCurTimeSinceBoot(time); long beforeSecs = time.seconds(); OsSocket* clientSocket = buildClientSocket(hostPort, hostAddress, localIp); OsDateTime::getCurTimeSinceBoot(time); long afterSecs = time.seconds(); if(afterSecs - beforeSecs > 1) { OsSysLog::add(FAC_SIP, PRI_WARNING, "SIP %s socket create for %s:%d took %d seconds", mProtocolString.data(), hostAddress, hostPort, (int)(afterSecs - beforeSecs)); } UtlBoolean isOk = clientSocket->isOk(); int writeWait = 3000; // mSec UtlBoolean isReadyToWrite = clientSocket->isReadyToWrite(writeWait); if(!isReadyToWrite) { OsSysLog::add(FAC_SIP, PRI_WARNING, "SIP %s socket %s:%d not ready for writing after %d seconds", mProtocolString.data(), hostAddress, hostPort, (int) (writeWait/1000)); } if(isOk && isReadyToWrite) { #ifdef TEST osPrintf("Socket OK, creating client\n"); #endif client = new SipClient(clientSocket) ; if (client && mSipUserAgent->getUseRport() && clientSocket->getIpProtocol() == OsSocket::UDP) { client->setSharedSocket(TRUE) ; } #ifdef TEST osPrintf("Created client\n"); #endif if(mSipUserAgent) { client->setUserAgent(mSipUserAgent); } if (clientSocket->getIpProtocol() != OsSocket::UDP) { //osPrintf("starting client\n"); clientStarted = client->start(); if(!clientStarted) { osPrintf("SIP %s client failed to start\n", mProtocolString.data()); } } OsSysLog::add(FAC_SIP, PRI_DEBUG, "Sip%sServer::createClient client: %p %s -> %s:%d", mProtocolString.data(), client, localIp, hostAddress, hostPort); mClientList.push(client); } // The socket failed to be connected else { if(clientSocket) { if (!mSipUserAgent->getUseRport() || (clientSocket->getIpProtocol() == OsSocket::TCP)) { delete clientSocket; } clientSocket = NULL; } OsSysLog::add(FAC_SIP, PRI_WARNING, "Sip%sServer::createClient client %p Failed to create socket %s -> %s:%d", mProtocolString.data(), this, localIp, hostAddress, hostPort); } } int isBusy = FALSE; if(client) { isBusy = client->isInUseForWrite(); if(!isBusy) client->markInUseForWrite(); } mClientLock.releaseWrite(); if(client && isBusy) { if(!waitForClientToWrite(client)) client = NULL; } return(client); }