#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 () |
| 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 |
Friends | |
| class | MediaLookupTable |
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(), 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(AddressString(ourAddress).val()); 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 << fOurAddressStr << ": " 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 << fOurAddressStr << ", 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 getSDPDescription().
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 getSDPDescription().
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, fURL, fURLSize, invite1(), inviteWithPassword(), NULL, our_random32(), parseSIPURLUsernamePassword(), password, processURL(), strDup(), and username.
Referenced by getSDPDescription(), and inviteWithPassword().
00169 { 00170 // First, check whether "url" contains a username:password to be used: 00171 char* username; char* password; 00172 if (authenticator == NULL 00173 && parseSIPURLUsernamePassword(url, username, password)) { 00174 char* result = inviteWithPassword(url, username, password); 00175 delete[] username; delete[] password; // they were dynamically allocated 00176 return result; 00177 } 00178 00179 if (!processURL(url)) return NULL; 00180 00181 delete[] (char*)fURL; fURL = strDup(url); 00182 fURLSize = strlen(fURL); 00183 00184 fCallId = our_random32(); 00185 fFromTag = our_random32(); 00186 00187 return invite1(authenticator); 00188 }
| char * SIPClient::inviteWithPassword | ( | char const * | url, | |
| char const * | username, | |||
| char const * | password | |||
| ) |
Definition at line 604 of file SIPClient.cpp.
References fUserName, fUserNameSize, fValidAuthenticator, invite(), invite1(), Authenticator::nonce(), NULL, Authenticator::realm(), and strDup().
Referenced by getSDPDescription(), and invite().
00605 { 00606 delete[] (char*)fUserName; fUserName = strDup(username); 00607 fUserNameSize = strlen(fUserName); 00608 00609 Authenticator authenticator(username, password); 00610 char* inviteResult = invite(url, &authenticator); 00611 if (inviteResult != NULL) { 00612 // We are already authorized 00613 return inviteResult; 00614 } 00615 00616 // The "realm" and "nonce" fields should have been filled in: 00617 if (authenticator.realm() == NULL || authenticator.nonce() == NULL) { 00618 // We haven't been given enough information to try again, so fail: 00619 return NULL; 00620 } 00621 00622 // Try again (but with the same CallId): 00623 inviteResult = invite1(&authenticator); 00624 if (inviteResult != NULL) { 00625 // The authenticator worked, so use it in future requests: 00626 fValidAuthenticator = authenticator; 00627 } 00628 00629 return inviteResult; 00630 }
| Boolean SIPClient::sendACK | ( | ) |
Definition at line 632 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 doInviteStateMachine(), and startPlayingSession().
00632 { 00633 char* cmd = NULL; 00634 do { 00635 char const* const cmdFmt = 00636 "ACK %s SIP/2.0\r\n" 00637 "From: %s <sip:%s@%s>;tag=%u\r\n" 00638 "Via: SIP/2.0/UDP %s:%u\r\n" 00639 "To: %s;tag=%s\r\n" 00640 "Call-ID: %u@%s\r\n" 00641 "CSeq: %d ACK\r\n" 00642 "Content-Length: 0\r\n\r\n"; 00643 unsigned cmdSize = strlen(cmdFmt) 00644 + fURLSize 00645 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00646 + fOurAddressStrSize + 5 /* max port len */ 00647 + fURLSize + fToTagStrSize 00648 + 20 + fOurAddressStrSize 00649 + 20; 00650 cmd = new char[cmdSize]; 00651 sprintf(cmd, cmdFmt, 00652 fURL, 00653 fUserName, fUserName, fOurAddressStr, fFromTag, 00654 fOurAddressStr, fOurPortNum, 00655 fURL, fToTagStr, 00656 fCallId, fOurAddressStr, 00657 fCSeq /* note: it's the same as before; not incremented */); 00658 00659 if (!sendRequest(cmd, strlen(cmd))) { 00660 envir().setResultErrMsg("ACK send() failed: "); 00661 break; 00662 } 00663 00664 delete[] cmd; 00665 return True; 00666 } while (0); 00667 00668 delete[] cmd; 00669 return False; 00670 }
| Boolean SIPClient::sendBYE | ( | ) |
Definition at line 672 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 tearDownSession().
00672 { 00673 // NOTE: This should really be retransmitted, for reliability ##### 00674 char* cmd = NULL; 00675 do { 00676 char const* const cmdFmt = 00677 "BYE %s SIP/2.0\r\n" 00678 "From: %s <sip:%s@%s>;tag=%u\r\n" 00679 "Via: SIP/2.0/UDP %s:%u\r\n" 00680 "To: %s;tag=%s\r\n" 00681 "Call-ID: %u@%s\r\n" 00682 "CSeq: %d ACK\r\n" 00683 "Content-Length: 0\r\n\r\n"; 00684 unsigned cmdSize = strlen(cmdFmt) 00685 + fURLSize 00686 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00687 + fOurAddressStrSize + 5 /* max port len */ 00688 + fURLSize + fToTagStrSize 00689 + 20 + fOurAddressStrSize 00690 + 20; 00691 cmd = new char[cmdSize]; 00692 sprintf(cmd, cmdFmt, 00693 fURL, 00694 fUserName, fUserName, fOurAddressStr, fFromTag, 00695 fOurAddressStr, fOurPortNum, 00696 fURL, fToTagStr, 00697 fCallId, fOurAddressStr, 00698 ++fCSeq); 00699 00700 if (!sendRequest(cmd, strlen(cmd))) { 00701 envir().setResultErrMsg("BYE send() failed: "); 00702 break; 00703 } 00704 00705 delete[] cmd; 00706 return True; 00707 } while (0); 00708 00709 delete[] cmd; 00710 return False; 00711 }
| Boolean SIPClient::parseSIPURL | ( | UsageEnvironment & | env, | |
| char const * | url, | |||
| NetAddress & | address, | |||
| portNumBits & | portNum | |||
| ) | [static] |
Definition at line 734 of file SIPClient.cpp.
References _strncasecmp, env, False, NetAddressList::firstAddress(), NetAddressList::numAddresses(), UsageEnvironment::setResultMsg(), and True.
Referenced by processURL().
00736 { 00737 do { 00738 // Parse the URL as "sip:<username>@<address>:<port>/<etc>" 00739 // (with ":<port>" and "/<etc>" optional) 00740 // Also, skip over any "<username>[:<password>]@" preceding <address> 00741 char const* prefix = "sip:"; 00742 unsigned const prefixLength = 4; 00743 if (_strncasecmp(url, prefix, prefixLength) != 0) { 00744 env.setResultMsg("URL is not of the form \"", prefix, "\""); 00745 break; 00746 } 00747 00748 unsigned const parseBufferSize = 100; 00749 char parseBuffer[parseBufferSize]; 00750 unsigned addressStartIndex = prefixLength; 00751 while (url[addressStartIndex] != '\0' 00752 && url[addressStartIndex++] != '@') {} 00753 char const* from = &url[addressStartIndex]; 00754 00755 // Skip over any "<username>[:<password>]@" 00756 char const* from1 = from; 00757 while (*from1 != '\0' && *from1 != '/') { 00758 if (*from1 == '@') { 00759 from = ++from1; 00760 break; 00761 } 00762 ++from1; 00763 } 00764 00765 char* to = &parseBuffer[0]; 00766 unsigned i; 00767 for (i = 0; i < parseBufferSize; ++i) { 00768 if (*from == '\0' || *from == ':' || *from == '/') { 00769 // We've completed parsing the address 00770 *to = '\0'; 00771 break; 00772 } 00773 *to++ = *from++; 00774 } 00775 if (i == parseBufferSize) { 00776 env.setResultMsg("URL is too long"); 00777 break; 00778 } 00779 00780 NetAddressList addresses(parseBuffer); 00781 if (addresses.numAddresses() == 0) { 00782 env.setResultMsg("Failed to find network address for \"", 00783 parseBuffer, "\""); 00784 break; 00785 } 00786 address = *(addresses.firstAddress()); 00787 00788 portNum = 5060; // default value 00789 char nextChar = *from; 00790 if (nextChar == ':') { 00791 int portNumInt; 00792 if (sscanf(++from, "%d", &portNumInt) != 1) { 00793 env.setResultMsg("No port number follows ':'"); 00794 break; 00795 } 00796 if (portNumInt < 1 || portNumInt > 65535) { 00797 env.setResultMsg("Bad port number"); 00798 break; 00799 } 00800 portNum = (portNumBits)portNumInt; 00801 } 00802 00803 return True; 00804 } while (0); 00805 00806 return False; 00807 }
| Boolean SIPClient::parseSIPURLUsernamePassword | ( | char const * | url, | |
| char *& | username, | |||
| char *& | password | |||
| ) | [static] |
Definition at line 809 of file SIPClient.cpp.
References _strncasecmp, False, NULL, strDup(), and True.
Referenced by invite().
00811 { 00812 username = password = NULL; // by default 00813 do { 00814 // Parse the URL as "sip:<username>[:<password>]@<whatever>" 00815 char const* prefix = "sip:"; 00816 unsigned const prefixLength = 4; 00817 if (_strncasecmp(url, prefix, prefixLength) != 0) break; 00818 00819 // Look for the ':' and '@': 00820 unsigned usernameIndex = prefixLength; 00821 unsigned colonIndex = 0, atIndex = 0; 00822 for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) { 00823 if (url[i] == ':' && colonIndex == 0) { 00824 colonIndex = i; 00825 } else if (url[i] == '@') { 00826 atIndex = i; 00827 break; // we're done 00828 } 00829 } 00830 if (atIndex == 0) break; // no '@' found 00831 00832 char* urlCopy = strDup(url); 00833 urlCopy[atIndex] = '\0'; 00834 if (colonIndex > 0) { 00835 urlCopy[colonIndex] = '\0'; 00836 password = strDup(&urlCopy[colonIndex+1]); 00837 } else { 00838 password = strDup(""); 00839 } 00840 username = strDup(&urlCopy[usernameIndex]); 00841 delete[] urlCopy; 00842 00843 return True; 00844 } while (0); 00845 00846 return False; 00847 }
| 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 190 of file SIPClient.cpp.
References Calling, createAuthenticatorString(), TaskScheduler::doEventLoop(), Medium::envir(), fApplicationName, fApplicationNameSize, fCallId, fClientStartPortNum, fCSeq, fDesiredAudioRTPPayloadFormat, fEventLoopStopFlag, fFromTag, fInviteClientState, fInviteCmd, fInviteCmdSize, fInviteSDPDescription, 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().
00190 { 00191 do { 00192 // Send the INVITE command: 00193 00194 // First, construct an authenticator string: 00195 fValidAuthenticator.reset(); 00196 fWorkingAuthenticator = authenticator; 00197 char* authenticatorStr 00198 = createAuthenticatorString(fWorkingAuthenticator, "INVITE", fURL); 00199 00200 // Then, construct the SDP description to be sent in the INVITE: 00201 char* rtpmapLine; 00202 unsigned rtpmapLineSize; 00203 if (fMIMESubtypeSize > 0) { 00204 char const* const rtpmapFmt = 00205 "a=rtpmap:%u %s/8000\r\n"; 00206 unsigned rtpmapFmtSize = strlen(rtpmapFmt) 00207 + 3 /* max char len */ + fMIMESubtypeSize; 00208 rtpmapLine = new char[rtpmapFmtSize]; 00209 sprintf(rtpmapLine, rtpmapFmt, 00210 fDesiredAudioRTPPayloadFormat, fMIMESubtype); 00211 rtpmapLineSize = strlen(rtpmapLine); 00212 } else { 00213 // Static payload type => no "a=rtpmap:" line 00214 rtpmapLine = strDup(""); 00215 rtpmapLineSize = 0; 00216 } 00217 char const* const inviteSDPFmt = 00218 "v=0\r\n" 00219 "o=- %u %u IN IP4 %s\r\n" 00220 "s=%s session\r\n" 00221 "c=IN IP4 %s\r\n" 00222 "t=0 0\r\n" 00223 "m=audio %u RTP/AVP %u\r\n" 00224 "%s"; 00225 unsigned inviteSDPFmtSize = strlen(inviteSDPFmt) 00226 + 20 /* max int len */ + 20 + fOurAddressStrSize 00227 + fApplicationNameSize 00228 + fOurAddressStrSize 00229 + 5 /* max short len */ + 3 /* max char len */ 00230 + rtpmapLineSize; 00231 delete[] fInviteSDPDescription; 00232 fInviteSDPDescription = new char[inviteSDPFmtSize]; 00233 sprintf(fInviteSDPDescription, inviteSDPFmt, 00234 fCallId, fCSeq, fOurAddressStr, 00235 fApplicationName, 00236 fOurAddressStr, 00237 fClientStartPortNum, fDesiredAudioRTPPayloadFormat, 00238 rtpmapLine); 00239 unsigned inviteSDPSize = strlen(fInviteSDPDescription); 00240 delete[] rtpmapLine; 00241 00242 char const* const cmdFmt = 00243 "INVITE %s SIP/2.0\r\n" 00244 "From: %s <sip:%s@%s>;tag=%u\r\n" 00245 "Via: SIP/2.0/UDP %s:%u\r\n" 00246 "To: %s\r\n" 00247 "Contact: sip:%s@%s:%u\r\n" 00248 "Call-ID: %u@%s\r\n" 00249 "CSeq: %d INVITE\r\n" 00250 "Content-Type: application/sdp\r\n" 00251 "%s" /* Proxy-Authorization: line (if any) */ 00252 "%s" /* User-Agent: line */ 00253 "Content-Length: %d\r\n\r\n" 00254 "%s"; 00255 unsigned inviteCmdSize = strlen(cmdFmt) 00256 + fURLSize 00257 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00258 + fOurAddressStrSize + 5 /* max port len */ 00259 + fURLSize 00260 + fUserNameSize + fOurAddressStrSize + 5 00261 + 20 + fOurAddressStrSize 00262 + 20 00263 + strlen(authenticatorStr) 00264 + fUserAgentHeaderStrSize 00265 + 20 00266 + inviteSDPSize; 00267 delete[] fInviteCmd; fInviteCmd = new char[inviteCmdSize]; 00268 sprintf(fInviteCmd, cmdFmt, 00269 fURL, 00270 fUserName, fUserName, fOurAddressStr, fFromTag, 00271 fOurAddressStr, fOurPortNum, 00272 fURL, 00273 fUserName, fOurAddressStr, fOurPortNum, 00274 fCallId, fOurAddressStr, 00275 ++fCSeq, 00276 authenticatorStr, 00277 fUserAgentHeaderStr, 00278 inviteSDPSize, 00279 fInviteSDPDescription); 00280 fInviteCmdSize = strlen(fInviteCmd); 00281 delete[] authenticatorStr; 00282 00283 // Before sending the "INVITE", arrange to handle any response packets, 00284 // and set up timers: 00285 fInviteClientState = Calling; 00286 fEventLoopStopFlag = 0; 00287 TaskScheduler& sched = envir().taskScheduler(); // abbrev. 00288 sched.turnOnBackgroundReadHandling(fOurSocket->socketNum(), 00289 &inviteResponseHandler, this); 00290 fTimerALen = 1*fT1; // initially 00291 fTimerACount = 0; // initially 00292 fTimerA = sched.scheduleDelayedTask(fTimerALen, timerAHandler, this); 00293 fTimerB = sched.scheduleDelayedTask(64*fT1, timerBHandler, this); 00294 fTimerD = NULL; // for now 00295 00296 if (!sendINVITE()) break; 00297 00298 // Enter the event loop, to handle response packets, and timeouts: 00299 envir().taskScheduler().doEventLoop(&fEventLoopStopFlag); 00300 00301 // We're finished with this "INVITE". 00302 // Turn off response handling and timers: 00303 sched.turnOffBackgroundReadHandling(fOurSocket->socketNum()); 00304 sched.unscheduleDelayedTask(fTimerA); 00305 sched.unscheduleDelayedTask(fTimerB); 00306 sched.unscheduleDelayedTask(fTimerD); 00307 00308 // NOTE: We return the SDP description that we used in the "INVITE", 00309 // not the one that we got from the server. 00310 // ##### Later: match the codecs in the response (offer, answer) ##### 00311 if (fInviteSDPDescription != NULL) { 00312 return strDup(fInviteSDPDescription); 00313 } 00314 } while (0); 00315 00316 return NULL; 00317 }
| Boolean SIPClient::processURL | ( | char const * | url | ) | [private] |
Definition at line 713 of file SIPClient.cpp.
References Groupsock::changeDestinationParameters(), NetAddress::data(), Medium::envir(), False, fOurSocket, fServerAddress, fServerPortNum, NULL, parseSIPURL(), and True.
Referenced by invite().
00713 { 00714 do { 00715 // If we don't already have a server address/port, then 00716 // get these by parsing the URL: 00717 if (fServerAddress.s_addr == 0) { 00718 NetAddress destAddress; 00719 if (!parseSIPURL(envir(), url, destAddress, fServerPortNum)) break; 00720 fServerAddress.s_addr = *(unsigned*)(destAddress.data()); 00721 00722 if (fOurSocket != NULL) { 00723 fOurSocket->changeDestinationParameters(fServerAddress, 00724 fServerPortNum, 255); 00725 } 00726 } 00727 00728 return True; 00729 } while (0); 00730 00731 return False; 00732 }
| Boolean SIPClient::sendINVITE | ( | ) | [private] |
Definition at line 441 of file SIPClient.cpp.
References Medium::envir(), False, fInviteCmd, fInviteCmdSize, sendRequest(), UsageEnvironment::setResultErrMsg(), and True.
Referenced by doInviteStateMachine(), and invite1().
00441 { 00442 if (!sendRequest(fInviteCmd, fInviteCmdSize)) { 00443 envir().setResultErrMsg("INVITE send() failed: "); 00444 return False; 00445 } 00446 return True; 00447 }
| void SIPClient::inviteResponseHandler | ( | void * | clientData, | |
| int | mask | |||
| ) | [static, private] |
Definition at line 319 of file SIPClient.cpp.
References doInviteStateMachine(), and getResponseCode().
Referenced by invite1().
00319 { 00320 SIPClient* client = (SIPClient*)clientData; 00321 unsigned responseCode = client->getResponseCode(); 00322 client->doInviteStateMachine(responseCode); 00323 }
| void SIPClient::doInviteStateMachine | ( | unsigned | responseCode | ) | [private] |
Definition at line 358 of file SIPClient.cpp.
References Calling, Completed, doInviteStateTerminated(), Medium::envir(), fInviteClientState, fTimerA, fTimerALen, fTimerB, fTimerD, Proceeding, TaskScheduler::scheduleDelayedTask(), sendACK(), sendINVITE(), UsageEnvironment::setResultMsg(), UsageEnvironment::taskScheduler(), Terminated, timerAFires, timerAHandler(), timerBFires, timerDFires, timerDHandler(), and TaskScheduler::unscheduleDelayedTask().
Referenced by inviteResponseHandler(), timerAHandler(), timerBHandler(), and timerDHandler().
00358 { 00359 // Implement the state transition diagram (RFC 3261, Figure 5) 00360 TaskScheduler& sched = envir().taskScheduler(); // abbrev. 00361 switch (fInviteClientState) { 00362 case Calling: { 00363 if (responseCode == timerAFires) { 00364 // Restart timer A (with double the timeout interval): 00365 fTimerALen *= 2; 00366 fTimerA 00367 = sched.scheduleDelayedTask(fTimerALen, timerAHandler, this); 00368 00369 fInviteClientState = Calling; 00370 if (!sendINVITE()) doInviteStateTerminated(0); 00371 } else { 00372 // Turn off timers A & B before moving to a new state: 00373 sched.unscheduleDelayedTask(fTimerA); 00374 sched.unscheduleDelayedTask(fTimerB); 00375 00376 if (responseCode == timerBFires) { 00377 envir().setResultMsg("No response from server"); 00378 doInviteStateTerminated(0); 00379 } else if (responseCode >= 100 && responseCode <= 199) { 00380 fInviteClientState = Proceeding; 00381 } else if (responseCode >= 200 && responseCode <= 299) { 00382 doInviteStateTerminated(responseCode); 00383 } else if (responseCode >= 400 && responseCode <= 499) { 00384 doInviteStateTerminated(responseCode); 00385 // this isn't what the spec says, but it seems right... 00386 } else if (responseCode >= 300 && responseCode <= 699) { 00387 fInviteClientState = Completed; 00388 fTimerD 00389 = sched.scheduleDelayedTask(32000000, timerDHandler, this); 00390 if (!sendACK()) doInviteStateTerminated(0); 00391 } 00392 } 00393 break; 00394 } 00395 00396 case Proceeding: { 00397 if (responseCode >= 100 && responseCode <= 199) { 00398 fInviteClientState = Proceeding; 00399 } else if (responseCode >= 200 && responseCode <= 299) { 00400 doInviteStateTerminated(responseCode); 00401 } else if (responseCode >= 400 && responseCode <= 499) { 00402 doInviteStateTerminated(responseCode); 00403 // this isn't what the spec says, but it seems right... 00404 } else if (responseCode >= 300 && responseCode <= 699) { 00405 fInviteClientState = Completed; 00406 fTimerD = sched.scheduleDelayedTask(32000000, timerDHandler, this); 00407 if (!sendACK()) doInviteStateTerminated(0); 00408 } 00409 break; 00410 } 00411 00412 case Completed: { 00413 if (responseCode == timerDFires) { 00414 envir().setResultMsg("Transaction terminated"); 00415 doInviteStateTerminated(0); 00416 } else if (responseCode >= 300 && responseCode <= 699) { 00417 fInviteClientState = Completed; 00418 if (!sendACK()) doInviteStateTerminated(0); 00419 } 00420 break; 00421 } 00422 00423 case Terminated: { 00424 doInviteStateTerminated(responseCode); 00425 break; 00426 } 00427 } 00428 }
| void SIPClient::doInviteStateTerminated | ( | unsigned | responseCode | ) | [private] |
Definition at line 430 of file SIPClient.cpp.
References fEventLoopStopFlag, fInviteClientState, fInviteSDPDescription, NULL, and Terminated.
Referenced by doInviteStateMachine().
00430 { 00431 fInviteClientState = Terminated; // FWIW... 00432 if (responseCode < 200 || responseCode > 299) { 00433 // We failed, so return NULL; 00434 delete[] fInviteSDPDescription; fInviteSDPDescription = NULL; 00435 } 00436 00437 // Unblock the event loop: 00438 fEventLoopStopFlag = ~0; 00439 }
| void SIPClient::timerAHandler | ( | void * | clientData | ) | [static, private] |
Definition at line 330 of file SIPClient.cpp.
References doInviteStateMachine(), Medium::envir(), fTimerACount, fTimerALen, fVerbosityLevel, and timerAFires.
Referenced by doInviteStateMachine(), and invite1().
00330 { 00331 SIPClient* client = (SIPClient*)clientData; 00332 if (client->fVerbosityLevel >= 1) { 00333 client->envir() << "RETRANSMISSION " << ++client->fTimerACount 00334 << ", after " << client->fTimerALen/1000000.0 00335 << " additional seconds\n"; 00336 } 00337 client->doInviteStateMachine(timerAFires); 00338 }
| void SIPClient::timerBHandler | ( | void * | clientData | ) | [static, private] |
Definition at line 340 of file SIPClient.cpp.
References doInviteStateMachine(), Medium::envir(), fT1, fVerbosityLevel, and timerBFires.
Referenced by invite1().
00340 { 00341 SIPClient* client = (SIPClient*)clientData; 00342 if (client->fVerbosityLevel >= 1) { 00343 client->envir() << "RETRANSMISSION TIMEOUT, after " 00344 << 64*client->fT1/1000000.0 << " seconds\n"; 00345 fflush(stderr); 00346 } 00347 client->doInviteStateMachine(timerBFires); 00348 }
| void SIPClient::timerDHandler | ( | void * | clientData | ) | [static, private] |
Definition at line 350 of file SIPClient.cpp.
References doInviteStateMachine(), Medium::envir(), fVerbosityLevel, and timerDFires.
Referenced by doInviteStateMachine().
00350 { 00351 SIPClient* client = (SIPClient*)clientData; 00352 if (client->fVerbosityLevel >= 1) { 00353 client->envir() << "TIMER D EXPIRED\n"; 00354 } 00355 client->doInviteStateMachine(timerDFires); 00356 }
| char * SIPClient::createAuthenticatorString | ( | Authenticator const * | authenticator, | |
| char const * | cmd, | |||
| char const * | url | |||
| ) | [private] |
Definition at line 850 of file SIPClient.cpp.
References Authenticator::computeDigestResponse(), Authenticator::nonce(), NULL, Authenticator::password(), Authenticator::realm(), Authenticator::reclaimDigestResponse(), strDup(), and Authenticator::username().
Referenced by invite1().
00851 { 00852 if (authenticator != NULL && authenticator->realm() != NULL 00853 && authenticator->nonce() != NULL && authenticator->username() != NULL 00854 && authenticator->password() != NULL) { 00855 // We've been provided a filled-in authenticator, so use it: 00856 char const* const authFmt 00857 = "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", response=\"%s\", uri=\"%s\"\r\n"; 00858 char const* response = authenticator->computeDigestResponse(cmd, url); 00859 unsigned authBufSize = strlen(authFmt) 00860 + strlen(authenticator->username()) + strlen(authenticator->realm()) 00861 + strlen(authenticator->nonce()) + strlen(url) + strlen(response); 00862 char* authenticatorStr = new char[authBufSize]; 00863 sprintf(authenticatorStr, authFmt, 00864 authenticator->username(), authenticator->realm(), 00865 authenticator->nonce(), response, url); 00866 authenticator->reclaimDigestResponse(response); 00867 00868 return authenticatorStr; 00869 } 00870 00871 return strDup(""); 00872 }
| Boolean SIPClient::sendRequest | ( | char const * | requestString, | |
| unsigned | requestLength | |||
| ) | [private] |
Definition at line 874 of file SIPClient.cpp.
References Medium::envir(), fOurSocket, fVerbosityLevel, and Groupsock::output().
Referenced by sendACK(), sendBYE(), and sendINVITE().
00875 { 00876 if (fVerbosityLevel >= 1) { 00877 envir() << "Sending request: " << requestString << "\n"; 00878 } 00879 // NOTE: We should really check that "requestLength" is not ##### 00880 // too large for UDP (see RFC 3261, section 18.1.1) ##### 00881 return fOurSocket->output(envir(), 255, (unsigned char*)requestString, 00882 requestLength); 00883 }
| unsigned SIPClient::getResponseCode | ( | ) | [private] |
Definition at line 449 of file SIPClient.cpp.
References Medium::envir(), False, fOurSocket, fToTagStr, fToTagStrSize, fVerbosityLevel, fWorkingAuthenticator, getLine(), getResponse(), Groupsock::handleRead(), NULL, parseResponseCode(), Authenticator::setRealmAndNonce(), UsageEnvironment::setResultMsg(), strDup(), strDupSize(), and True.
Referenced by inviteResponseHandler().
00449 { 00450 unsigned responseCode = 0; 00451 do { 00452 // Get the response from the server: 00453 unsigned const readBufSize = 10000; 00454 char readBuffer[readBufSize+1]; char* readBuf = readBuffer; 00455 00456 char* firstLine = NULL; 00457 char* nextLineStart = NULL; 00458 unsigned bytesRead = getResponse(readBuf, readBufSize); 00459 if (bytesRead == 0) break; 00460 if (fVerbosityLevel >= 1) { 00461 envir() << "Received INVITE response: " << readBuf << "\n"; 00462 } 00463 00464 // Inspect the first line to get the response code: 00465 firstLine = readBuf; 00466 nextLineStart = getLine(firstLine); 00467 if (!parseResponseCode(firstLine, responseCode)) break; 00468 00469 if (responseCode != 200) { 00470 if (responseCode >= 400 && responseCode <= 499 00471 && fWorkingAuthenticator != NULL) { 00472 // We have an authentication failure, so fill in 00473 // "*fWorkingAuthenticator" using the contents of a following 00474 // "Proxy-Authenticate:" line. (Once we compute a 'response' for 00475 // "fWorkingAuthenticator", it can be used in a subsequent request 00476 // - that will hopefully succeed.) 00477 char* lineStart; 00478 while (1) { 00479 lineStart = nextLineStart; 00480 if (lineStart == NULL) break; 00481 00482 nextLineStart = getLine(lineStart); 00483 if (lineStart[0] == '\0') break; // this is a blank line 00484 00485 char* realm = strDupSize(lineStart); 00486 char* nonce = strDupSize(lineStart); 00487 // ##### Check for the format of "Proxy-Authenticate:" lines from 00488 // ##### known server types. 00489 // ##### This is a crock! We should make the parsing more general 00490 Boolean foundAuthenticateHeader = False; 00491 if ( 00492 // Asterisk ##### 00493 sscanf(lineStart, "Proxy-Authenticate: Digest realm=\"%[^\"]\", nonce=\"%[^\"]\"", 00494 realm, nonce) == 2 || 00495 // Cisco ATA ##### 00496 sscanf(lineStart, "Proxy-Authenticate: Digest algorithm=MD5,domain=\"%*[^\"]\",nonce=\"%[^\"]\", realm=\"%[^\"]\"", 00497 nonce, realm) == 2) { 00498 fWorkingAuthenticator->setRealmAndNonce(realm, nonce); 00499 foundAuthenticateHeader = True; 00500 } 00501 delete[] realm; delete[] nonce; 00502 if (foundAuthenticateHeader) break; 00503 } 00504 } 00505 envir().setResultMsg("cannot handle INVITE response: ", firstLine); 00506 break; 00507 } 00508 00509 // Skip every subsequent header line, until we see a blank line. 00510 // While doing so, check for "To:" and "Content-Length:" lines. 00511 // The remaining data is assumed to be the SDP descriptor that we want. 00512 // We should really do some more checking on the headers here - e.g., to 00513 // check for "Content-type: application/sdp", "CSeq", etc. ##### 00514 int contentLength = -1; 00515 char* lineStart; 00516 while (1) { 00517 lineStart = nextLineStart; 00518 if (lineStart == NULL) break; 00519 00520 nextLineStart = getLine(lineStart); 00521 if (lineStart[0] == '\0') break; // this is a blank line 00522 00523 char* toTagStr = strDupSize(lineStart); 00524 if (sscanf(lineStart, "To:%*[^;]; tag=%s", toTagStr) == 1) { 00525 delete[] (char*)fToTagStr; fToTagStr = strDup(toTagStr); 00526 fToTagStrSize = strlen(fToTagStr); 00527 } 00528 delete[] toTagStr; 00529 00530 if (sscanf(lineStart, "Content-Length: %d", &contentLength) == 1 00531 || sscanf(lineStart, "Content-length: %d", &contentLength) == 1) { 00532 if (contentLength < 0) { 00533 envir().setResultMsg("Bad \"Content-Length:\" header: \"", 00534 lineStart, "\""); 00535 break; 00536 } 00537 } 00538 } 00539 00540 // We're now at the end of the response header lines 00541 if (lineStart == NULL) { 00542 envir().setResultMsg("no content following header lines: ", readBuf); 00543 break; 00544 } 00545 00546 // Use the remaining data as the SDP descr, but first, check 00547 // the "Content-Length:" header (if any) that we saw. We may need to 00548 // read more data, or we may have extraneous data in the buffer. 00549 char* bodyStart = nextLineStart; 00550 if (bodyStart != NULL && contentLength >= 0) { 00551 // We saw a "Content-Length:" header 00552 unsigned numBodyBytes = &readBuf[bytesRead] - bodyStart; 00553 if (contentLength > (int)numBodyBytes) { 00554 // We need to read more data. First, make sure we have enough 00555 // space for it: 00556 unsigned numExtraBytesNeeded = contentLength - numBodyBytes; 00557 #ifdef USING_TCP 00558 // THIS CODE WORKS ONLY FOR TCP: ##### 00559 unsigned remainingBufferSize 00560 = readBufSize - (bytesRead + (readBuf - readBuffer)); 00561 if (numExtraBytesNeeded > remainingBufferSize) { 00562 char tmpBuf[200]; 00563 sprintf(tmpBuf, "Read buffer size (%d) is too small for \"Content-Length:\" %d (need a buffer size of >= %d bytes\n", 00564 readBufSize, contentLength, 00565 readBufSize + numExtraBytesNeeded - remainingBufferSize); 00566 envir().setResultMsg(tmpBuf); 00567 break; 00568 } 00569 00570 // Keep reading more data until we have enough: 00571 if (fVerbosityLevel >= 1) { 00572 envir() << "Need to read " << numExtraBytesNeeded 00573 << " extra bytes\n"; 00574 } 00575 while (numExtraBytesNeeded > 0) { 00576 char* ptr = &readBuf[bytesRead]; 00577 unsigned bytesRead2; 00578 struct sockaddr_in fromAddr; 00579 Boolean readSuccess 00580 = fOurSocket->handleRead((unsigned char*)ptr, 00581 numExtraBytesNeeded, 00582 bytesRead2, fromAddr); 00583 if (!readSuccess) break; 00584 ptr[bytesRead2] = '\0'; 00585 if (fVerbosityLevel >= 1) { 00586 envir() << "Read " << bytesRead2 00587 << " extra bytes: " << ptr << "\n"; 00588 } 00589 00590 bytesRead += bytesRead2; 00591 numExtraBytesNeeded -= bytesRead2; 00592 } 00593 #endif 00594 if (numExtraBytesNeeded > 0) break; // one of the reads failed 00595 } 00596 00597 bodyStart[contentLength] = '\0'; // trims any extra data 00598 } 00599 } while (0); 00600 00601 return responseCode; 00602 }
| unsigned SIPClient::getResponse | ( | char *& | responseBuffer, | |
| unsigned | responseBufferSize | |||
| ) | [private] |
Definition at line 885 of file SIPClient.cpp.
References Medium::envir(), False, fOurSocket, Groupsock::handleRead(), UsageEnvironment::setResultMsg(), and True.
Referenced by getResponseCode().
00886 { 00887 if (responseBufferSize == 0) return 0; // just in case... 00888 responseBuffer[0] = '\0'; // ditto 00889 00890 // Keep reading data from the socket until we see "\r\n\r\n" (except 00891 // at the start), or until we fill up our buffer. 00892 // Don't read any more than this. 00893 char* p = responseBuffer; 00894 Boolean haveSeenNonCRLF = False; 00895 int bytesRead = 0; 00896 while (bytesRead < (int)responseBufferSize) { 00897 unsigned bytesReadNow; 00898 struct sockaddr_in fromAddr; 00899 unsigned char* toPosn = (unsigned char*)(responseBuffer+bytesRead); 00900 Boolean readSuccess 00901 = fOurSocket->handleRead(toPosn, responseBufferSize-bytesRead, 00902 bytesReadNow, fromAddr); 00903 if (!readSuccess || bytesReadNow == 0) { 00904 envir().setResultMsg("SIP response was truncated"); 00905 break; 00906 } 00907 bytesRead += bytesReadNow; 00908 00909 // Check whether we have "\r\n\r\n": 00910 char* lastToCheck = responseBuffer+bytesRead-4; 00911 if (lastToCheck < responseBuffer) continue; 00912 for (; p <= lastToCheck; ++p) { 00913 if (haveSeenNonCRLF) { 00914 if (*p == '\r' && *(p+1) == '\n' && 00915 *(p+2) == '\r' && *(p+3) == '\n') { 00916 responseBuffer[bytesRead] = '\0'; 00917 00918 // Before returning, trim any \r or \n from the start: 00919 while (*responseBuffer == '\r' || *responseBuffer == '\n') { 00920 ++responseBuffer; 00921 --bytesRead; 00922 } 00923 return bytesRead; 00924 } 00925 } else { 00926 if (*p != '\r' && *p != '\n') { 00927 haveSeenNonCRLF = True; 00928 } 00929 } 00930 } 00931 } 00932 00933 return 0; 00934 }
| Boolean SIPClient::parseResponseCode | ( | char const * | line, | |
| unsigned & | responseCode | |||
| ) | [private] |
Definition at line 936 of file SIPClient.cpp.
References Medium::envir(), False, UsageEnvironment::setResultMsg(), and True.
Referenced by getResponseCode().
00937 { 00938 if (sscanf(line, "%*s%u", &responseCode) != 1) { 00939 envir().setResultMsg("no response code in line: \"", line, "\""); 00940 return False; 00941 } 00942 00943 return True; 00944 }
| Boolean Medium::lookupByName | ( | UsageEnvironment & | env, | |
| char const * | mediumName, | |||
| Medium *& | resultMedium | |||
| ) | [static, inherited] |
Definition at line 41 of file Media.cpp.
References env, False, MediaLookupTable::lookup(), NULL, MediaLookupTable::ourMedia(), UsageEnvironment::setResultMsg(), and True.
Referenced by ServerMediaSession::lookupByName(), RTSPServer::lookupByName(), RTSPClient::lookupByName(), RTCPInstance::lookupByName(), MediaSource::lookupByName(), MediaSink::lookupByName(), MediaSession::lookupByName(), and DarwinInjector::lookupByName().
00042 { 00043 resultMedium = MediaLookupTable::ourMedia(env)->lookup(mediumName); 00044 if (resultMedium == NULL) { 00045 env.setResultMsg("Medium ", mediumName, " does not exist"); 00046 return False; 00047 } 00048 00049 return True; 00050 }
| void Medium::close | ( | UsageEnvironment & | env, | |
| char const * | mediumName | |||
| ) | [static, inherited] |
Definition at line 52 of file Media.cpp.
References env, MediaLookupTable::ourMedia(), and MediaLookupTable::remove().
Referenced by afterPlaying(), Medium::close(), closeMediaSinks(), OnDemandServerMediaSubsession::closeStreamSource(), continueAfterTEARDOWN(), WAVAudioFileSource::createNew(), QuickTimeFileSink::createNew(), QCELPAudioRTPSource::createNew(), MP3FileSource::createNew(), AVIFileSink::createNew(), AMRAudioRTPSource::createNew(), WAVAudioFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), MediaSubsession::deInitiate(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::handleHTTPCmd_StreamingGET(), MediaSubsession::initiate(), MPEG1or2ProgramStreamFileDuration(), MPEG1or2Demux::noteElementaryStreamDeletion(), ByteStreamMultiFileSource::onSourceClosure1(), StreamState::reclaim(), RTSPServer::removeServerMediaSession(), OnDemandServerMediaSubsession::sdpLines(), shutdownStream(), subsessionAfterPlaying(), ClientTrickPlayState::updateStateOnScaleChange(), AMRDeinterleaver::~AMRDeinterleaver(), ByteStreamMultiFileSource::~ByteStreamMultiFileSource(), DarwinInjector::~DarwinInjector(), FramedFilter::~FramedFilter(), H264VideoRTPSink::~H264VideoRTPSink(), InputESSourceRecord::~InputESSourceRecord(), MatroskaFileParser::~MatroskaFileParser(), MatroskaFileServerDemux::~MatroskaFileServerDemux(), MPEG1or2Demux::~MPEG1or2Demux(), MPEG1or2FileServerDemux::~MPEG1or2FileServerDemux(), MPEG2TransportFileServerMediaSubsession::~MPEG2TransportFileServerMediaSubsession(), MPEG2TransportStreamFromPESSource::~MPEG2TransportStreamFromPESSource(), ProxyServerMediaSession::~ProxyServerMediaSession(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::~RTSPClientSessionSupportingHTTPStreaming(), ServerMediaSession::~ServerMediaSession(), ServerMediaSubsession::~ServerMediaSubsession(), StreamClientState::~StreamClientState(), StreamReplicator::~StreamReplicator(), and T140TextRTPSink::~T140TextRTPSink().
00052 { 00053 MediaLookupTable::ourMedia(env)->remove(name); 00054 }
| void Medium::close | ( | Medium * | medium | ) | [static, inherited] |
Definition at line 56 of file Media.cpp.
References Medium::close(), Medium::envir(), Medium::name(), and NULL.
00056 { 00057 if (medium == NULL) return; 00058 00059 close(medium->envir(), medium->name()); 00060 }
| UsageEnvironment& Medium::envir | ( | ) | const [inline, inherited] |
Definition at line 59 of file Media.hh.
References Medium::fEnviron.
Referenced by QuickTimeFileSink::addArbitraryString(), FileSink::addData(), RTCPInstance::addStreamSocket(), MPEG2IFrameIndexFromTransportStream::addToTail(), StreamParser::afterGettingBytes1(), DummySink::afterGettingFrame(), TCPStreamSink::afterGettingFrame(), T140IdleFilter::afterGettingFrame(), FileSink::afterGettingFrame(), MultiFramedRTPSink::afterGettingFrame1(), InputESSourceRecord::afterGettingFrame1(), MPEG2TransportStreamFramer::afterGettingFrame1(), MPEG2IFrameIndexFromTransportStream::afterGettingFrame1(), H264VideoStreamDiscreteFramer::afterGettingFrame1(), BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), H264VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoStreamParser::analyzeVOLHeader(), announceStream(), RTSPServer::RTSPClientSession::changeClientInputSocket(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), H264VideoFileServerMediaSubsession::checkForAuxSDPLine1(), Medium::close(), ProxyServerMediaSubsession::closeStreamSource(), MPEG2IFrameIndexFromTransportStream::compactParseBuffer(), RTSPClient::connectionHandler1(), RTSPClient::connectToServer(), ProxyServerMediaSession::continueAfterDESCRIBE(), ProxyRTSPClient::continueAfterOPTIONS(), ProxyRTSPClient::continueAfterSETUP(), T140TextRTPSink::continuePlaying(), QuickTimeFileSink::continuePlaying(), H264VideoRTPSink::continuePlaying(), AVIFileSink::continuePlaying(), VP8VideoMatroskaFileServerMediaSubsession::createNewRTPSink(), VorbisAudioMatroskaFileServerMediaSubsession::createNewRTPSink(), T140TextMatroskaFileServerMediaSubsession::createNewRTPSink(), ProxyServerMediaSubsession::createNewRTPSink(), MPEG4VideoFileServerMediaSubsession::createNewRTPSink(), MPEG2TransportUDPServerMediaSubsession::createNewRTPSink(), MPEG2TransportFileServerMediaSubsession::createNewRTPSink(), MPEG1or2VideoFileServerMediaSubsession::createNewRTPSink(), MPEG1or2DemuxedServerMediaSubsession::createNewRTPSink(), MP3AudioFileServerMediaSubsession::createNewRTPSink(), H264VideoFileServerMediaSubsession::createNewRTPSink(), H263plusVideoFileServerMediaSubsession::createNewRTPSink(), DVVideoFileServerMediaSubsession::createNewRTPSink(), AMRAudioFileServerMediaSubsession::createNewRTPSink(), ADTSAudioFileServerMediaSubsession::createNewRTPSink(), AC3AudioMatroskaFileServerMediaSubsession::createNewRTPSink(), AC3AudioFileServerMediaSubsession::createNewRTPSink(), AACAudioMatroskaFileServerMediaSubsession::createNewRTPSink(), ProxyServerMediaSubsession::createNewStreamSource(), MPEG4VideoFileServerMediaSubsession::createNewStreamSource(), MPEG2TransportUDPServerMediaSubsession::createNewStreamSource(), MPEG2TransportFileServerMediaSubsession::createNewStreamSource(), MPEG1or2VideoFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), MP3AudioFileServerMediaSubsession::createNewStreamSource(), H264VideoMatroskaFileServerMediaSubsession::createNewStreamSource(), H264VideoFileServerMediaSubsession::createNewStreamSource(), H263plusVideoFileServerMediaSubsession::createNewStreamSource(), DVVideoFileServerMediaSubsession::createNewStreamSource(), AMRAudioFileServerMediaSubsession::createNewStreamSource(), ADTSAudioFileServerMediaSubsession::createNewStreamSource(), AC3AudioFileServerMediaSubsession::createNewStreamSource(), AMRDeinterleavingBuffer::deliverIncomingFrame(), MPEG2IFrameIndexFromTransportStream::deliverIndexRecord(), SegmentQueue::dequeue(), DeviceSource::DeviceSource(), WAVAudioFileSource::doGetNextFrame(), T140IdleFilter::doGetNextFrame(), MPEG2IFrameIndexFromTransportStream::doGetNextFrame(), MP3FileSource::doGetNextFrame(), H264FUAFragmenter::doGetNextFrame(), ByteStreamMultiFileSource::doGetNextFrame(), ByteStreamFileSource::doGetNextFrame(), BasicUDPSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), MP3FileSource::doGetNextFrame1(), ADUFromMP3Source::doGetNextFrame1(), doInviteStateMachine(), WAVAudioFileSource::doReadFromFile(), ByteStreamFileSource::doReadFromFile(), MPEG1or2VideoRTPSink::doSpecialFrameHandling(), MP3ADURTPSink::doSpecialFrameHandling(), H263plusVideoRTPSink::doSpecialFrameHandling(), WAVAudioFileSource::doStopGettingFrames(), T140IdleFilter::doStopGettingFrames(), ByteStreamFileSource::doStopGettingFrames(), BasicUDPSource::doStopGettingFrames(), SegmentQueue::enqueueNewSegment(), StreamParser::ensureValidBytes1(), MediaSubsession::env(), SubsessionIOState::envir(), RTSPServer::RTSPClientSession::envir(), RTPInterface::envir(), AVISubsessionIOState::envir(), ServerMediaSession::generateSDPDescription(), RTPSource::getAttributes(), MP3FileSource::getAttributes(), MP3ADUTranscoder::getAttributes(), MediaSource::getAttributes(), MPEG4VideoFileServerMediaSubsession::getAuxSDPLine(), H264VideoFileServerMediaSubsession::getAuxSDPLine(), getMPEG1or2TimeCode(), FramedSource::getNextFrame(), getOptions(), DVVideoStreamFramer::getProfile(), getResponse(), getResponseCode(), getSDPDescription(), OnDemandServerMediaSubsession::getStreamParameters(), RTSPClient::handleGET_PARAMETERResponse(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::handleHTTPCmd_StreamingGET(), RTSPClient::handleIncomingRequest(), RTSPClient::handlePLAYResponse(), RTSPClient::handleRequestError(), RTSPClient::handleResponseBytes(), RTSPClient::handleSETUPResponse(), RTSPServer::incomingConnectionHandler(), RTSPClient::incomingDataHandler1(), RTCPInstance::incomingReportHandler1(), MP3FileSource::initializeStream(), MediaSession::initializeWithSDP(), MediaSession::initiateByMediaType(), invite1(), DynamicRTSPServer::lookupServerMediaSession(), MatroskaDemux::MatroskaDemux(), MatroskaFile::MatroskaFile(), MPEG4GenericRTPSource::MPEG4GenericRTPSource(), MatroskaDemux::newDemuxedTrack(), MPEG1or2FileServerDemux::newElementaryStream(), MPEG1or2Demux::newElementaryStream(), MPEG4GenericBufferedPacket::nextEnclosedFrameSize(), AMRBufferedPacket::nextEnclosedFrameSize(), T140IdleFilter::onSourceClosure(), RTSPClient::openConnection(), MPEG2TransportStreamIndexFile::openFid(), MPEG2IFrameIndexFromTransportStream::parseFrame(), AC3AudioStreamParser::parseFrame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), parseResponseCode(), MediaSession::parseSDPLine(), MPEG1or2VideoStreamParser::parseSlice(), MatroskaFileParser::parseStartOfFile(), MPEGProgramStreamParser::parseSystemHeader(), MPEG4VideoStreamParser::parseVideoObjectLayer(), MPEG4VideoStreamParser::parseVideoObjectPlane(), MPEG4VideoStreamParser::parseVisualObject(), TCPStreamSink::processBuffer(), processURL(), AC3AudioStreamParser::readAndSaveAFrame(), MPEG1or2Demux::registerReadInterest(), RTCPInstance::reschedule(), RTSPClient::resendCommand(), ProxyRTSPClient::reset(), RTSPClient::resetTCPSockets(), RTSPClient::responseHandlerForHTTP_GET1(), RTSPServer::rtspURLPrefix(), RTCPInstance::schedule(), ProxyRTSPClient::scheduleDESCRIBECommand(), ProxyRTSPClient::scheduleLivenessCommand(), OnDemandServerMediaSubsession::sdpLines(), sendACK(), sendBYE(), sendINVITE(), MultiFramedRTPSink::sendPacketIfNecessary(), sendRequest(), RTSPClient::sendRequest(), DarwinInjector::setDestination(), RTSPClient::setupHTTPTunneling1(), setupNextSubsession(), RTSPServer::setUpTunnelingOverHTTP(), QuickTimeFileSink::setWord(), AVIFileSink::setWord(), QuickTimeFileSink::setWord64(), shutdownStream(), SIPClient(), TCPStreamSink::socketWritableHandler1(), AMRAudioRTPSink::sourceIsCompatibleWithUs(), QuickTimeFileSink::startPlaying(), StreamState::startPlaying(), MediaSink::startPlaying(), AVIFileSink::startPlaying(), startPlayingSession(), PassiveServerMediaSubsession::startStream(), MediaSink::stopPlaying(), ProxyServerMediaSubsession::subsessionByeHandler(), tearDownSession(), timerAHandler(), timerBHandler(), timerDHandler(), ClientTrickPlayState::updateStateOnScaleChange(), MPEG2TransportStreamFramer::updateTSPacketDurationEstimate(), BasicUDPSource::~BasicUDPSource(), ByteStreamFileSource::~ByteStreamFileSource(), DeviceSource::~DeviceSource(), RTSPServer::~RTSPServer(), StreamClientState::~StreamClientState(), T140IdleFilter::~T140IdleFilter(), and WAVAudioFileSource::~WAVAudioFileSource().
00059 {return fEnviron;}
| char const* Medium::name | ( | ) | const [inline, inherited] |
Definition at line 61 of file Media.hh.
References Medium::fMediumName.
Referenced by QuickTimeFileSink::addAtom_hdlr2(), Medium::close(), MP3ADUTranscoder::createNew(), MP3FromADUSource::createNew(), ADUFromMP3Source::createNew(), and MP3FileSource::initializeStream().
00061 {return fMediumName;}
| Boolean Medium::isSource | ( | ) | const [virtual, inherited] |
Reimplemented in MediaSource.
Definition at line 62 of file Media.cpp.
References False.
Referenced by MediaSource::lookupByName().
00062 { 00063 return False; // default implementation 00064 }
| Boolean Medium::isSink | ( | ) | const [virtual, inherited] |
| Boolean Medium::isRTCPInstance | ( | ) | const [virtual, inherited] |
Reimplemented in RTCPInstance.
Definition at line 70 of file Media.cpp.
References False.
Referenced by RTCPInstance::lookupByName().
00070 { 00071 return False; // default implementation 00072 }
| Boolean Medium::isRTSPClient | ( | ) | const [virtual, inherited] |
Reimplemented in RTSPClient.
Definition at line 74 of file Media.cpp.
References False.
Referenced by RTSPClient::lookupByName().
00074 { 00075 return False; // default implementation 00076 }
| Boolean Medium::isRTSPServer | ( | ) | const [virtual, inherited] |
Reimplemented in RTSPServer.
Definition at line 78 of file Media.cpp.
References False.
Referenced by RTSPServer::lookupByName().
00078 { 00079 return False; // default implementation 00080 }
| Boolean Medium::isMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in MediaSession.
Definition at line 82 of file Media.cpp.
References False.
Referenced by MediaSession::lookupByName().
00082 { 00083 return False; // default implementation 00084 }
| Boolean Medium::isServerMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in ServerMediaSession.
Definition at line 86 of file Media.cpp.
References False.
Referenced by ServerMediaSession::lookupByName().
00086 { 00087 return False; // default implementation 00088 }
| Boolean Medium::isDarwinInjector | ( | ) | const [virtual, inherited] |
Reimplemented in DarwinInjector.
Definition at line 90 of file Media.cpp.
References False.
Referenced by DarwinInjector::lookupByName().
00090 { 00091 return False; // default implementation 00092 }
| TaskToken& Medium::nextTask | ( | ) | [inline, protected, inherited] |
Definition at line 78 of file Media.hh.
References Medium::fNextTask.
Referenced by BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), H264VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), H264VideoFileServerMediaSubsession::checkForAuxSDPLine1(), MP3FileSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), WAVAudioFileSource::doReadFromFile(), ByteStreamFileSource::doReadFromFile(), RTCPInstance::reschedule(), RTCPInstance::schedule(), MultiFramedRTPSink::sendPacketIfNecessary(), and MediaSink::stopPlaying().
00078 { 00079 return fNextTask; 00080 }
friend class MediaLookupTable [friend, inherited] |
TaskToken SIPClient::fTimerA [private] |
TaskToken SIPClient::fTimerB [private] |
TaskToken SIPClient::fTimerD [private] |
unsigned const SIPClient::fT1 [private] |
unsigned SIPClient::fTimerALen [private] |
Definition at line 96 of file SIPClient.hh.
Referenced by doInviteStateMachine(), invite1(), and timerAHandler().
unsigned SIPClient::fTimerACount [private] |
unsigned char SIPClient::fDesiredAudioRTPPayloadFormat [private] |
char* SIPClient::fMIMESubtype [private] |
Definition at line 110 of file SIPClient.hh.
Referenced by invite1(), SIPClient(), and ~SIPClient().
unsigned SIPClient::fMIMESubtypeSize [private] |
int SIPClient::fVerbosityLevel [private] |
Definition at line 112 of file SIPClient.hh.
Referenced by getResponseCode(), sendRequest(), timerAHandler(), timerBHandler(), and timerDHandler().
unsigned SIPClient::fCSeq [private] |
char const* SIPClient::fApplicationName [private] |
Definition at line 114 of file SIPClient.hh.
Referenced by invite1(), reset(), SIPClient(), and ~SIPClient().
unsigned SIPClient::fApplicationNameSize [private] |
char const* SIPClient::fOurAddressStr [private] |
Definition at line 116 of file SIPClient.hh.
Referenced by invite1(), sendACK(), sendBYE(), SIPClient(), and ~SIPClient().
unsigned SIPClient::fOurAddressStrSize [private] |
Definition at line 117 of file SIPClient.hh.
Referenced by invite1(), sendACK(), sendBYE(), and SIPClient().
portNumBits SIPClient::fOurPortNum [private] |
Definition at line 118 of file SIPClient.hh.
Referenced by invite1(), sendACK(), sendBYE(), and SIPClient().
Groupsock* SIPClient::fOurSocket [private] |
Definition at line 119 of file SIPClient.hh.
Referenced by getResponse(), getResponseCode(), invite1(), processURL(), sendRequest(), setProxyServer(), SIPClient(), and ~SIPClient().
char* SIPClient::fUserAgentHeaderStr [private] |
Definition at line 120 of file SIPClient.hh.
Referenced by invite1(), SIPClient(), and ~SIPClient().
unsigned SIPClient::fUserAgentHeaderStrSize [private] |
char const* SIPClient::fURL [private] |
unsigned SIPClient::fURLSize [private] |
struct in_addr SIPClient::fServerAddress [read, private] |
Definition at line 126 of file SIPClient.hh.
Referenced by processURL(), reset(), and setProxyServer().
portNumBits SIPClient::fServerPortNum [private] |
Definition at line 127 of file SIPClient.hh.
Referenced by processURL(), reset(), and setProxyServer().
portNumBits SIPClient::fClientStartPortNum [private] |
unsigned SIPClient::fCallId [private] |
unsigned SIPClient::fFromTag [private] |
char const* SIPClient::fToTagStr [private] |
Definition at line 130 of file SIPClient.hh.
Referenced by getResponseCode(), reset(), sendACK(), and sendBYE().
unsigned SIPClient::fToTagStrSize [private] |
Definition at line 131 of file SIPClient.hh.
Referenced by getResponseCode(), reset(), sendACK(), and sendBYE().
Authenticator SIPClient::fValidAuthenticator [private] |
Definition at line 132 of file SIPClient.hh.
Referenced by invite1(), inviteWithPassword(), and reset().
char const* SIPClient::fUserName [private] |
Definition at line 133 of file SIPClient.hh.
Referenced by invite1(), inviteWithPassword(), reset(), sendACK(), and sendBYE().
unsigned SIPClient::fUserNameSize [private] |
Definition at line 134 of file SIPClient.hh.
Referenced by invite1(), inviteWithPassword(), reset(), sendACK(), and sendBYE().
char* SIPClient::fInviteSDPDescription [private] |
Definition at line 136 of file SIPClient.hh.
Referenced by doInviteStateTerminated(), invite1(), and reset().
char* SIPClient::fInviteCmd [private] |
unsigned SIPClient::fInviteCmdSize [private] |
Authenticator* SIPClient::fWorkingAuthenticator [private] |
Definition at line 139 of file SIPClient.hh.
Referenced by getResponseCode(), invite1(), and reset().
Definition at line 140 of file SIPClient.hh.
Referenced by doInviteStateMachine(), doInviteStateTerminated(), and invite1().
char SIPClient::fEventLoopStopFlag [private] |
Definition at line 141 of file SIPClient.hh.
Referenced by doInviteStateTerminated(), and invite1().
1.5.2