Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

383 lines
11 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTPIO.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides Session Creation/Deletion Functionality.
  5. *
  6. *
  7. * This listing is supplied under the terms
  8. * of a license agreement with Intel Corporation and
  9. * many not be copied nor disclosed except in accordance
  10. * with the terms of that agreement.
  11. * Copyright (c) 1995 Intel Corporation.
  12. *--------------------------------------------------------------------------*/
  13. #include "rrcm.h"
  14. /*---------------------------------------------------------------------------
  15. / Global Variables
  16. /--------------------------------------------------------------------------*/
  17. /*---------------------------------------------------------------------------
  18. / External Variables
  19. /--------------------------------------------------------------------------*/
  20. extern PRTP_CONTEXT pRTPContext;
  21. #ifdef _DEBUG
  22. extern char debug_string[];
  23. #endif
  24. /*----------------------------------------------------------------------------
  25. * Function : CreateRTPSession
  26. * Description: Creates an RTP (and RTCP) session for a new stream.
  27. *
  28. * Input : RTPsocket : RTP socket descriptor
  29. * RTCPsd : RTCP socket descriptor
  30. * pRTCPTo : RTCP destination address
  31. * toRTCPLen : RTCP destination address length
  32. * pSdesInfo : -> to SDES information
  33. * dwStreamClock : Stream clocking frequency
  34. * ssrc : If set, user selected SSRC
  35. * pRRCMcallback : RRCM notification
  36. * dwCallbackInfo : User callback info
  37. * miscInfo : Miscelleanous information:
  38. * H.323Conf: 0x00000002
  39. * Encrypt SR/RR: 0x00000004
  40. * RTCPon: 0x00000008
  41. * dwRtpSessionBw : RTP session bandwidth used for RTCP BW
  42. * *pStatus : -> to status information
  43. *
  44. * Return: handle to created session if successful
  45. * Otherwise(0) *pStatus = Initialization Error (see RRCM.H)
  46. ---------------------------------------------------------------------------*/
  47. HANDLE WINAPI CreateRTPSession (SOCKET RTPsocket,
  48. SOCKET RTCPsocket,
  49. LPVOID pRTCPTo,
  50. DWORD toRTCPLen,
  51. PSDES_DATA pSdesInfo,
  52. DWORD dwStreamClock,
  53. PENCRYPT_INFO pEncryptInfo,
  54. DWORD ssrc,
  55. PRRCM_EVENT_CALLBACK pRRCMcallback,
  56. DWORD_PTR dwCallbackInfo,
  57. DWORD miscInfo,
  58. DWORD dwRtpSessionBw,
  59. DWORD *pStatus)
  60. {
  61. DWORD numCells = NUM_FREE_CONTEXT_CELLS;
  62. DWORD dwStatus;
  63. DWORD dwRTCPstatus;
  64. PRTP_SESSION pSession = NULL;
  65. PSSRC_ENTRY pSSRC;
  66. IN_OUT_STR ("RTP : Enter CreateRTPSession()\n");
  67. // set status code
  68. *pStatus = dwStatus = RRCM_NoError;
  69. // If RTP context doesn't exist, report error and return.
  70. if (pRTPContext == NULL)
  71. {
  72. RRCM_DBG_MSG ("RTP : ERROR - No RTP Instance",
  73. 0, __FILE__, __LINE__, DBG_CRITICAL);
  74. IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
  75. *pStatus = MAKE_RRCM_ERROR(RRCMError_RTPNoContext);
  76. return 0;
  77. }
  78. #if 0
  79. // look for an existing session - Sender/Receiver for the same session
  80. // will be on two different graph under ActiveMovie
  81. if (pSession = findSessionID (RTPsocket))
  82. {
  83. RRCM_DBG_MSG ("RTP : Session already created", 0,
  84. __FILE__, __LINE__, DBG_TRACE);
  85. IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
  86. // return the unique RTP session ID
  87. return ((HANDLE)pSession);
  88. }
  89. #endif
  90. // Allocate a new session pointer.
  91. pSession = (PRTP_SESSION)GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT,
  92. sizeof(RTP_SESSION));
  93. // Report error if could not allocate context
  94. if (pSession == NULL)
  95. {
  96. RRCM_DBG_MSG ("RTP : ERROR - Resource allocation failed", 0,
  97. __FILE__, __LINE__, DBG_CRITICAL);
  98. IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
  99. *pStatus = MAKE_RRCM_ERROR(RRCMError_RTPSessResources);
  100. return 0;
  101. }
  102. // Initialize the RTP session's critical section
  103. InitializeCriticalSection(&pSession->critSect);
  104. // All seems OK, initialize RTCP for this session
  105. pSession->pRTCPSession = CreateRTCPSession(RTPsocket,
  106. RTCPsocket,
  107. pRTCPTo,
  108. toRTCPLen,
  109. pSdesInfo,
  110. dwStreamClock,
  111. pEncryptInfo,
  112. ssrc,
  113. pRRCMcallback,
  114. dwCallbackInfo,
  115. miscInfo,
  116. dwRtpSessionBw,
  117. &dwRTCPstatus);
  118. if (pSession->pRTCPSession == NULL)
  119. {
  120. dwStatus = dwRTCPstatus;
  121. // Can't proceed, return session pointer
  122. if (pSession)
  123. {
  124. GlobalFree (pSession);
  125. pSession = NULL;
  126. }
  127. }
  128. else
  129. {
  130. #if 0
  131. // Associate the socket with the Session address
  132. dwStatus = createHashEntry (pSession, RTPsocket);
  133. #endif
  134. if (dwStatus == RRCM_NoError)
  135. {
  136. pSSRC =
  137. (PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
  138. if (pSSRC == NULL)
  139. {
  140. RRCM_DBG_MSG ("RTP : ERROR - No RTCP Xmt list", 0,
  141. __FILE__, __LINE__, DBG_CRITICAL);
  142. dwStatus = RRCMError_RTCPNoXmtList;
  143. }
  144. else
  145. {
  146. // Let's add this to our context
  147. addToHeadOfList(&(pRTPContext->pRTPSession),
  148. (PLINK_LIST)pSession,
  149. &pRTPContext->critSect);
  150. #ifdef _DEBUG
  151. wsprintf(debug_string, "RTP : Adding RTP Session. (Addr:0x%p)",
  152. pSession);
  153. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  154. #endif
  155. }
  156. }
  157. }
  158. // set status code
  159. if (dwStatus != RRCM_NoError)
  160. *pStatus = MAKE_RRCM_ERROR(dwStatus);
  161. IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
  162. // return the unique RTP session ID
  163. return ((HANDLE)pSession);
  164. }
  165. /*----------------------------------------------------------------------------
  166. * Function : CloseRTPSession
  167. * Description: Terminates a local stream session.
  168. *
  169. * Input : RTPSession = RTP session ID
  170. * byeReason = -> to BYE reason
  171. * closeRTCPSocket = TRUE/FALSE. RTCP will close or not the socket
  172. *
  173. * Return: RRCM_NoError = OK.
  174. * Otherwise(!=0) = Error (see RRCM.H)
  175. ---------------------------------------------------------------------------*/
  176. HRESULT WINAPI CloseRTPSession (HANDLE RTPSession,
  177. PCHAR byeReason,
  178. DWORD closeRTCPSocket)
  179. {
  180. PRTP_SESSION pSession;
  181. PSSRC_ENTRY pSSRCList;
  182. PSSRC_ENTRY pSSRC;
  183. DWORD dwStatus;
  184. IN_OUT_STR ("RTP : Enter CloseRTPSession()\n");
  185. // If RTP context doesn't exist, report error and return.
  186. if (pRTPContext == NULL)
  187. {
  188. RRCM_DBG_MSG ("RTP : ERROR - No RTP Instance", 0,
  189. __FILE__, __LINE__, DBG_ERROR);
  190. IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
  191. return (MAKE_RRCM_ERROR(RRCMError_RTPNoContext));
  192. }
  193. // Cast Session ID to obtain the session pointer.
  194. pSession = (PRTP_SESSION)RTPSession;
  195. if (pSession == NULL)
  196. {
  197. RRCM_DBG_MSG ("RTP : ERROR - Invalid RTP session", 0,
  198. __FILE__, __LINE__, DBG_ERROR);
  199. IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
  200. return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidSession));
  201. }
  202. // Remove the session from the linked list of sessions
  203. dwStatus = deleteRTPSession (pRTPContext, pSession);
  204. if (dwStatus != RRCM_NoError)
  205. {
  206. #ifdef _DEBUG
  207. wsprintf(debug_string,
  208. "RTP : ERROR - RTP session (Addr:0x%p) not found",
  209. RTPSession);
  210. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_ERROR);
  211. #endif
  212. return (MAKE_RRCM_ERROR(dwStatus));
  213. }
  214. // lock out the session - it's on a free list now
  215. EnterCriticalSection (&pSession->critSect);
  216. #if 0
  217. // clean up the Hash table for any stream still left in the Session
  218. for (pSSRCList = (PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
  219. pSSRCList != NULL;
  220. pSSRCList = (PSSRC_ENTRY)pSSRCList->SSRCList.next)
  221. {
  222. deleteHashEntry (pSSRCList->RTPsd);
  223. }
  224. #endif
  225. // All seems OK, close RTCP for each stream still open
  226. pSSRC = (PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
  227. if (pSSRC == NULL)
  228. {
  229. RRCM_DBG_MSG ("RTP : ERROR - No SSRC entry on the Xmt list", 0,
  230. __FILE__, __LINE__, DBG_ERROR);
  231. IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
  232. return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidSSRCentry));
  233. }
  234. // reset the close socket flag
  235. if (closeRTCPSocket)
  236. pSSRC->dwSSRCStatus |= CLOSE_RTCP_SOCKET;
  237. dwStatus = deleteRTCPSession (pSSRC->RTCPsd, byeReason);
  238. #ifdef _DEBUG
  239. if (dwStatus != RRCM_NoError)
  240. {
  241. wsprintf(debug_string,
  242. "RTP : ERROR - RTCP delete Session (Addr: x%p) error:%d",
  243. pSession, dwStatus);
  244. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  245. }
  246. #endif
  247. #ifdef _DEBUG
  248. wsprintf(debug_string, "RTP : Deleting Session x%p", pSession);
  249. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  250. #endif
  251. // lock out the session - it's on a free list now
  252. LeaveCriticalSection (&pSession->critSect);
  253. DeleteCriticalSection (&pSession->critSect);
  254. GlobalFree (pSession);
  255. pSession = NULL;
  256. IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
  257. if (dwStatus != RRCM_NoError)
  258. dwStatus = MAKE_RRCM_ERROR(dwStatus);
  259. return (dwStatus);
  260. }
  261. /*--------------------------------------------------------------------------
  262. ** Function : deleteRTPSession
  263. ** Description: Remove from RTP session queue and restore links for other
  264. ** sessions.
  265. **
  266. ** Input : pRTPContext: -> to the RTP context
  267. ** pSession: -> to the RTP session
  268. **
  269. ** Return: OK: RRCM_NoError
  270. ** !0: Error code (see RRCM.H)
  271. --------------------------------------------------------------------------*/
  272. DWORD deleteRTPSession(PRTP_CONTEXT pRTPContext,
  273. PRTP_SESSION pSession)
  274. {
  275. PLINK_LIST pTmp;
  276. IN_OUT_STR ("RTP : Enter deleteRTPSession()\n");
  277. // make sure the session exist
  278. pTmp = pRTPContext->pRTPSession.prev;
  279. while (pTmp)
  280. {
  281. if (pTmp == (PLINK_LIST)pSession)
  282. break;
  283. pTmp = pTmp->next;
  284. }
  285. if (pTmp == NULL)
  286. {
  287. RRCM_DBG_MSG ("RTP : ERROR - Invalid RTP session", 0,
  288. __FILE__, __LINE__, DBG_ERROR);
  289. IN_OUT_STR ("RTP : Exit deleteRTPSession()\n");
  290. return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidSession));
  291. }
  292. // lock out queue access
  293. EnterCriticalSection (&pRTPContext->critSect);
  294. EnterCriticalSection (&pSession->critSect);
  295. if (pSession->RTPList.prev == NULL)
  296. // this was the first entry in the queue
  297. pRTPContext->pRTPSession.prev = pSession->RTPList.next;
  298. else
  299. (pSession->RTPList.prev)->next = pSession->RTPList.next;
  300. if (pSession->RTPList.next == NULL)
  301. // this was the last entry in the queue
  302. pRTPContext->pRTPSession.next = pSession->RTPList.prev;
  303. else
  304. (pSession->RTPList.next)->prev = pSession->RTPList.prev;
  305. // unlock out queue access
  306. LeaveCriticalSection (&pSession->critSect);
  307. LeaveCriticalSection (&pRTPContext->critSect);
  308. IN_OUT_STR ("RTP : Exit deleteRTPSession()\n");
  309. return (RRCM_NoError);
  310. }
  311. // [EOF]