Extend your H.323-based applications by using NON-STANDARD messages

Extend your H.323-based applications by using NON-STANDARD messages

Abstract

Comparing to SIP protocol or RTSP protocol, H.323 protocol is a strict one, which has its own working flow control, and every bits in it's protocol buf has its meaning. However H.323 provided a NON-STANDARD message machenism to allow users to extend your own bussiness rules. This document is discribing a example extended H.323 bussiness by using NON-STANDARD message of H.323. And also could be a guide of how to start your own NON-STANDARD message for your H.323-based applications.

Keywords: H.323, RAS, NON-STANDARD message

Key problems to be solved

H323 is a standard defined over ten years ago, the standard commands are no longer enough for some specified applications. In cases, we need to add some customized informations or command protocols for our featured implementations of our H.323-based products.

Solutions for the key problems

There is a machenism of NON-STANDARD message in H.323, which allow you to extend your own protocol/feature for your products.

And there are two ways to add your customized message to H.323 protocol:

  • Using an independent H.245 NSM command
  • Padding NSM data after a standard H.323 protocol(RAS, H.225, or H.245 message)

Both of them could be very helpful, if you want add some customized functions or integrate some value-added bussiness into your VoIP or H.323-base applications.
And its a really popular way to use NSM messages in H.323 protocol, I'm here providing you two examples both of them are claimed as patents, and both of them are Invention level of patents.

  • China Patent CN101119251B

Method for implementing video added value service in H.323 standard based network, invented by China Telecom.
You can download it here: http://docs.google.com/a/rg4.net/viewer?url=patentimages.storage.googleapis.com/pdfs/2b97ddd77940eba9f4f4/CN101119251B.pdf

  • US Patent US20060245419

Back-to back H.323 proxy gatekeeper, invented by Siddhartha Nag, Bo Shu, Rahul Gulati, Ilana Polyak
You can download it here: http://docs.google.com/a/rg4.net/viewer?url=patentimages.storage.googleapis.com/pdfs/US20060245419.pdf

Considering NSM's all-yours data format, by using it, you can do anything you want, integrate any bussiness you need to your H.323 applications. Don't you exciting?

Two ways to use NSM

Now I'll show you the codes of the two ways to send NON-STANDARD messages by using RV H.323 stack.

1. Independent H.245 NSM command

a. Packing and sending an independent H.245 NSM command

[cpp]
s32 NonStdMsgH245SendWithCustom(HCALL hsCall, const void* pBuf, IN u16 nBufLen)
{
if( nBufLen>( MAX_CUSTOM_DATALEN) )
{
OspPrintf(TRUE, FALSE,"[adapter][EXP] NonStdMsgH245SendWithCustom — err:pBuf(%d) len(%d)\n",(s32)pBuf, nBufLen);
return ADAPTER_ERR;
}
HPVT hVal = cmGetValTree(g_tInfo.m_hApp);
VALID_RETURN_VALUE("NonStdMsgH245SendWithCustom",hVal,ADAPTER_ERR);

HPST hSyn = cmGetSynTreeByRootName(g_tInfo.m_hApp,"h245");
VALID_RETURN_VALUE("NonStdMsgH245SendWithCustom",hSyn,ADAPTER_ERR);

s32 RootId = pvtAddRoot(hVal,hSyn,0,NULL);
VALID_RETURN_VALUE("NonStdMsgH245SendWithCustom",RootId,ADAPTER_ERR);

pvtBuildByPath(hVal,RootId,"command.nonStandard.nonStandardData.nonStandardIdentifier.h221NonStandard.t35CountryCode",86,NULL);
pvtBuildByPath(hVal,RootId,"command.nonStandard.nonStandardData.nonStandardIdentifier.h221NonStandard.t35Extension",1,NULL);
pvtBuildByPath(hVal,RootId,"command.nonStandard.nonStandardData.nonStandardIdentifier.h221NonStandard.manufacturerCode",2457,NULL);
pvtBuildByPath(hVal,RootId,"command.nonStandard.nonStandardData.data", nBufLen, (s8*)pBuf);

HPROTCONN hConn;
if((hConn = cmGetTpktChanHandle(hsCall,cmH245TpktChannel)) == NULL)
{
pvtDelete(hVal, RootId);
OspPrintf(TRUE, FALSE,"[adapter][IMT] SendH245Msg — get invalid conn\r\n");
return ADAPTER_ERR;
}

s32 nRet = cmProtocolSendMessage(hApp, hConn, RootId);
if( nRet < 0)
{
pvtDelete(hVal, RootId);
OspPrintf(TRUE, FALSE,"[adapter][EXP] SendH245Msg — send msg failed\r\n");
return ADAPTER_ERR;
}

PVTDELETE(hVal, RootId);

nRet = ADAPTER_OK;
return nRet;
}
[/cpp]

