X Tutup
/* * Copyright (C) 2012 Yee Young Han (http://blog.naver.com/websearch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "SipStackDefine.h" #ifdef USE_TLS #include "SipStackThread.h" #include "TcpSessionList.h" #include "ServerUtility.h" #include "SipQueue.h" #include "Log.h" #include #include "MemoryDebug.h" /** * @ingroup SipStack * @brief SIP ¸Þ½ÃÁö¸¦ ÆÄ½ÌÇÏ¿©¼­ SIP stack ¿¡ ÀÔ·ÂÇÑ´Ù. * @param pclsSipStack SIP stack * @param iThreadId UDP ¾²·¹µå ¹øÈ£ * @param pszBuf ³×Æ®¿öÅ©¿¡¼­ ¼ö½ÅµÈ SIP ¸Þ½ÃÁö * @param iBufLen ³×Æ®¿öÅ©¿¡¼­ ¼ö½ÅµÈ SIP ¸Þ½ÃÁöÀÇ ±æÀÌ * @param pszIp IP ÁÖ¼Ò * @param iPort Æ÷Æ® ¹øÈ£ * @returns ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù. */ static bool SipMessageProcess( CSipStack * pclsSipStack, int iThreadId, const char * pszBuf, int iBufLen, const char * pszIp, unsigned short iPort ) { CLog::Print( LOG_NETWORK, "TlsRecv(%s:%d) [%.*s]", pszIp, iPort, iBufLen, pszBuf ); if( pclsSipStack->m_clsSetup.m_iTcpCallBackThreadCount > 0 ) { return gclsSipQueue.Insert( pszBuf, iBufLen, pszIp, iPort, E_SIP_TLS ); } return pclsSipStack->RecvSipMessage( iThreadId, pszBuf, iBufLen, pszIp, iPort, E_SIP_TLS ); } /** * @ingroup SipStack * @brief TLS ¼¼¼ÇÀ» À§ÇÑ ¾²·¹µå ÇÔ¼ö * @param lpParameter CThreadListEntry °´Ã¼ÀÇ Æ÷ÀÎÅÍ * @returns 0 À» ¸®ÅÏÇÑ´Ù. */ THREAD_API SipTlsThread( LPVOID lpParameter ) { CThreadListEntry * pclsEntry = (CThreadListEntry *)lpParameter; CSipStack * pclsSipStack = (CSipStack *)pclsEntry->m_pUser; CTcpSessionList clsSessionList( pclsSipStack, E_SIP_TLS ); CTcpComm clsTcpComm; int n, i, iBufLen, iThreadId; char szBuf[SIP_MAX_BUF_SIZE], *pszBuf; time_t iTime, iDeleteTime; pclsSipStack->IncreateTcpThreadCount( iThreadId ); if( clsSessionList.Init( pclsSipStack->m_clsSetup.m_iTcpMaxSocketPerThread + 1 ) == false ) goto FUNC_END; if( clsSessionList.Insert( pclsEntry->m_hRecv ) == false ) goto FUNC_END; time( &iDeleteTime ); while( pclsSipStack->m_bStopEvent == false ) { n = poll( clsSessionList.m_psttPollFd, clsSessionList.m_iPoolFdCount, 1000 ); time( &iTime ); if( n <= 0 ) goto LOOP_END; if( clsSessionList.m_psttPollFd[0].revents & POLLIN ) { if( CThreadList::RecvCommand( clsSessionList.m_psttPollFd[0].fd, (char *)&clsTcpComm, sizeof(clsTcpComm) ) == sizeof(clsTcpComm) ) { if( clsTcpComm.m_psttSsl ) { if( clsSessionList.Insert( clsTcpComm, clsTcpComm.m_psttSsl ) ) { pclsSipStack->m_clsTlsSocketMap.Insert( clsTcpComm.m_szIp, clsTcpComm.m_iPort, clsTcpComm.m_hSocket, clsTcpComm.m_psttSsl ); } else { pclsSipStack->TcpSessionEnd( clsTcpComm.m_szIp, clsTcpComm.m_iPort, E_SIP_TLS ); SSLClose( clsTcpComm.m_psttSsl ); closesocket( clsTcpComm.m_hSocket ); pclsEntry->DecreaseSocketCount(); } } else { SSL * psttSsl; bool bRes = false; if( SSLAccept( clsTcpComm.m_hSocket, &psttSsl, false, 0, pclsSipStack->m_clsSetup.m_iTlsAcceptTimeout * 1000 ) ) { if( clsSessionList.Insert( clsTcpComm, psttSsl ) ) { pclsSipStack->m_clsTlsSocketMap.Insert( clsTcpComm.m_szIp, clsTcpComm.m_iPort, clsTcpComm.m_hSocket, psttSsl ); bRes = true; } else { SSLClose( psttSsl ); } } if( bRes == false ) { closesocket( clsTcpComm.m_hSocket ); pclsEntry->DecreaseSocketCount(); } } } --n; } if( n == 0 ) goto LOOP_END; for( i = 1; i < clsSessionList.m_iPoolFdCount; ++i ) { if( !(clsSessionList.m_psttPollFd[i].revents & POLLIN) ) continue; n = SSLRecv( clsSessionList.m_clsList[i].m_psttSsl, szBuf, sizeof(szBuf) ); if( n <= 0 ) { CLOSE_SESSION: pclsSipStack->m_clsTlsSocketMap.Delete( clsSessionList.m_clsList[i].m_strIp.c_str(), clsSessionList.m_clsList[i].m_iPort ); clsSessionList.Delete( i, pclsEntry ); continue; } clsSessionList.m_clsList[i].m_iRecvTime = iTime; if( clsSessionList.m_clsList[i].m_clsSipBuf.AddBuf( szBuf, n ) == false ) goto CLOSE_SESSION; while( clsSessionList.m_clsList[i].m_clsSipBuf.GetSipMessage( &pszBuf, &iBufLen ) ) { SipMessageProcess( pclsSipStack, iThreadId, pszBuf, iBufLen, clsSessionList.m_clsList[i].m_strIp.c_str(), clsSessionList.m_clsList[i].m_iPort ); clsSessionList.m_clsList[i].m_clsSipBuf.ShiftBuf( iBufLen ); } } LOOP_END: if( ( iDeleteTime + 5 ) < iTime ) { clsSessionList.DeleteTimeout( pclsSipStack->m_clsSetup.m_iTcpRecvTimeout, pclsEntry ); iDeleteTime = iTime; } } clsSessionList.DeleteAll( pclsEntry ); FUNC_END: pclsSipStack->ThreadEnd( iThreadId ); pclsSipStack->DecreateTcpThreadCount(); #if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_remove_thread_state( NULL ); #endif return 0; } /** * @ingroup SipStack * @brief TLS ÇÁ·ÎÅäÄÝ·Î SIP ¸Þ½ÃÁö ¼ö½Å ¹× SIP ¼ö½Å À̺¥Æ®¸¦ ó¸®ÇÏ´Â ¾²·¹µå ÇÔ¼ö * @param lpParameter SIP stack Æ÷ÀÎÅÍ * @returns 0 À» ¸®ÅÏÇÑ´Ù. */ THREAD_API SipTlsListenThread( LPVOID lpParameter ) { CSipStack * pclsSipStack = (CSipStack *)lpParameter; struct pollfd arrPollFd[1]; int n, iThreadId; Socket hConnFd; CTcpComm clsTcpComm; if( pclsSipStack->m_hTlsSocket == INVALID_SOCKET ) { CLog::Print( LOG_ERROR, "%s pclsSipStack->m_hTlsSocket == INVALID_SOCKET", __FUNCTION__ ); goto FUNC_END; } pclsSipStack->IncreateTcpThreadCount( iThreadId ); TcpSetPollIn( arrPollFd[0], pclsSipStack->m_hTlsSocket ); while( pclsSipStack->m_bStopEvent == false ) { n = poll( arrPollFd, 1, 1000 ); if( n > 0 ) { if( !(arrPollFd[0].revents & POLLIN) ) continue; hConnFd = TcpAccept( arrPollFd[0].fd, clsTcpComm.m_szIp, sizeof(clsTcpComm.m_szIp), &clsTcpComm.m_iPort, pclsSipStack->m_clsSetup.m_bIpv6 ); if( hConnFd == INVALID_SOCKET ) { continue; } clsTcpComm.m_hSocket = hConnFd; if( pclsSipStack->m_clsTlsThreadList.SendCommand( (char *)&clsTcpComm, sizeof(clsTcpComm) ) == false ) { closesocket( hConnFd ); } } } FUNC_END: pclsSipStack->DecreateTcpThreadCount( ); return 0; } /** * @ingroup SipStack * @brief TLS ÇÁ·ÎÅäÄÝ·Î SIP ¸Þ½ÃÁö ¼ö½Å ¹× SIP ¼ö½Å À̺¥Æ®¸¦ ó¸®ÇÏ´Â Thread Pool À» ½ÃÀÛÇÑ´Ù. * @param pclsSipStack SIP stack Æ÷ÀÎÅÍ * @returns ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ½ÇÆÐÇϸé false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool StartSipTlsListenThread( CSipStack * pclsSipStack ) { return StartThread( "SipTlsListenThread", SipTlsListenThread, pclsSipStack ); } #endif
X Tutup