/*---------------------------------------------------------------------------- * File: RTPSEND.C * Product: RTP/RTCP implementation * Description: Provides WSA Send functions. * * This listing is supplied under the terms * of a license agreement with Intel Corporation and * many not be copied nor disclosed except in accordance * with the terms of that agreement. * Copyright (c) 1995 Intel Corporation. *--------------------------------------------------------------------------*/ #include "rrcm.h" /*--------------------------------------------------------------------------- / Global Variables /--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- / External Variables /--------------------------------------------------------------------------*/ extern PRTP_CONTEXT pRTPContext; extern RRCM_WS RRCMws; #if (defined(_DEBUG) || defined(PCS_COMPLIANCE)) //INTEROP extern LPInteropLogger RTPLogger; #endif /*---------------------------------------------------------------------------- * Function : RTPSendTo * Description: Intercepts sendto requests from the application. * Handles any statistical processing required for RTCP. * Copies completion routine from app and substitutes its own. * Apps completion routine will be called after RTP's completion * routine gets called by Winsock2. * * Input : RTPsocket: RTP socket descriptor * pBufs: -> to WSAbuf structure * dwBufCount: Buffer count in WSAbuf structure * pNumBytesSent: -> to number of bytes sent * socketFlags: Flags * pTo: -> to the destination address * toLen: Destination address length * pOverlapped: -> to overlapped I/O structure * pCompletionRoutine: -> to completion routine * * Return: RRCM_NoError = OK. * Otherwise(!=0) = Check RRCM.h file for references. ---------------------------------------------------------------------------*/ DWORD WINAPI RTPSendTo ( HANDLE hRTPSess, SOCKET RTPsocket, LPWSABUF pBufs, DWORD dwBufCount, LPDWORD pNumBytesSent, int socketFlags, LPVOID pTo, int toLen, LPWSAOVERLAPPED pOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE pCompletionRoutine) { int dwStatus; int dwErrorStatus; PRTP_SESSION pRTPSession = (PRTP_SESSION) hRTPSess; RTP_HDR_T *pRTPHeader; PSSRC_ENTRY pSSRC; IN_OUT_STR ("RTP : Enter RTPSendTo()\n"); // If RTP context doesn't exist, report error and return. if (pRTPContext == NULL) { RRCM_DBG_MSG ("RTP : ERROR - No RTP Instance", 0, __FILE__, __LINE__, DBG_CRITICAL); IN_OUT_STR ("RTP : Exit RTPSendTo()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTPInvalid)); } ASSERT(pRTPSession); // Complete filling in header. First cast a pointer // of type RTP_HDR_T to ease accessing pRTPHeader = (RTP_HDR_T *)pBufs->buf; ASSERT (pRTPHeader); // Now setup some of the RTP header fields pRTPHeader->type = RTP_TYPE; // RTP Version 2 // Get pointer to our entry in SSRC table for this session pSSRC = searchForMySSRC ( (PSSRC_ENTRY)pRTPSession->pRTCPSession->XmtSSRCList.prev, RTPsocket); ASSERT (pSSRC); // lock out access to this RTCP session variable EnterCriticalSection (&pSSRC->critSect); // save the RTP timestamp RRCMws.ntohl (RTPsocket, pRTPHeader->ts, &pSSRC->xmtInfo.dwLastSendRTPTimeStamp); // save the last transmit time pSSRC->xmtInfo.dwLastSendRTPSystemTime = timeGetTime (); // copy over sequence number sent RRCMws.ntohs (RTPsocket, pRTPHeader->seq, (WORD *)&pSSRC->xmtInfo.dwCurXmtSeqNum); // SSRC RRCMws.htonl (RTPsocket, pSSRC->SSRC, &pRTPHeader->ssrc); // Update initial XmtSeqNum so RTCP knows the baseline if ((pSSRC->dwSSRCStatus & SEQ_NUM_UPDATED) == 0) { pSSRC->xmtInfo.dwPrvXmtSeqNum = pSSRC->xmtInfo.dwCurXmtSeqNum; pSSRC->dwSSRCStatus |= SEQ_NUM_UPDATED; } // update the payload type for this SSRC_ENTRY pSSRC->PayLoadType = pRTPHeader->pt; // unlock pointer access LeaveCriticalSection (&pSSRC->critSect); #if (defined(_DEBUG) || defined(PCS_COMPLIANCE)) if (RTPLogger) { //INTEROP InteropOutput (RTPLogger, (BYTE FAR*)(pBufs->buf), (int)pBufs->len, RTPLOG_SENT_PDU | RTP_PDU); } #endif dwStatus = RRCMws.sendTo (RTPsocket, pBufs, dwBufCount, pNumBytesSent, socketFlags, (PSOCKADDR)pTo, toLen, pOverlapped, pCompletionRoutine); if (dwStatus != SOCKET_ERROR || GetLastError() == WSA_IO_PENDING) { DWORD i, cbTransferred = 0; // assume the send will succeed /* lock out access to this RTCP session variable */ EnterCriticalSection (&pSSRC->critSect); // calculate statistics (-DWORD) for the CRSC entry defined // in the RTP header (but we should remove it from the data structure) for (i = 0;i < dwBufCount; i++) cbTransferred += pBufs[i].len; pSSRC->xmtInfo.dwNumBytesSent += (cbTransferred - (sizeof(RTP_HDR_T) - sizeof(DWORD))); pSSRC->xmtInfo.dwNumPcktSent++; /* unlock access */ LeaveCriticalSection (&pSSRC->critSect); } IN_OUT_STR ("RTP : Exit RTPSendTo()\n"); return (dwStatus); } // [EOF]