⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voip_stream_server.c

📁 telcobridges voip develop
💻 C
📖 第 1 页 / 共 4 页
字号:
/*--------------------------------------------------------------------------------------------------------------------------------
 |
 |	Project:    	VOIP sample
 |
 |	Filename:   	voip_stream_server.c
 |
 |	Copyright:  	TelcoBridges 2002-2004, All Rights Reserved
 |
 |	Description:	This file contains the code that handles communication with the stream server
 |
 |	Notes:      	Tabs = 4
 |
 *-------------------------------------------------------------------------------------------------------------------------------
 |
 |	Revision:   	$Revision: 1.18 $
 |
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Includes
 *------------------------------------------------------------------------------------------------------------------------------*/

#include "voip_includes.h"


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Forward declarations
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Defines
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Types
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Versioning
 *------------------------------------------------------------------------------------------------------------------------------*/

#ifdef WIN32
	/*@unused@*/ static char g_szFileVersion [] = "$Revision: 1.18 $";
#endif


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Global variables
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Macros
 *------------------------------------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Function Prototypes
 *------------------------------------------------------------------------------------------------------------------------------*/

static TBX_RESULT	VoipStreamServerReceiveThread();
static TBX_RESULT	VoipStreamServerStartPlayInternal( PVOIP_STREAM_SERVER_PROMPT_CONTEXT );
static TBX_RESULT	VoipStreamServerStopPlayInternal( PVOIP_STREAM_SERVER_PROMPT_CONTEXT	);
static TBX_RESULT	VoipStreamServerPromptClearInternal( PVOIP_STREAM_SERVER_PROMPT_CONTEXT );
static TBX_HASH_KEY	VoipStreamServerPromptGetKey( PTBX_VOID, PTBX_VOID );


/*--------------------------------------------------------------------------------------------------------------------------------
 |  Implementation
 *------------------------------------------------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------------------------------------------------
 |
 |  VoipStreamServerOpen		:	This function initializes the stream server library.
 |
 |  io_pszStreamServerIp0		:	First IP address of the stream server to use with this application
 |  io_pszStreamServerIp1		:	Second IP address of the stream server to use with this application
 |
 |  Note						:	~
 |
 |  Return						:	TBX_RESULT_OK if the function succeeded
 |									Other error code if the function could not complete properly.
 |
 *------------------------------------------------------------------------------------------------------------------------------*/
