#include <SIPClient.hh>
Inheritance diagram for SIPClient:


Public Member Functions | |
| void | setProxyServer (unsigned proxyServerAddress, portNumBits proxyServerPortNum) |
| void | setClientStartPortNum (portNumBits clientStartPortNum) |
| char * | invite (char const *url, Authenticator *authenticator=NULL) |
| char * | inviteWithPassword (char const *url, char const *username, char const *password) |
| Boolean | sendACK () |
| Boolean | sendBYE () |
| unsigned | inviteStatus () const |
| UsageEnvironment & | envir () const |
| char const * | name () const |
| virtual Boolean | isSource () const |
| virtual Boolean | isSink () const |
| virtual Boolean | isRTCPInstance () const |
| virtual Boolean | isRTSPClient () const |
| virtual Boolean | isRTSPServer () const |
| virtual Boolean | isMediaSession () const |
| virtual Boolean | isServerMediaSession () const |
| virtual Boolean | isDarwinInjector () const |
Static Public Member Functions | |
| static SIPClient * | createNew (UsageEnvironment &env, unsigned char desiredAudioRTPPayloadFormat, char const *mimeSubtype=NULL, int verbosityLevel=0, char const *applicationName=NULL) |
| static Boolean | parseSIPURL (UsageEnvironment &env, char const *url, NetAddress &address, portNumBits &portNum) |
| static Boolean | parseSIPURLUsernamePassword (char const *url, char *&username, char *&password) |
| static Boolean | lookupByName (UsageEnvironment &env, char const *mediumName, Medium *&resultMedium) |
| static void | close (UsageEnvironment &env, char const *mediumName) |
| static void | close (Medium *medium) |
Protected Member Functions | |
| virtual | ~SIPClient () |
| TaskToken & | nextTask () |
Private Member Functions | |
| SIPClient (UsageEnvironment &env, unsigned char desiredAudioRTPPayloadFormat, char const *mimeSubtype, int verbosityLevel, char const *applicationName) | |
| void | reset () |
| char * | invite1 (Authenticator *authenticator) |
| Boolean | processURL (char const *url) |
| Boolean | sendINVITE () |
| void | doInviteStateMachine (unsigned responseCode) |
| void | doInviteStateTerminated (unsigned responseCode) |
| char * | createAuthenticatorString (Authenticator const *authenticator, char const *cmd, char const *url) |
| Boolean | sendRequest (char const *requestString, unsigned requestLength) |
| unsigned | getResponseCode () |
| unsigned | getResponse (char *&responseBuffer, unsigned responseBufferSize) |
| Boolean | parseResponseCode (char const *line, unsigned &responseCode) |
Static Private Member Functions | |
| static void | inviteResponseHandler (void *clientData, int mask) |
| static void | timerAHandler (void *clientData) |
| static void | timerBHandler (void *clientData) |
| static void | timerDHandler (void *clientData) |
Private Attributes | |
| TaskToken | fTimerA |
| TaskToken | fTimerB |
| TaskToken | fTimerD |
| unsigned const | fT1 |
| unsigned | fTimerALen |
| unsigned | fTimerACount |
| unsigned char | fDesiredAudioRTPPayloadFormat |
| char * | fMIMESubtype |
| unsigned | fMIMESubtypeSize |
| int | fVerbosityLevel |
| unsigned | fCSeq |
| char const * | fApplicationName |
| unsigned | fApplicationNameSize |
| char const * | fOurAddressStr |
| unsigned | fOurAddressStrSize |
| portNumBits | fOurPortNum |
| Groupsock * | fOurSocket |
| char * | fUserAgentHeaderStr |
| unsigned | fUserAgentHeaderStrSize |
| char const * | fURL |
| unsigned | fURLSize |
| in_addr | fServerAddress |
| portNumBits | fServerPortNum |
| portNumBits | fClientStartPortNum |
| unsigned | fCallId |
| unsigned | fFromTag |
| char const * | fToTagStr |
| unsigned | fToTagStrSize |
| Authenticator | fValidAuthenticator |
| char const * | fUserName |
| unsigned | fUserNameSize |
| char * | fInviteSDPDescription |
| char * | fInviteCmd |
| unsigned | fInviteCmdSize |
| Authenticator * | fWorkingAuthenticator |
| inviteClientState | fInviteClientState |
| char | fEventLoopStopFlag |
| unsigned | fInviteStatusCode |
Definition at line 37 of file SIPClient.hh.
| SIPClient::~SIPClient | ( | ) | [protected, virtual] |
Definition at line 119 of file SIPClient.cpp.
References fApplicationName, fMIMESubtype, fOurAddressStr, fOurSocket, fUserAgentHeaderStr, and reset().
00119 { 00120 reset(); 00121 00122 delete[] fUserAgentHeaderStr; 00123 delete fOurSocket; 00124 delete[] (char*)fOurAddressStr; 00125 delete[] (char*)fApplicationName; 00126 delete[] (char*)fMIMESubtype; 00127 }
| SIPClient::SIPClient | ( | UsageEnvironment & | env, | |
| unsigned char | desiredAudioRTPPayloadFormat, | |||
| char const * | mimeSubtype, | |||
| int | verbosityLevel, | |||
| char const * | applicationName | |||
| ) | [private] |
Definition at line 41 of file SIPClient.cpp.
References env, Medium::envir(), fApplicationName, fApplicationNameSize, fMIMESubtype, fMIMESubtypeSize, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fOurSocket, fUserAgentHeaderStr, fUserAgentHeaderStrSize, UsageEnvironment::getResultMsg(), getSourcePort(), libVersionStr, LIVEMEDIA_LIBRARY_VERSION_STRING, NULL, Port::num(), our_inet_ntoa(), ourIPAddress(), Groupsock::output(), reset(), Socket::socketNum(), and strDup().
00045 : Medium(env), 00046 fT1(500000 /* 500 ms */), 00047 fDesiredAudioRTPPayloadFormat(desiredAudioRTPPayloadFormat), 00048 fVerbosityLevel(verbosityLevel), 00049 fCSeq(0), fURL(NULL), fURLSize(0), 00050 fToTagStr(NULL), fToTagStrSize(0), 00051 fUserName(NULL), fUserNameSize(0), 00052 fInviteSDPDescription(NULL), fInviteCmd(NULL), fInviteCmdSize(0){ 00053 if (mimeSubtype == NULL) mimeSubtype = ""; 00054 fMIMESubtype = strDup(mimeSubtype); 00055 fMIMESubtypeSize = strlen(fMIMESubtype); 00056 00057 if (applicationName == NULL) applicationName = ""; 00058 fApplicationName = strDup(applicationName); 00059 fApplicationNameSize = strlen(fApplicationName); 00060 00061 struct in_addr ourAddress; 00062 ourAddress.s_addr = ourIPAddress(env); // hack 00063 fOurAddressStr = strDup(our_inet_ntoa(ourAddress)); 00064 fOurAddressStrSize = strlen(fOurAddressStr); 00065 00066 fOurSocket = new Groupsock(env, ourAddress, 0, 255); 00067 if (fOurSocket == NULL) { 00068 env << "ERROR: Failed to create socket for addr " 00069 << our_inet_ntoa(ourAddress) << ": " 00070 << env.getResultMsg() << "\n"; 00071 } 00072 00073 // Now, find out our source port number. Hack: Do this by first trying to 00074 // send a 0-length packet, so that the "getSourcePort()" call will work. 00075 fOurSocket->output(envir(), 255, (unsigned char*)"", 0); 00076 Port srcPort(0); 00077 getSourcePort(env, fOurSocket->socketNum(), srcPort); 00078 if (srcPort.num() != 0) { 00079 fOurPortNum = ntohs(srcPort.num()); 00080 } else { 00081 // No luck. Try again using a default port number: 00082 fOurPortNum = 5060; 00083 delete fOurSocket; 00084 fOurSocket = new Groupsock(env, ourAddress, fOurPortNum, 255); 00085 if (fOurSocket == NULL) { 00086 env << "ERROR: Failed to create socket for addr " 00087 << our_inet_ntoa(ourAddress) << ", port " 00088 << fOurPortNum << ": " 00089 << env.getResultMsg() << "\n"; 00090 } 00091 } 00092 00093 // Set various headers to be used in each request: 00094 char const* formatStr; 00095 unsigned headerSize; 00096 00097 // Set the "User-Agent:" header: 00098 char const* const libName = "LIVE555 Streaming Media v"; 00099 char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING; 00100 char const* libPrefix; char const* libSuffix; 00101 if (applicationName == NULL || applicationName[0] == '\0') { 00102 applicationName = libPrefix = libSuffix = ""; 00103 } else { 00104 libPrefix = " ("; 00105 libSuffix = ")"; 00106 } 00107 formatStr = "User-Agent: %s%s%s%s%s\r\n"; 00108 headerSize 00109 = strlen(formatStr) + fApplicationNameSize + strlen(libPrefix) 00110 + strlen(libName) + strlen(libVersionStr) + strlen(libSuffix); 00111 fUserAgentHeaderStr = new char[headerSize]; 00112 sprintf(fUserAgentHeaderStr, formatStr, 00113 applicationName, libPrefix, libName, libVersionStr, libSuffix); 00114 fUserAgentHeaderStrSize = strlen(fUserAgentHeaderStr); 00115 00116 reset(); 00117 }
| SIPClient * SIPClient::createNew | ( | UsageEnvironment & | env, | |
| unsigned char | desiredAudioRTPPayloadFormat, | |||
| char const * | mimeSubtype = NULL, |
|||
| int | verbosityLevel = 0, |
|||
| char const * | applicationName = NULL | |||
| ) | [static] |
Definition at line 33 of file SIPClient.cpp.
References env.
Referenced by createClient().
00036 { 00037 return new SIPClient(env, desiredAudioRTPPayloadFormat, mimeSubtype, 00038 verbosityLevel, applicationName); 00039 }
| void SIPClient::setProxyServer | ( | unsigned | proxyServerAddress, | |
| portNumBits | proxyServerPortNum | |||
| ) |
Definition at line 145 of file SIPClient.cpp.
References Groupsock::changeDestinationParameters(), fOurSocket, fServerAddress, fServerPortNum, and NULL.
Referenced by getSDPDescriptionFromURL().
00146 { 00147 fServerAddress.s_addr = proxyServerAddress; 00148 fServerPortNum = proxyServerPortNum; 00149 if (fOurSocket != NULL) { 00150 fOurSocket->changeDestinationParameters(fServerAddress, 00151 fServerPortNum, 255); 00152 } 00153 }
| void SIPClient::setClientStartPortNum | ( | portNumBits | clientStartPortNum | ) | [inline] |
Definition at line 48 of file SIPClient.hh.
References fClientStartPortNum.
Referenced by getSDPDescriptionFromURL().
00048 { 00049 fClientStartPortNum = clientStartPortNum; 00050 }
| char * SIPClient::invite | ( | char const * | url, | |
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 169 of file SIPClient.cpp.
References fCallId, fFromTag, fInviteStatusCode, fURL, fURLSize, invite1(), inviteWithPassword(), NULL, our_random(), parseSIPURLUsernamePassword(), password, processURL(), strDup(), and username.
Referenced by getSDPDescriptionFromURL(), and inviteWithPassword().
00169 { 00170 // First, check whether "url" contains a username:password to be used: 00171 fInviteStatusCode = 0; 00172 char* username; char* password; 00173 if (authenticator == NULL 00174 && parseSIPURLUsernamePassword(url, username, password)) { 00175 char* result = inviteWithPassword(url, username, password); 00176 delete[] username; delete[] password; // they were dynamically allocated 00177 return result; 00178 } 00179 00180 if (!processURL(url)) return NULL; 00181 00182 delete[] (char*)fURL; fURL = strDup(url); 00183 fURLSize = strlen(fURL); 00184 00185 fCallId = our_random(); 00186 fFromTag = our_random(); 00187 00188 return invite1(authenticator); 00189 }
| char * SIPClient::inviteWithPassword | ( | char const * | url, | |
| char const * | username, | |||
| char const * | password | |||
| ) |
Definition at line 606 of file SIPClient.cpp.
References fUserName, fUserNameSize, fValidAuthenticator, invite(), invite1(), Authenticator::nonce(), NULL, Authenticator::realm(), Authenticator::setUsernameAndPassword(), and strDup().
Referenced by getSDPDescriptionFromURL(), and invite().
00607 { 00608 delete[] (char*)fUserName; fUserName = strDup(username); 00609 fUserNameSize = strlen(fUserName); 00610 00611 Authenticator authenticator; 00612 authenticator.setUsernameAndPassword(username, password); 00613 char* inviteResult = invite(url, &authenticator); 00614 if (inviteResult != NULL) { 00615 // We are already authorized 00616 return inviteResult; 00617 } 00618 00619 // The "realm" and "nonce" fields should have been filled in: 00620 if (authenticator.realm() == NULL || authenticator.nonce() == NULL) { 00621 // We haven't been given enough information to try again, so fail: 00622 return NULL; 00623 } 00624 00625 // Try again (but with the same CallId): 00626 inviteResult = invite1(&authenticator); 00627 if (inviteResult != NULL) { 00628 // The authenticator worked, so use it in future requests: 00629 fValidAuthenticator = authenticator; 00630 } 00631 00632 return inviteResult; 00633 }
| Boolean SIPClient::sendACK | ( | ) |
Definition at line 635 of file SIPClient.cpp.
References Medium::envir(), False, fCallId, fCSeq, fFromTag, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, NULL, sendRequest(), UsageEnvironment::setResultErrMsg(), and True.
Referenced by clientStartPlayingSession(), and doInviteStateMachine().
00635 { 00636 char* cmd = NULL; 00637 do { 00638 char* const cmdFmt = 00639 "ACK %s SIP/2.0\r\n" 00640 "From: %s <sip:%s@%s>;tag=%u\r\n" 00641 "Via: SIP/2.0/UDP %s:%u\r\n" 00642 "To: %s;tag=%s\r\n" 00643 "Call-ID: %u@%s\r\n" 00644 "CSeq: %d ACK\r\n" 00645 "Content-length: 0\r\n\r\n"; 00646 unsigned cmdSize = strlen(cmdFmt) 00647 + fURLSize 00648 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00649 + fOurAddressStrSize + 5 /* max port len */ 00650 + fURLSize + fToTagStrSize 00651 + 20 + fOurAddressStrSize 00652 + 20; 00653 cmd = new char[cmdSize]; 00654 sprintf(cmd, cmdFmt, 00655 fURL, 00656 fUserName, fUserName, fOurAddressStr, fFromTag, 00657 fOurAddressStr, fOurPortNum, 00658 fURL, fToTagStr, 00659 fCallId, fOurAddressStr, 00660 fCSeq /* note: it's the same as before; not incremented */); 00661 00662 if (!sendRequest(cmd, strlen(cmd))) { 00663 envir().setResultErrMsg("ACK send() failed: "); 00664 break; 00665 } 00666 00667 delete[] cmd; 00668 return True; 00669 } while (0); 00670 00671 delete[] cmd; 00672 return False; 00673 }
| Boolean SIPClient::sendBYE | ( | ) |
Definition at line 675 of file SIPClient.cpp.
References Medium::envir(), False, fCallId, fCSeq, fFromTag, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, NULL, sendRequest(), UsageEnvironment::setResultErrMsg(), and True.
Referenced by clientTearDownSession().
00675 { 00676 // NOTE: This should really be retransmitted, for reliability ##### 00677 char* cmd = NULL; 00678 do { 00679 char* const cmdFmt = 00680 "BYE %s SIP/2.0\r\n" 00681 "From: %s <sip:%s@%s>;tag=%u\r\n" 00682 "Via: SIP/2.0/UDP %s:%u\r\n" 00683 "To: %s;tag=%s\r\n" 00684 "Call-ID: %u@%s\r\n" 00685 "CSeq: %d ACK\r\n" 00686 "Content-length: 0\r\n\r\n"; 00687 unsigned cmdSize = strlen(cmdFmt) 00688 + fURLSize 00689 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00690 + fOurAddressStrSize + 5 /* max port len */ 00691 + fURLSize + fToTagStrSize 00692 + 20 + fOurAddressStrSize 00693 + 20; 00694 cmd = new char[cmdSize]; 00695 sprintf(cmd, cmdFmt, 00696 fURL, 00697 fUserName, fUserName, fOurAddressStr, fFromTag, 00698 fOurAddressStr, fOurPortNum, 00699 fURL, fToTagStr, 00700 fCallId, fOurAddressStr, 00701 ++fCSeq); 00702 00703 if (!sendRequest(cmd, strlen(cmd))) { 00704 envir().setResultErrMsg("BYE send() failed: "); 00705 break; 00706 } 00707 00708 delete[] cmd; 00709 return True; 00710 } while (0); 00711 00712 delete[] cmd; 00713 return False; 00714 }
| Boolean SIPClient::parseSIPURL | ( | UsageEnvironment & | env, | |
| char const * | url, | |||
| NetAddress & | address, | |||
| portNumBits & | portNum | |||
| ) | [static] |
Definition at line 738 of file SIPClient.cpp.
References _strncasecmp, env, False, NetAddressList::firstAddress(), NetAddressList::numAddresses(), UsageEnvironment::setResultMsg(), and True.
Referenced by processURL().
00740 { 00741 do { 00742 // Parse the URL as "sip:<username>@<address>:<port>/<etc>" 00743 // (with ":<port>" and "/<etc>" optional) 00744 // Also, skip over any "<username>[:<password>]@" preceding <address> 00745 char const* prefix = "sip:"; 00746 unsigned const prefixLength = 4; 00747 if (_strncasecmp(url, prefix, prefixLength) != 0) { 00748 env.setResultMsg("URL is not of the form \"", prefix, "\""); 00749 break; 00750 } 00751 00752 unsigned const parseBufferSize = 100; 00753 char parseBuffer[parseBufferSize]; 00754 unsigned addressStartIndex = prefixLength; 00755 while (url[addressStartIndex] != '\0' 00756 && url[addressStartIndex++] != '@') {} 00757 char const* from = &url[addressStartIndex]; 00758 00759 // Skip over any "<username>[:<password>]@" 00760 char const* from1 = from; 00761 while (*from1 != '\0' && *from1 != '/') { 00762 if (*from1 == '@') { 00763 from = ++from1; 00764 break; 00765 } 00766 ++from1; 00767 } 00768 00769 char* to = &parseBuffer[0]; 00770 unsigned i; 00771 for (i = 0; i < parseBufferSize; ++i) { 00772 if (*from == '\0' || *from == ':' || *from == '/') { 00773 // We've completed parsing the address 00774 *to = '\0'; 00775 break; 00776 } 00777 *to++ = *from++; 00778 } 00779 if (i == parseBufferSize) { 00780 env.setResultMsg("URL is too long"); 00781 break; 00782 } 00783 00784 NetAddressList addresses(parseBuffer); 00785 if (addresses.numAddresses() == 0) { 00786 env.setResultMsg("Failed to find network address for \"", 00787 parseBuffer, "\""); 00788 break; 00789 } 00790 address = *(addresses.firstAddress()); 00791 00792 portNum = 5060; // default value 00793 char nextChar = *from; 00794 if (nextChar == ':') { 00795 int portNumInt; 00796 if (sscanf(++from, "%d", &portNumInt) != 1) { 00797 env.setResultMsg("No port number follows ':'"); 00798 break; 00799 } 00800 if (portNumInt < 1 || portNumInt > 65535) { 00801 env.setResultMsg("Bad port number"); 00802 break; 00803 } 00804 portNum = (portNumBits)portNumInt; 00805 } 00806 00807 return True; 00808 } while (0); 00809 00810 return False; 00811 }
| Boolean SIPClient::parseSIPURLUsernamePassword | ( | char const * | url, | |
| char *& | username, | |||
| char *& | password | |||
| ) | [static] |
Definition at line 813 of file SIPClient.cpp.
References _strncasecmp, False, NULL, strDup(), and True.
Referenced by invite().
00815 { 00816 username = password = NULL; // by default 00817 do { 00818 // Parse the URL as "sip:<username>[:<password>]@<whatever>" 00819 char const* prefix = "sip:"; 00820 unsigned const prefixLength = 4; 00821 if (_strncasecmp(url, prefix, prefixLength) != 0) break; 00822 00823 // Look for the ':' and '@': 00824 unsigned usernameIndex = prefixLength; 00825 unsigned colonIndex = 0, atIndex = 0; 00826 for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) { 00827 if (url[i] == ':' && colonIndex == 0) { 00828 colonIndex = i; 00829 } else if (url[i] == '@') { 00830 atIndex = i; 00831 break; // we're done 00832 } 00833 } 00834 if (atIndex == 0) break; // no '@' found 00835 00836 char* urlCopy = strDup(url); 00837 urlCopy[atIndex] = '\0'; 00838 if (colonIndex > 0) { 00839 urlCopy[colonIndex] = '\0'; 00840 password = strDup(&urlCopy[colonIndex+1]); 00841 } else { 00842 password = strDup(""); 00843 } 00844 username = strDup(&urlCopy[usernameIndex]); 00845 delete[] urlCopy; 00846 00847 return True; 00848 } while (0); 00849 00850 return False; 00851 }
| unsigned SIPClient::inviteStatus | ( | ) | const [inline] |
Definition at line 71 of file SIPClient.hh.
References fInviteStatusCode.
Referenced by getSDPDescriptionFromURL().
00071 { return fInviteStatusCode; }
| void SIPClient::reset | ( | ) | [private] |
Definition at line 129 of file SIPClient.cpp.
References fApplicationName, fInviteCmd, fInviteCmdSize, fInviteSDPDescription, fServerAddress, fServerPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, fValidAuthenticator, fWorkingAuthenticator, NULL, Authenticator::reset(), and strDup().
Referenced by SIPClient(), and ~SIPClient().
00129 { 00130 fWorkingAuthenticator = NULL; 00131 delete[] fInviteCmd; fInviteCmd = NULL; fInviteCmdSize = 0; 00132 delete[] fInviteSDPDescription; fInviteSDPDescription = NULL; 00133 00134 delete[] (char*)fUserName; fUserName = strDup(fApplicationName); 00135 fUserNameSize = strlen(fUserName); 00136 00137 fValidAuthenticator.reset(); 00138 00139 delete[] (char*)fToTagStr; fToTagStr = NULL; fToTagStrSize = 0; 00140 fServerPortNum = 0; 00141 fServerAddress.s_addr = 0; 00142 delete[] (char*)fURL; fURL = NULL; fURLSize = 0; 00143 }
| char * SIPClient::invite1 | ( | Authenticator * | authenticator | ) | [private] |
Definition at line 191 of file SIPClient.cpp.
References Calling, createAuthenticatorString(), TaskScheduler::doEventLoop(), Medium::envir(), fApplicationName, fApplicationNameSize, fCallId, fClientStartPortNum, fCSeq, fDesiredAudioRTPPayloadFormat, fEventLoopStopFlag, fFromTag, fInviteClientState, fInviteCmd, fInviteCmdSize, fInviteSDPDescription, fInviteStatusCode, fMIMESubtype, fMIMESubtypeSize, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fOurSocket, fT1, fTimerA, fTimerACount, fTimerALen, fTimerB, fTimerD, fURL, fURLSize, fUserAgentHeaderStr, fUserAgentHeaderStrSize, fUserName, fUserNameSize, fValidAuthenticator, fWorkingAuthenticator, inviteResponseHandler(), NULL, Authenticator::reset(), TaskScheduler::scheduleDelayedTask(), sendINVITE(), Socket::socketNum(), strDup(), UsageEnvironment::taskScheduler(), timerAHandler(), timerBHandler(), TaskScheduler::turnOffBackgroundReadHandling(), TaskScheduler::turnOnBackgroundReadHandling(), and TaskScheduler::unscheduleDelayedTask().
Referenced by invite(), and inviteWithPassword().
00191 { 00192 do { 00193 // Send the INVITE command: 00194 00195 // First, construct an authenticator string: 00196 fValidAuthenticator.reset(); 00197 fWorkingAuthenticator = authenticator; 00198 char* authenticatorStr 00199 = createAuthenticatorString(fWorkingAuthenticator, "INVITE", fURL); 00200 00201 // Then, construct the SDP description to be sent in the INVITE: 00202 char* rtpmapLine; 00203 unsigned rtpmapLineSize; 00204 if (fMIMESubtypeSize > 0) { 00205 char* const rtpmapFmt = 00206 "a=rtpmap:%u %s/8000\r\n"; 00207 unsigned rtpmapFmtSize = strlen(rtpmapFmt) 00208 + 3 /* max char len */ + fMIMESubtypeSize; 00209 rtpmapLine = new char[rtpmapFmtSize]; 00210 sprintf(rtpmapLine, rtpmapFmt, 00211 fDesiredAudioRTPPayloadFormat, fMIMESubtype); 00212 rtpmapLineSize = strlen(rtpmapLine); 00213 } else { 00214 // Static payload type => no "a=rtpmap:" line 00215 rtpmapLine = strDup(""); 00216 rtpmapLineSize = 0; 00217 } 00218 char* const inviteSDPFmt = 00219 "v=0\r\n" 00220 "o=- %u %u IN IP4 %s\r\n" 00221 "s=%s session\r\n" 00222 "c=IN IP4 %s\r\n" 00223 "t=0 0\r\n" 00224 "m=audio %u RTP/AVP %u\r\n" 00225 "%s"; 00226 unsigned inviteSDPFmtSize = strlen(inviteSDPFmt) 00227 + 20 /* max int len */ + 20 + fOurAddressStrSize 00228 + fApplicationNameSize 00229 + fOurAddressStrSize 00230 + 5 /* max short len */ + 3 /* max char len */ 00231 + rtpmapLineSize; 00232 delete[] fInviteSDPDescription; 00233 fInviteSDPDescription = new char[inviteSDPFmtSize]; 00234 sprintf(fInviteSDPDescription, inviteSDPFmt, 00235 fCallId, fCSeq, fOurAddressStr, 00236 fApplicationName, 00237 fOurAddressStr, 00238 fClientStartPortNum, fDesiredAudioRTPPayloadFormat, 00239 rtpmapLine); 00240 unsigned inviteSDPSize = strlen(fInviteSDPDescription); 00241 delete[] rtpmapLine; 00242 00243 char* const cmdFmt = 00244 "INVITE %s SIP/2.0\r\n" 00245 "From: %s <sip:%s@%s>;tag=%u\r\n" 00246 "Via: SIP/2.0/UDP %s:%u\r\n" 00247 "To: %s\r\n" 00248 "Contact: sip:%s@%s:%u\r\n" 00249 "Call-ID: %u@%s\r\n" 00250 "CSeq: %d INVITE\r\n" 00251 "Content-Type: application/sdp\r\n" 00252 "%s" /* Proxy-Authorization: line (if any) */ 00253 "%s" /* User-Agent: line */ 00254 "Content-length: %d\r\n\r\n" 00255 "%s"; 00256 unsigned inviteCmdSize = strlen(cmdFmt) 00257 + fURLSize 00258 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00259 + fOurAddressStrSize + 5 /* max port len */ 00260 + fURLSize 00261 + fUserNameSize + fOurAddressStrSize + 5 00262 + 20 + fOurAddressStrSize 00263 + 20 00264 + strlen(authenticatorStr) 00265 + fUserAgentHeaderStrSize 00266 + 20 00267 + inviteSDPSize; 00268 delete[] fInviteCmd; fInviteCmd = new char[inviteCmdSize]; 00269 sprintf(fInviteCmd, cmdFmt, 00270 fURL, 00271 fUserName, fUserName, fOurAddressStr, fFromTag, 00272 fOurAddressStr, fOurPortNum, 00273 fURL, 00274 fUserName, fOurAddressStr, fOurPortNum, 00275 fCallId, fOurAddressStr, 00276 ++fCSeq, 00277 authenticatorStr, 00278 fUserAgentHeaderStr, 00279 inviteSDPSize, 00280 fInviteSDPDescription); 00281 fInviteCmdSize = strlen(fInviteCmd); 00282 delete[] authenticatorStr; 00283 00284 // Before sending the "INVITE", arrange to handle any response packets, 00285 // and set up timers: 00286 fInviteClientState = Calling; 00287 fEventLoopStopFlag = 0; 00288 TaskScheduler& sched = envir().taskScheduler(); // abbrev. 00289 sched.turnOnBackgroundReadHandling(fOurSocket->socketNum(), 00290 &inviteResponseHandler, this); 00291 fTimerALen = 1*fT1; // initially 00292 fTimerACount = 0; // initially 00293 fTimerA = sched.scheduleDelayedTask(fTimerALen, timerAHandler, this); 00294 fTimerB = sched.scheduleDelayedTask(64*fT1, timerBHandler, this); 00295 fTimerD = NULL; // for now 00296 00297 if (!sendINVITE()) break; 00298 00299 // Enter the event loop, to handle response packets, and timeouts: 00300 envir().taskScheduler().doEventLoop(&fEventLoopStopFlag); 00301 00302 // We're finished with this "INVITE". 00303 // Turn off response handling and timers: 00304 sched.turnOffBackgroundReadHandling(fOurSocket->socketNum()); 00305 sched.unscheduleDelayedTask(fTimerA); 00306 sched.unscheduleDelayedTask(fTimerB); 00307 sched.unscheduleDelayedTask(fTimerD); 00308 00309 // NOTE: We return the SDP description that we used in the "INVITE", 00310 // not the one that we got from the server. 00311 // ##### Later: match the codecs in the response (offer, answer) ##### 00312 if (fInviteSDPDescription != NULL) { 00313 return strDup(fInviteSDPDescription); 00314 } 00315 } while (0); 00316 00317 fInviteStatusCode = 2; 00318 return NULL; 00319 }
| Boolean SIPClient::processURL | ( | char const * | url | ) | [private] |
Definition at line 716 of file SIPClient.cpp.
References Groupsock::changeDestinationParameters(), N