📄 voip_stream_server.c
字号:
/*--------------------------------------------------------------------------------------------------------------------------------
|
| 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 + -