TBX_RESULT
VoipStreamServerOpen(
	IN		PTBX_CHAR	io_pszStreamServerIp0,
	IN		PTBX_CHAR	io_pszStreamServerIp1 )
{
	TBX_RESULT							result;
	PVOIP_CLI_CONTEXT					pCliContext;
	TBX_STREAM_SERVER_LIB_INIT_PARAMS	StreamServerLibParams;
	TBX_STREAM_SERVER_HANDLE			hStreamServer;
	STREAMSERVER_MSG					StreamServerStatus;
	TBX_UINT32							un32NbPrompts = 0;
	PVOIP_STREAM_SERVER_CONTEXT			pStreamServerContext;

	/*---------------------------------------------------------------------------------------------------------------------------
	 |  Code section
	 *--------------------------------------------------------------------------------------------------------------------------*/
	CODE
	{
		/* Initialize local variables */
		pCliContext = &g_pContext->CliContext;
		pStreamServerContext = &g_pContext->StreamServerContext;

		/* Create stream server resources semaphore */
		TBX_SEM_CREATE( &pStreamServerContext->StreamServerSem, 1, 1 );
		TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );

		/* Initialize pool of prompt contexts */
		pStreamServerContext->hPoolOfPrompts = TBXPoolOfBuffersCreate
		(
			VOIP_MAX_PROMPTS,
			sizeof( VOIP_STREAM_SERVER_PROMPT_CONTEXT ),
			VoipStreamServerPromptGetKey,
			NULL,
			TBX_FALSE
		);
		if( pStreamServerContext->hPoolOfPrompts == TBX_HANDLE_INVALID )
		{
			TBX_EXIT_ERROR( TBX_RESULT_OUT_OF_MEMORY, 0, "Unable to allocate pool of stream server promtps" );
		}

		/* Open the stream server library */
		StreamServerLibParams.un32StructVersion	= 1;
		StreamServerLibParams.un32UniqueId		= 0;
		StreamServerLibParams.hLib				= g_pContext->hTbxLib;
		result = StreamServerLibOpen(
			&StreamServerLibParams,
			&pStreamServerContext->hStreamServerLib);
		if( TBX_RESULT_FAILURE( result ) )
		{
			TBX_EXIT_ERROR(result, 0, "Unable to open stream server library");
		}

		/* Allow some time to detect stream servers */
		TBX_SLEEP_MS( VOIP_STREAM_SERVER_DISCOVERY_TIMEOUT );

		/*
		 *	 Search for the stream server specified in the config file
		 */
		TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_1, NULL, "Searching for active stream servers...\n" );
		memset( &StreamServerStatus.ReqGetStatus, 0, sizeof(StreamServerStatus.ReqGetStatus) );
		StreamServerStatus.Header.MessageType = STREAMSERVER_MSG_ID_REQ_GET_STATUS;
		StreamServerLibCommandSend(
			pStreamServerContext->hStreamServerLib,
			&StreamServerStatus,
			TBX_STREAM_SERVER_BROADCAST);

		while( result == TBX_RESULT_OK )
		{
			result = StreamServerLibRead(
				pStreamServerContext->hStreamServerLib,
				&StreamServerStatus,
				VOIP_STREAM_SERVER_DISCOVERY_TIMEOUT,
				&hStreamServer,
				NULL);
			if( result != TBX_RESULT_OK )
			{
				break;
			}

			if( StreamServerStatus.Header.MessageType == STREAMSERVER_MSG_ID_RSP_GET_STATUS )
			{
				if( StreamServerStatus.RspGetStatus.un32ServerVersion == STREAMSERVER_CURRENT_VERSION )
				{
					TBX_UINT32	un32Index;
					TBX_BOOL	fIsSearchedStreamServer = TBX_FALSE;
					TBX_UINT32	un32SearchedIp0			= TBX_INET_ADDR( io_pszStreamServerIp0 );
					TBX_UINT32	un32SearchedIp1			= TBX_INET_ADDR( io_pszStreamServerIp1 );

					/* Look if one of the IP addresses of the stream server searched is one of the 2 IP addresses
					   that this application wants to use... */
					for( un32Index = 0; un32Index < StreamServerStatus.RspGetStatus.un32NbServerRecordIPs; un32Index++ )
					{
						if( un32SearchedIp0 == StreamServerStatus.RspGetStatus.aun32ServerRecordIPs[ un32Index ] )
						{
							fIsSearchedStreamServer = TBX_TRUE;
							break;
						}
						else if( un32SearchedIp1 == StreamServerStatus.RspGetStatus.aun32ServerRecordIPs[ un32Index ] )
						{
							fIsSearchedStreamServer = TBX_TRUE;
							break;
						}
					}

					/* Maybe the server was specified by it's "control" IP addresses? */
					if( strcmp( io_pszStreamServerIp0, StreamServerStatus.RspGetStatus.szServerControlIp0 ) == 0 )
						fIsSearchedStreamServer = TBX_TRUE;
					else if( strcmp( io_pszStreamServerIp0, StreamServerStatus.RspGetStatus.szServerControlIp1 ) == 0 )
						fIsSearchedStreamServer = TBX_TRUE;
					else if( strcmp( io_pszStreamServerIp1, StreamServerStatus.RspGetStatus.szServerControlIp0 ) == 0 )
						fIsSearchedStreamServer = TBX_TRUE;
					else if( strcmp( io_pszStreamServerIp1, StreamServerStatus.RspGetStatus.szServerControlIp1 ) == 0 )
						fIsSearchedStreamServer = TBX_TRUE;

					if( fIsSearchedStreamServer )
					{
						TBX_UINT32	un32Index;

						/* Make sure IP 0 and 1 are always stored in the same order */
						strcpy( pStreamServerContext->szStreamServerIp0, StreamServerStatus.RspGetStatus.szServerControlIp0 );
						strcpy( pStreamServerContext->szStreamServerIp1, StreamServerStatus.RspGetStatus.szServerControlIp1 );

						/* Display the information on this StreamServer */
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "Found StreamServer:\n" );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Control IP Address 0            :  %s\n", StreamServerStatus.RspGetStatus.szServerControlIp0 );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Control IP Address 1            :  %s\n", StreamServerStatus.RspGetStatus.szServerControlIp1 );
						for( un32Index = 0; un32Index < StreamServerStatus.RspGetStatus.un32NbServerRecordIPs; un32Index++ )
						{
							TBX_CHAR	szThisInterfaceIP[64];
							TBX_INET_NTOA( StreamServerStatus.RspGetStatus.aun32ServerRecordIPs[ un32Index ], szThisInterfaceIP );

							TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Record IP Address %d             :  %s\n", (int)un32Index, szThisInterfaceIP );
						}
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Number of files being loaded    :  %d\n", StreamServerStatus.RspGetStatus.un32NbPendingIO );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Number of files being played    :  %d\n", StreamServerStatus.RspGetStatus.un32NbPlaybacks );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Number of files being recorded  :  %d\n", StreamServerStatus.RspGetStatus.un32NbRecordsPending + StreamServerStatus.RspGetStatus.un32NbRecords );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Total Number of reads           :  %d\n", StreamServerStatus.RspGetStatus.un32NbReads );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Total Number of writes          :  %d\n", StreamServerStatus.RspGetStatus.un32NbWrites );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Maximum number of chunks        :  %d\n", StreamServerStatus.RspGetStatus.un32MaxChunks );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Current number of chunks        :  %d\n", StreamServerStatus.RspGetStatus.un32NbChunks );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Current number of audio files   :  %d\n", StreamServerStatus.RspGetStatus.un32NbAudioFiles );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "    Current number of audio prompts :  %d\n", StreamServerStatus.RspGetStatus.un32NbPrompts );
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "---------------------------------------------------\n" );

						un32NbPrompts = StreamServerStatus.RspGetStatus.un32NbPrompts;

						pStreamServerContext->hStreamServer = hStreamServer;
						break;
					}
					else
					{
						TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "Ignoring stream server at IPs %s / %s\n", StreamServerStatus.RspGetStatus.szServerControlIp0, StreamServerStatus.RspGetStatus.szServerControlIp1 );
					}
				}
				else
				{
					TBX_CHAR	szIpAddress0[ 64 ];
					TBX_CHAR	szIpAddress1[ 64 ];
					
					StreamServerLibGetServerIp(
						pStreamServerContext->hStreamServerLib,
						hStreamServer,
						szIpAddress0,
						szIpAddress1,
						NULL,
						NULL);

					TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "**** StreamServer %s / %s, incompatible version. Will be ignored!\n",szIpAddress0, szIpAddress1 );
					TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ALWAYS, NULL, "---------------------------------------------------\n" );
				}
			}
		}

		if( pStreamServerContext->hStreamServer == (TBX_STREAM_SERVER_LIB_HANDLE)TBX_HANDLE_INVALID )
		{
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "***********************************\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "*                                 *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "* WARNING: Found no stream server *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "*                                 *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "***********************************\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "\n" );
			TBX_EXIT_ERROR(TBX_RESULT_NOT_FOUND, 0, "Found no stream server");
		}
		else if( un32NbPrompts == 0)
		{
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "***********************************************************************\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "*                                                                     *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "* WARNING: Stream server has no audio prompt. Can't use it for tests. *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "*                                                                     *\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "***********************************************************************\n" );
			TbxCliToolsLogPrint( pCliContext->hCliTools, TRACE_LEVEL_ERROR, NULL, "\n" );
			TBX_EXIT_ERROR(TBX_RESULT_INVALID_CONFIG, 0, "Found no stream server");
		}

		/* Mark the stream server as enable */
		pStreamServerContext->fEnable = TBX_TRUE;

		/* Mark the stream server as unavailable to force resync at startup */
		pStreamServerContext->fServerAvailable = TBX_FALSE;

		/* End of the code (skip to cleanup) */
		TBX_EXIT_SUCCESS (TBX_RESULT_OK);
	}

	/*---------------------------------------------------------------------------------------------------------------------------
	 |  Error handling section
	 *--------------------------------------------------------------------------------------------------------------------------*/
	ERROR_HANDLING
	{
		/* Print the error to the user */
		TbxCliToolsLogPrint(
			pCliContext->hCliTools,
			TRACE_LEVEL_ERROR,
			NULL,
			"VoipStreamServerOpen: %s (Result 0x%08X, %s, line %d\n",
			TBX_ERROR_DESCRIPTION,
			TBX_ERROR_RESULT,
			__FILE__,
			TBX_ERROR_LINE);
	}

	/*---------------------------------------------------------------------------------------------------------------------------
	 |  Cleanup section
	 *--------------------------------------------------------------------------------------------------------------------------*/
	CLEANUP
	{
		TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
	}

	RETURN;
}