b. De-pack and parse out received independent NSM command

Code part 1: get the protocol type after received a H.245 message, if it is a NSM command, then call code part 2 to parse the NSM.
[cpp]
//Get the protocol type
cmProtocol emProtocol = cmProtocolGetProtocol(g_tInfo.m_hApp, message);
if(emProtocol != cmProtocolH245)
{
//Process H245 message only
return act_ok;
}

s32 nRet = -1;
HPVT hVal = cmGetValTree(g_tInfo.m_hApp);
VALID_RETURN_VALUE("cmEvCallRecvMessage",hVal, -1);

HPST hSyn = pvtGetSynTree(hVal, message);
VALID_RETURN_VALUE("cmEvCallRecvMessage",hSyn, -1);

INTPTR nChildFieldId;
s32 nChild = pvtChild(hVal, message);
nRet = pvtGet(hVal, nChild, &nChildFieldId, NULL, NULL, NULL);
VALID_RETURN_VALUE("cmEvCallRecvMessage–Get nChildFieldId",nRet, -1);

INTPTR nGrandChildFieldId;
s32 nGrandChild = pvtChild(hVal, nChild);
nRet = pvtGet(hVal, nGrandChild, &nGrandChildFieldId, NULL, NULL, NULL);
VALID_RETURN_VALUE("cmEvCallRecvMessage–Get nGrandChildFieldId",nRet, -1);

switch(nChildFieldId)
{
case __h245(request):
{
switch(nGrandChildFieldId)
{
case __h245(nonStandard):
OnH245ConfCustomMsg(hsCall,hSyn,hVal,nGrandChild);
break;
case __h245(conferenceRequest):
case __h245(terminalCapabilitySet):
case __h245(openLogicalChannel):
case __h245(genericRequest):
….
break;
default:

break;
}
}
break;
case __h245(response):
{
switch(nGrandChildFieldId)
{
case __h245(nonStandard):
OnH245ConfCustomMsg(hsCall,hSyn,hVal,nGrandChild);
break;
case __h245(conferenceResponse):
case __h245(openLogicalChannelAck):
case __h245(genericResponse):

break;
default:

break;
}
}
break;
case __h245(command):
{
switch(nGrandChildFieldId)
{
case __h245(nonStandard):
if (g_nIsHuaweiMcu && hsCall == g_tNonStdMsg.m_hsCall)
{
OnH245ConfNonStdMsg(hsCall, hSyn, hVal, nGrandChild);
}
else
{
OnH245ConfCustomMsg(hsCall,hSyn,hVal,nGrandChild);
}
break;
case __h245(conferenceCommand):
case __h245(communicationModeCommand):
case __h245(genericCommand):

break;
case __h245(miscellaneousCommand):
switch (typeId)
{
case __h245(encryptionUpdateRequest):
case __h245(encryptionUpdate):
case __h245(encryptionUpdateCommand):

break;
default: break;
}
default:

break;
}
}
break;
case __h245(indication):
{
switch(nGrandChildFieldId)
{
case __h245(nonStandard):
{
OnH245ConfCustomMsg(hsCall,hSyn,hVal,nGrandChild);
break;
}
case __h245(conferenceIndication):
case __h245(mcLocationIndication):
case __h245(flowControlIndication):
case __h245(functionNotUnderstood):
case __h245(genericIndication):
break;
default:

break;
}
}
break;
default:break;
}

[/cpp]

