receivecall.cpp
来自「基于sipfoundy 公司开发的sipx协议API」· C++ 代码 · 共 536 行
CPP
536 行
//// Copyright (C) 2004, 2005 Pingtel Corp.// //// $$//////////////////////////////////////////////////////////////////////////////#include "os/OsDefs.h"#include <assert.h>#if defined(_WIN32)# include <windows.h># define SLEEP(milliseconds) Sleep(milliseconds)#else# include <unistd.h># define SLEEP(milliseconds) usleep((milliseconds)*1000)#endif#include "os/OsDefs.h"#include "tapi/sipXtapi.h"#include "tapi/sipXtapiEvents.h"#define SAMPLES_PER_FRAME 80 // Number of samples per frame time#define LOOPBACK_LENGTH 200 // Frames for loopback delay (10ms per frame)static short* g_loopback_samples[LOOPBACK_LENGTH] ; // loopback bufferstatic short g_loopback_head = 0 ; // index into loopbackstatic char* g_szPlayTones = NULL ; // tones to play on answerstatic char* g_szFile = NULL ; // file to play on answer// Print usage messagevoid usage(const char* szExecutable){ char szBuffer[64] = ""; sipxConfigGetVersion(szBuffer, 64); printf("\nUsage:\n"); printf(" %s <options>\n", szExecutable) ; printf(" using %s\n", szBuffer) ; printf("\n") ; printf("Options:\n") ; printf(" -d durationInSeconds (default=30 seconds)\n") ; printf(" -t playT tones (default = none)\n") ; printf(" -f play file (default = none)\n") ; printf(" -p SIP port (default = 5060)\n") ; printf(" -r RTP port start (default = 9000)\n") ; printf(" -l loopback audio (2 second delay)\n") ; printf(" -i line identity (e.g. sip:122@pingtel.com)\n") ; printf(" -u username (for authentication)\n") ; printf(" -a password (for authentication)\n") ; printf(" -m realm (for authentication)\n") ; printf(" -x proxy (outbound proxy)\n"); printf(" -S stun server\n") ; printf(" -v show sipXtapi version\n"); printf("\n") ;}// Parse argumentsbool parseArgs(int argc, char *argv[], int* pDuration, int* pSipPort, int* pRtpPort, char** pszPlayTones, char** pszFile, bool* bLoopback, char** pszIdentity, char** pszUsername, char** pszPassword, char** pszRealm, char** pszStunServer, char** pszProxy){ bool bRC = true ; char szBuffer[64]; assert(pDuration && pszPlayTones) ; *pDuration = 30 ; *pSipPort = 5060 ; *pRtpPort = 9000 ; *pszPlayTones = NULL ; *pszFile = NULL ; *bLoopback = false ; *pszIdentity = NULL ; *pszUsername = NULL ; *pszPassword = NULL ; *pszRealm = NULL ; *pszStunServer = NULL ; *pszProxy = NULL; for (int i=1; i<argc; i++) { if (strcmp(argv[i], "-d") == 0) { if ((i+1) < argc) { *pDuration = atoi(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-t") == 0) { if ((i+1) < argc) { *pszPlayTones = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-f") == 0) { if ((i+1) < argc) { *pszFile = strdup(argv[++i]) ; } else { break ; // Error } } else if (strcmp(argv[i], "-p") == 0) { if ((i+1) < argc) { *pSipPort = atoi(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-r") == 0) { if ((i+1) < argc) { *pRtpPort = atoi(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-l") == 0) { *bLoopback = true ; } else if (strcmp(argv[i], "-i") == 0) { if ((i+1) < argc) { *pszIdentity = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-u") == 0) { if ((i+1) < argc) { *pszUsername = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-a") == 0) { if ((i+1) < argc) { *pszPassword = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-m") == 0) { if ((i+1) < argc) { *pszRealm = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-S") == 0) { if ((i+1) < argc) { *pszStunServer = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-x") == 0) { if ((i+1) < argc) { *pszProxy = strdup(argv[++i]) ; } else { bRC = false ; break ; // Error } } else if (strcmp(argv[i], "-v") == 0) { sipxConfigGetVersion(szBuffer, 64); printf("%s\n", szBuffer); exit(0); } else { bRC = false ; break ; // Error } } return bRC ;}// Play a file (8000 samples/sec, 16 bit unsigned, mono PCM)bool playFile(char* szFile, SIPX_CALL hCall){ bool bRC = false ; sipxCallPlayFile(hCall, g_szFile, true, true) ; return true ;}// Play a series of tonesbool playTones(char* szPlayTones, SIPX_CALL hCall){ bool bRC = true ; while (*szPlayTones) { int toneId = *szPlayTones++ ; if ( (toneId >= '0' && toneId <= '9') || (toneId == '#') || (toneId == '*') || toneId == ',' || toneId == '!') { if (toneId == ',') { printf("<-> Playtone: Sleeping for 2 seconds\n") ; SLEEP(2000) ; } else { printf("<-> Playtone: %c\n", toneId) ; SLEEP(250) ; sipxCallStartTone(hCall, (TONE_ID) toneId, true, false) ; SLEEP(500) ; sipxCallStopTone(hCall) ; } } else { bRC = false ; break ; } } return bRC ;}void SpkrAudioHook(const int nSamples, short* pSamples){ memcpy(g_loopback_samples[g_loopback_head], pSamples, sizeof(short) * SAMPLES_PER_FRAME) ; g_loopback_head = ((g_loopback_head + 1) % LOOPBACK_LENGTH) ; memset(pSamples, 0, sizeof(short) * SAMPLES_PER_FRAME) ;}void MicAudioHook(const int nSamples, short* pSamples){ short index = ((g_loopback_head + 1) % LOOPBACK_LENGTH) ; memcpy(pSamples, g_loopback_samples[index], sizeof(short) * SAMPLES_PER_FRAME) ;}void clearLoopback(){ for (int i=0; i<LOOPBACK_LENGTH; i++) { if (g_loopback_samples[i]) { memset(g_loopback_samples[i], 0, sizeof(short) * SAMPLES_PER_FRAME) ; } } g_loopback_head = 0 ;}void initLoopback(){ for (int i=0; i<LOOPBACK_LENGTH; i++) { g_loopback_samples[i] = new short[SAMPLES_PER_FRAME] ; } clearLoopback() ; sipxConfigSetSpkrAudioHook(SpkrAudioHook) ; sipxConfigSetMicAudioHook(MicAudioHook) ;}bool EventCallBack(SIPX_EVENT_CATEGORY category, void* pInfo, void* pUserData){ assert (pInfo != NULL); // Dump event char cBuf[1024] ; printf("%s\n", sipxEventToString(category, pInfo, cBuf, sizeof(cBuf))) ; if (category == EVENT_CATEGORY_CALLSTATE) { SIPX_CALLSTATE_INFO* pCallInfo = static_cast<SIPX_CALLSTATE_INFO*>(pInfo); printf(" hCall=%d, hAssociatedCall=%d\n", pCallInfo->hCall, pCallInfo->hAssociatedCall) ; switch (pCallInfo->event) { case CALLSTATE_OFFERING: sipxCallAccept(pCallInfo->hCall) ; break ; case CALLSTATE_ALERTING: clearLoopback() ; sipxCallAnswer(pCallInfo->hCall) ; break ; case CALLSTATE_CONNECTED: SLEEP(1000) ; // BAD: Do not block the callback thread // Play file if provided if (g_szFile) { if (!playFile(g_szFile, pCallInfo->hCall)) { printf("Failed to play file: %s\n", g_szFile) ; } } // Play tones if provided if (g_szPlayTones) { if (!playTones(g_szPlayTones, pCallInfo->hCall)) { printf("Failed to play tones: %s\n", g_szPlayTones) ; } } break ; case CALLSTATE_DISCONNECTED: sipxCallDestroy(pCallInfo->hCall) ; break ; case CALLSTATE_AUDIO_EVENT: if (pCallInfo->cause == CALLSTATE_AUDIO_START) { printf("* Negotiated codec: %s, payload type %d\n", pCallInfo->codecs.audioCodec.cName, pCallInfo->codecs.audioCodec.iPayloadType); } break; case CALLSTATE_DESTROYED: break ; } } return true;}SIPX_LINE lineInit(SIPX_INST hInst, char* szIdentity, char* szUsername, char* szPassword, char* szRealm){ SIPX_LINE hLine = NULL ; if (szIdentity && strlen(szIdentity)) { sipxLineAdd(hInst, szIdentity, &hLine) ; if ( szUsername && strlen(szUsername) && szPassword && strlen(szPassword) && szRealm && strlen(szRealm)) { sipxLineAddCredential(hLine, szUsername, szPassword, szRealm) ; sipxLineRegister(hLine, true); } } else { sipxLineAdd(hInst, "sip:receivecall@localhost", &hLine) ; } return hLine ;}void dumpLocalContacts(SIPX_INST hInst){ SIPX_CONTACT_ADDRESS contacts[10] ; size_t nContacts; SIPX_RESULT status = sipxConfigGetLocalContacts(hInst, contacts, 10, nContacts) ; if (status == SIPX_RESULT_SUCCESS) { for (size_t i = 0; i<nContacts; i++) { const char* szType = "UNKNOWN" ; switch (contacts[i].eContactType) { case CONTACT_LOCAL: szType = "LOCAL" ; break ; case CONTACT_NAT_MAPPED: szType = "NAT_MAPPED" ; break ; case CONTACT_RELAY: szType = "RELAY" ; break ; case CONTACT_CONFIG: szType = "CONFIG" ; break ; } printf("<-> Type %s, Interface: %s, Ip %s, Port %d\n", szType, contacts[i].cInterface, contacts[i].cIpAddress, contacts[i].iPort) ; } } else { printf("<-> Unable to query local contact addresses\n") ; }}int main(int argc, char* argv[]){ bool bError = true ; int iDuration, iSipPort, iRtpPort ; bool bLoopback ; char* szIdentity ; char* szUsername ; char* szPassword ; char* szRealm ; char* szStunServer ; char* szProxy ; SIPX_INST hInst ; SIPX_LINE hLine ; // Parse Arguments if (parseArgs(argc, argv, &iDuration, &iSipPort, &iRtpPort, &g_szPlayTones, &g_szFile, &bLoopback, &szIdentity, &szUsername, &szPassword, &szRealm, &szStunServer, &szProxy) && (iDuration > 0) && (portIsValid(iSipPort)) && (portIsValid(iRtpPort))) { if (bLoopback) { initLoopback() ; } // initialize sipx TAPI-like API sipxConfigSetLogLevel(LOG_LEVEL_DEBUG) ; sipxConfigSetLogFile("ReceiveCall.log"); if (sipxInitialize(&hInst, iSipPort, iSipPort, 5061, iRtpPort, 16, szIdentity) == SIPX_RESULT_SUCCESS) { if (szProxy) { sipxConfigSetOutboundProxy(hInst, szProxy); } sipxConfigEnableRport(hInst, true) ; if (szStunServer) { sipxConfigEnableStun(hInst, szStunServer, 28) ; } sipxEventListenerAdd(hInst, EventCallBack, NULL) ; hLine = lineInit(hInst, szIdentity, szUsername, szPassword, szRealm) ; dumpLocalContacts(hInst) ; while (true) { SLEEP(1000) ; } } else { printf("unable to initialize sipXtapi layer\n") ; } } else { usage(argv[0]) ; } return (int) bError ;}#if !defined(_WIN32)// Dummy definition of JNI_LightButton() to prevent the reference in// sipXcallLib from producing an error.void JNI_LightButton(long){}#endif /* !defined(_WIN32) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?