CCL MGCP Protocol Stack Shang-Chih Tsai
Features of the Stack n The Stack currently supports both Win32 and Solaris platform. n The Stack provides a C language API. n The Stack implemented the "At-Most-Once" functionality (section of RFC 2705). Also, it implemented a retransmission mechanism (section of RFC2705 ) while sending messages with UDP.
MGCP1.0 APIs n mgcMsg : APIs for messages n mgcAck : APIs for acknowledgements n mgcLoop : APIs for waiting incoming messages and sending outgoing messages(or acknowledgments) n mgcSock n mgcHash n mgcStr
Programming Model n Incoming messages mgcLoop Another MGCP process Application Message CCL’s MGCP protocol stack Ack Application process and generate acknowledgement MGCP calls application defined MSG callback function
Initialize mgcLoop int main(int argc, char**argv) { struct mgcExtEvents events[2]; struct timeval timeOut = {60,0}; mgcInit(); events[0].fd = 0; events[0].cb = NULL; /* no user-defined events */ mgcLoopSetDelay(50000); /* initial resend delay = 50 msec */ mgcLoop(2427, doMsg, doAck, events, &timeOut, doTimeout); }
Message Callback Function int doMsg(mgcMsg msg) { /* handle incoming command messages */ switch( mgcMsgGetType(msg) ) { case mgcCreatConn: handleCreatConn(); break; default: break; } mgcMsgFree(msg); /* responsible (could pass on) */ return 0; }
Programming Model n Outgoing messages mgcLoop Application CCL’s MGCP protocol stack Another MGCP process Message Ack External Event Application process and generate MGCP message MGCP calls application defined ACK callback function
mgcSockAddr dst_addr; mgcMsg mgcComm; /* set destination address */ dst_addr = mgcSockAddrNewDom(“gw.ccl.itri.org.tw”, 2427); /* set the MGCP command verb, endpoint and TID */ mgcComm = mgcMsgNew(mgcCreatConn); mgcMsgSetEPt(mgcComm, mgcMsgSetTId(mgcComm,”1007”); / * set command parameters */ mgcMsgAddParm(mgcComm, "C", “1”); /* call ID */ mgcMsgAddParm(mgcComm, "X", ”5”); /* request ID */ mgcMsgAddParm(mgcComm, "L", “P:3-4,A:G.711,B:32-64,E:ON”); mgcMsgAddParm(mgcComm, "M", “SENDRECEV”); mgcMsgAddParm(mgcComm, "S", “RT”); mgcMsgSend(mgcComm, dst_addr); Send Message CRCX 1007 MGCP 1.0 X:5 L:P:3-4,A:G.711,B:32-64,E:ON M:SENDRECV S:RG C:1
Send Acknowledge /* callback function that informing us an incoming MGCP command */ int doMsg(mgcMsg msg) { mgcAck ack = NULL; /* process the command here */ /* send the response to the command */ ack = mgcAckNew(mgcAckOK); mgcAckSetTId(ack, mgcMsgGetTId(msg)); mgcAckAddParm(ack, "I", “ABCDEFGHIJ11” ); mgcAckSend(ack, mgcMsgGetAddr(msg)); … } OK I: ABCDEFGHIJ11
mgcStr struct mgcStrObj { char* text; long len, alloced; }; MGCP_API mgcStr mgcStrNew(void); MGCP_API int mgcStrLen(mgcStr); MGCP_API void mgcStrClr(mgcStr); MGCP_API void mgcStrFree(mgcStr); MGCP_API void mgcStrCat(mgcStr, char*); MGCP_API void mgcStrCatN(mgcStr, char*, int); MGCP_API char*mgcStrAsCStr(mgcStr); mgcStr mgcStrNew() { mgcStr _this; _this = malloc(sizeof *_this); /* ErrorCheck */ _this->len = 0; _this->alloced = MINALLOC; // MINALLOC = 200 _this->text = malloc(MINALLOC); mgcStrClr(_this); return _this; }
mgcHash typedef struct EntryObj *Entry; struct EntryObj { char* key; char* val; Entry next; }; struct mgcHashObj { Entry* table; int CELLS, elements; int keysUpper, strings; Entry iterNext; /* next entry in current bucket */ int bucketNext; /* next bucket to search */ }; table bucketNext /* * CELLs = number of entries in table (may grow) * keysUpper: bool should keys be mapped to upper case * strings: mgcHashType should val be copied (cstrings and ints) * by mgcHashAdd * keys are always strings and always copied */ iterNext Entrys
mgcHash API n MGCP_API mgcHash mgcHashNew(int initSize, int keysUpper, mgcHashType strings); n MGCP_API void mgcHashFree(mgcHash, void (*freeVal)(void*)); n /* add pair key/val to hash, return old value */ MGCP_API void*mgcHashAdd(mgcHash, char* key, void* val); n MGCP_API void*mgcHashDel(mgcHash, char* key); n /* return val for key in hash. NULL if not found. */ MGCP_API void*mgcHashItem(mgcHash, char* key); n MGCP_API voidmgcStartKeys(mgcHash); n MGCP_API char*mgcNextKeys(mgcHash); n MGCP_API int mgcHashSize(mgcHash);
mgcSock struct mgcSockAddrObj { char*domain_; intport_; struct sockaddr_in addr_; mgcSockAddr next_; }; MGCP_API mgcSockAddrmgcSockAddrNewDom(char* domain, int port); MGCP_API mgcSockAddrmgcSockAddrDup(mgcSockAddr); MGCP_API intmgcSockAddrBind(mgcSockAddr, int fd); MGCP_API intmgcSockAddrSendTo(mgcSockAddr, int fd, mgcStr); MGCP_API mgcSockAddrmgcSockAddrRecvFrom(int fd, mgcStr); MGCP_API voidmgcSockAddrFree(mgcSockAddr); MGCP_API char*mgcSockAddrGetDomain(mgcSockAddr); MGCP_API int mgcSockNew(void); freeList
mgcMsg struct mgcMsgObj { mgcMsgTypetype_; mgcStrasStr_; mgcHashparms_; char*tId_; char*ePt_; mgcStrsesParms_; mgcSockAddrsrcAddr_; }; CRCX 1007 MGCP 1.0 X:5 L:P:3-4,A:G.711,B:32-64,E:ON M:SENDRECV S:RG C:1
mgcAck struct mgcAckObj { mgcAckTypetype_; mgcStrasStr_; char*tId_; mgcHashparms_; mgcStrsesParms_; mgcSockAddrsrcAddr_; }; OK I: ABCDEFGHIJ11
mgcLoop n Trace code mgcLoop.c n ackNrecv: outstanding sent messages not yet acknowledged :maps message Tid to the count of messages sent n msgActv: stores active messages received yet to be acknowledged: maps message Tid to a dummy n msgComp1: moves messages from the active list to the completed list maps message Tid to the duplicate acknowledgement to be sent n msgComp2: mirror image of msgComp1 delayed by 30 seconds
mgcAlarm Start Time: ms new HEAP HEAP End Time: ms Start Time: ms Set timer = 5