Code part 2: parse out the NSM message.
[cpp]
BOOL OnH245ConfCustomMsg(HCALL hsCall, HPST hSyn, HPVT hVal, s32 NodeId)
{
s32 nValue = 0;
BOOL bStr = FALSE;

s32 nDataId = pvtGetByPath(hVal,NodeId,"nonStandardData.data", NULL, &nValue,(unsigned int *)&bStr);
VALID_RETURN_VALUE("OnH245NonStardardMsg",nDataId,FALSE);

if (!bStr || nValue {
return FALSE;
}

s8 pBuf[MAX_CUSTOM_DATALEN];
nValue = min(nValue, MAX_CUSTOM_DATALEN);

if (pvtGetString(hVal, nDataId, nValue, pBuf) < 0) {

AdapterLog(LOG_EXP,"[adapter][EXP] OnConfCtrlNonStardardMsg — get value err\r\n");

return FALSE;

}

TKdvNonStandrdData *pData = (TKdvNonStandrdData *)pBuf;

if(!pData->IsKdvGUID())
{
AdapterLog(LOG_ALL,"[adapter][EXP] OnConfCtrlNonStardardMsg — not kdv data\n");
return FALSE;
}
s32 nLen = nValue – sizeof(TKDVBaseNonStandardData);

AdapterLog(LOG_DEBUG, "[adapter][DEBUG] Get CustomMsg(type:%d,len%d)!\n", pData->GetDataType(), nLen);

NotifyConfCtrlMsg(hsCall,(u16)pData->GetDataType(), &(pData->m_pbyData), nLen);

return TRUE;
}
[/cpp]

2. Padding NSM data after a standard H.323 protocol(RAS, H.225, or H.245 message)

a. Packing and sending a padding NSM data to the RRQ message(RAS)

[cpp]
RvChar achQuantumID[sizeof(((cmElem*)(autoras->hApp))->m_dwMyQuantumID)];
cmNonStandardParam cmRasKdvTsParam;

memset(achQuantumID, 0, sizeof(((cmElem*)(autoras->hApp))->m_dwMyQuantumID));
memcpy(achQuantumID, &((cmElem*)(autoras->hApp))->m_dwMyQuantumID, sizeof(((cmElem*)(autoras->hApp))->m_dwMyQuantumID));
memset(&cmRasKdvTsParam, 0, sizeof(cmRasKdvTsParam)); cmRasKdvTsParam.info.objectLength = 0;
cmRasKdvTsParam.info.t35CountryCode = 38; //KDC_COUNTRYCODE;
cmRasKdvTsParam.info.t35Extension = 0; //KDC_T35EXTENSION;
cmRasKdvTsParam.info.manufacturerCode = 8888; //KDC_MANUCODE;
cmRasKdvTsParam.data = achQuantumID;
cmRasKdvTsParam.length = sizeof(((cmElem*)(autoras->hApp))->m_dwMyQuantumID);
if ( cmRASSetParam( autoras->registrationTx, cmRASTrStageRequest, cmRASParamNonStandard, 0,
sizeof(cmRasKdvTsParam), (char *)&cmRasKdvTsParam) < 0 ) {

//Print the error message, but, we'll live with it

printf("autoRasSendLightweightRRQ: set cmRASParamNonStandard err\r\n");

}

[/cpp]

b. De-pack and parse out received padding NSM data

[cpp] cmNonStandardParam cmRasKdvTsParam;

u8 abydata[2048];

s32 len = 0;

memset( &cmRasKdvTsParam , 0 , sizeof(cmRasKdvTsParam) );

memset(abydata,0,sizeof(abydata));

cmRasKdvTsParam.data = (char*)abydata;

cmRasKdvTsParam.length = 2048;

if( cmRASGetParam( hsRas, cmRASTrStageRequest, cmRASParamNonStandard,0, &len, (char *)&cmRasKdvTsParam ) >= 0 )
{
memcpy( &ptRRQInfo->m_dwQuantumID, cmRasKdvTsParam.data, sizeof(ptRRQInfo->m_dwQuantumID) );
ptRRQInfo->m_dwQuantumID = ptRRQInfo->m_dwQuantumID;
}
[/cpp]

Summary

As you can see, its really simple codes. By using it, you can do whatever functions you want, add any features you need for your applications. Furthermore, inventions are not far from you, if you want, you can have your own inventions.

Author: Jacky Wei

I am a programmer, welcome to my blog: http://rg4.net.

Leave a Reply

Your email address will not be published. Required fields are marked *