int CUDP_RTSPClient::sendSetupCommand(const char * url) { char* authenticatorStr = createAuthenticatorString("SETUP", url); char sendBuf[RTSPCOMMANDLEN]; memset(sendBuf, 0, RTSPCOMMANDLEN); std::string strSession = m_SessionID; if( strSession.length() > 0 ){ strSession = "Session: "; strSession += m_SessionID; strSession += "\r\n"; } char * OptionsInfo = "SETUP %s RTSP/1.0\r\n" "CSeq: %d\r\n" "%s" "Transport: RTP/AVP;unicast;client_port=%d-%d\r\n" "%s" "User-Agent:%s\r\n" "\r\n"; int iClientRTPPort = 0; iClientRTPPort = s_udpportvector.GetFreeUDPPort() - 1; if( m_bSendingVideoSETUP ) m_clinet_video_rtpport = iClientRTPPort; if( m_bSendingAudioSETUP ) m_clinet_audio_rtpport = iClientRTPPort; sprintf(sendBuf, OptionsInfo, url, m_icseq, authenticatorStr/*m_strAuthenticator.c_str()*/, iClientRTPPort, iClientRTPPort + 1, strSession.c_str(), m_user_agent); delete[] authenticatorStr; m_iCommandStatus = SETUPCOMMAND; return sendtoSvr( sendBuf, strlen( sendBuf ) ); return 0; }
char* SIPClient::invite1(Authenticator* authenticator) { do { // Send the INVITE command: // First, construct an authenticator string: fValidAuthenticator.reset(); fWorkingAuthenticator = authenticator; char* authenticatorStr = createAuthenticatorString(fWorkingAuthenticator, "INVITE", fURL); // Then, construct the SDP description to be sent in the INVITE: char* rtpmapLine; unsigned rtpmapLineSize; if (fMIMESubtypeSize > 0) { char const* const rtpmapFmt = "a=rtpmap:%u %s/8000\r\n"; unsigned rtpmapFmtSize = strlen(rtpmapFmt) + 3 /* max char len */ + fMIMESubtypeSize; rtpmapLine = new char[rtpmapFmtSize]; sprintf(rtpmapLine, rtpmapFmt, fDesiredAudioRTPPayloadFormat, fMIMESubtype); rtpmapLineSize = strlen(rtpmapLine); } else { // Static payload type => no "a=rtpmap:" line rtpmapLine = strDup(""); rtpmapLineSize = 0; } char const* const inviteSDPFmt = "v=0\r\n" "o=- %u %u IN IP4 %s\r\n" "s=%s session\r\n" "c=IN IP4 %s\r\n" "t=0 0\r\n" "m=audio %u RTP/AVP %u\r\n" "%s"; unsigned inviteSDPFmtSize = strlen(inviteSDPFmt) + 20 /* max int len */ + 20 + fOurAddressStrSize + fApplicationNameSize + fOurAddressStrSize + 5 /* max short len */ + 3 /* max char len */ + rtpmapLineSize; delete[] fInviteSDPDescription; fInviteSDPDescription = new char[inviteSDPFmtSize]; sprintf(fInviteSDPDescription, inviteSDPFmt, fCallId, fCSeq, fOurAddressStr, fApplicationName, fOurAddressStr, fClientStartPortNum, fDesiredAudioRTPPayloadFormat, rtpmapLine); unsigned inviteSDPSize = strlen(fInviteSDPDescription); delete[] rtpmapLine; char const* const cmdFmt = "INVITE %s SIP/2.0\r\n" "From: %s <sip:%s@%s>;tag=%u\r\n" "Via: SIP/2.0/UDP %s:%u\r\n" "Max-Forwards: 70\r\n" "To: %s\r\n" "Contact: sip:%s@%s:%u\r\n" "Call-ID: %u@%s\r\n" "CSeq: %d INVITE\r\n" "Content-Type: application/sdp\r\n" "%s" /* Proxy-Authorization: line (if any) */ "%s" /* User-Agent: line */ "Content-Length: %d\r\n\r\n" "%s"; unsigned inviteCmdSize = strlen(cmdFmt) + fURLSize + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ + fOurAddressStrSize + 5 /* max port len */ + fURLSize + fUserNameSize + fOurAddressStrSize + 5 + 20 + fOurAddressStrSize + 20 + strlen(authenticatorStr) + fUserAgentHeaderStrLen + 20 + inviteSDPSize; delete[] fInviteCmd; fInviteCmd = new char[inviteCmdSize]; sprintf(fInviteCmd, cmdFmt, fURL, fUserName, fUserName, fOurAddressStr, fFromTag, fOurAddressStr, fOurPortNum, fURL, fUserName, fOurAddressStr, fOurPortNum, fCallId, fOurAddressStr, ++fCSeq, authenticatorStr, fUserAgentHeaderStr, inviteSDPSize, fInviteSDPDescription); fInviteCmdSize = strlen(fInviteCmd); delete[] authenticatorStr; // Before sending the "INVITE", arrange to handle any response packets, // and set up timers: fInviteClientState = Calling; fEventLoopStopFlag = 0; TaskScheduler& sched = envir().taskScheduler(); // abbrev. sched.turnOnBackgroundReadHandling(fOurSocket->socketNum(), &inviteResponseHandler, this); fTimerALen = 1*fT1; // initially fTimerACount = 0; // initially fTimerA = sched.scheduleDelayedTask(fTimerALen, timerAHandler, this); fTimerB = sched.scheduleDelayedTask(64*fT1, timerBHandler, this); fTimerD = NULL; // for now if (!sendINVITE()) break; // Enter the event loop, to handle response packets, and timeouts: envir().taskScheduler().doEventLoop(&fEventLoopStopFlag); // We're finished with this "INVITE". // Turn off response handling and timers: sched.turnOffBackgroundReadHandling(fOurSocket->socketNum()); sched.unscheduleDelayedTask(fTimerA); sched.unscheduleDelayedTask(fTimerB); sched.unscheduleDelayedTask(fTimerD); // NOTE: We return the SDP description that we used in the "INVITE", // not the one that we got from the server. // ##### Later: match the codecs in the response (offer, answer) ##### if (fInviteSDPDescription != NULL) { return strDup(fInviteSDPDescription); } } while (0); return NULL; }