/*-------------------------------------------------------------------------------------------------------------------------------
 |
 |  VoipStreamServerStart	:	This function launches the stream server receive thread
 |
 |  Note					:	~
 |
 |  Return					:	TBX_RESULT_OK if the function succeeded
 |								Other error code if the function could not complete properly.
 |
 *------------------------------------------------------------------------------------------------------------------------------*/
TBX_RESULT
VoipStreamServerStart()
{
	TBX_RESULT					result;
	PVOIP_CLI_CONTEXT			pCliContext;
	PVOIP_STREAM_SERVER_CONTEXT	pStreamServerContext;

	/*---------------------------------------------------------------------------------------------------------------------------
	 |  Code section
	 *--------------------------------------------------------------------------------------------------------------------------*/
	CODE
	{
		/* Initialize local variables */
		pCliContext = &g_pContext->CliContext;
		pStreamServerContext = &g_pContext->StreamServerContext;

		TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );

		/* Launch the receive thread */
		pStreamServerContext->fRecvThreadRunning	= TBX_FALSE;
		pStreamServerContext->fRecvThreadDone		= TBX_FALSE;
		result = TBX_THREAD_CREATE(
			&pStreamServerContext->hRecvThread,
			VoipStreamServerReceiveThread,
			NULL);
		if( TBX_RESULT_FAILURE( result ) )
		{
			TBX_EXIT_ERROR(result, 0, "Unable launch stream server receive thread");
		}

		/* Wait until the thread has started */
		while( !pStreamServerContext->fRecvThreadRunning )
		{
			TBX_SEM_GIV( pStreamServerContext->StreamServerSem );
			TBX_SLEEP_MS( 10 );
			TBX_SEM_GET( pStreamServerContext->StreamServerSem, TBX_SEM_WAIT_FOREVER );
		}

		/* End of the code (skip to cleanup) */
		TBX_EXIT_SUCCESS (TBX_RESULT_OK);
	}

	/*---------------------------------------------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -