#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 |
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 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_random(), 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_random(); 00185 fFromTag = our_random(); 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(), Authenticator::setUsernameAndPassword(), and strDup().
Referenced by getSDPDescription(), and invite().
00605 { 00606 delete[] (char*)fUserName; fUserName = strDup(username); 00607 fUserNameSize = strlen(fUserName); 00608 00609 Authenticator authenticator; 00610 authenticator.setUsernameAndPassword(username, password); 00611 char* inviteResult = invite(url, &authenticator); 00612 if (inviteResult != NULL) { 00613 // We are already authorized 00614 return inviteResult; 00615 } 00616 00617 // The "realm" and "nonce" fields should have been filled in: 00618 if (authenticator.realm() == NULL || authenticator.nonce() == NULL) { 00619 // We haven't been given enough information to try again, so fail: 00620 return NULL; 00621 } 00622 00623 // Try again (but with the same CallId): 00624 inviteResult = invite1(&authenticator); 00625 if (inviteResult != NULL) { 00626 // The authenticator worked, so use it in future requests: 00627 fValidAuthenticator = authenticator; 00628 } 00629 00630 return inviteResult; 00631 }
| Boolean SIPClient::sendACK | ( | ) |
Definition at line 633 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().
00633 { 00634 char* cmd = NULL; 00635 do { 00636 char const* const cmdFmt = 00637 "ACK %s SIP/2.0\r\n" 00638 "From: %s <sip:%s@%s>;tag=%u\r\n" 00639 "Via: SIP/2.0/UDP %s:%u\r\n" 00640 "To: %s;tag=%s\r\n" 00641 "Call-ID: %u@%s\r\n" 00642 "CSeq: %d ACK\r\n" 00643 "Content-length: 0\r\n\r\n"; 00644 unsigned cmdSize = strlen(cmdFmt) 00645 + fURLSize 00646 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00647 + fOurAddressStrSize + 5 /* max port len */ 00648 + fURLSize + fToTagStrSize 00649 + 20 + fOurAddressStrSize 00650 + 20; 00651 cmd = new char[cmdSize]; 00652 sprintf(cmd, cmdFmt, 00653 fURL, 00654 fUserName, fUserName, fOurAddressStr, fFromTag, 00655 fOurAddressStr, fOurPortNum, 00656 fURL, fToTagStr, 00657 fCallId, fOurAddressStr, 00658 fCSeq /* note: it's the same as before; not incremented */); 00659 00660 if (!sendRequest(cmd, strlen(cmd))) { 00661 envir().setResultErrMsg("ACK send() failed: "); 00662 break; 00663 } 00664 00665 delete[] cmd; 00666 return True; 00667 } while (0); 00668 00669 delete[] cmd; 00670 return False; 00671 }
| Boolean SIPClient::sendBYE | ( | ) |
Definition at line 673 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().
00673 { 00674 // NOTE: This should really be retransmitted, for reliability ##### 00675 char* cmd = NULL; 00676 do { 00677 char const* const cmdFmt = 00678 "BYE %s SIP/2.0\r\n" 00679 "From: %s <sip:%s@%s>;tag=%u\r\n" 00680 "Via: SIP/2.0/UDP %s:%u\r\n" 00681 "To: %s;tag=%s\r\n" 00682 "Call-ID: %u@%s\r\n" 00683 "CSeq: %d ACK\r\n" 00684 "Content-length: 0\r\n\r\n"; 00685 unsigned cmdSize = strlen(cmdFmt) 00686 + fURLSize 00687 + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */ 00688 + fOurAddressStrSize + 5 /* max port len */ 00689 + fURLSize + fToTagStrSize 00690 + 20 + fOurAddressStrSize 00691 + 20; 00692 cmd = new char[cmdSize]; 00693 sprintf(cmd, cmdFmt, 00694 fURL, 00695 fUserName, fUserName, fOurAddressStr, fFromTag, 00696 fOurAddressStr, fOurPortNum, 00697 fURL, fToTagStr, 00698 fCallId, fOurAddressStr, 00699 ++fCSeq); 00700 00701 if (!sendRequest(cmd, strlen(cmd))) { 00702 envir().setResultErrMsg("BYE send() failed: "); 00703 break; 00704 } 00705 00706 delete[] cmd; 00707 return True; 00708 } while (0); 00709 00710 delete[] cmd; 00711 return False; 00712 }
| Boolean SIPClient::parseSIPURL | ( | UsageEnvironment & | env, | |
| char const * | url, | |||
| NetAddress & | address, | |||
| portNumBits & | portNum | |||
| ) | [static] |
Definition at line 735 of file SIPClient.cpp.
References _strncasecmp, env, False, NetAddressList::firstAddress(), NetAddressList::numAddresses(), UsageEnvironment::setResultMsg(), and True.
Referenced by processURL().
00737 { 00738 do { 00739 // Parse the URL as "sip:<username>@<address>:<port>/<etc>" 00740 // (with ":<port>" and "/<etc>" optional) 00741 // Also, skip over any "<username>[:<password>]@" preceding <address> 00742 char const* prefix = "sip:"; 00743 unsigned const prefixLength = 4; 00744 if (_strncasecmp(url, prefix, prefixLength) != 0) { 00745 env.setResultMsg("URL is not of the form \"", prefix, "\""); 00746 break; 00747 } 00748 00749 unsigned const parseBufferSize = 100; 00750 char parseBuffer[parseBufferSize]; 00751 unsigned addressStartIndex = prefixLength; 00752 while (url[addressStartIndex] != '\0' 00753 && url[addressStartIndex++] != '@') {} 00754 char const* from = &url[addressStartIndex]; 00755 00756 // Skip over any "<username>[:<password>]@" 00757 char const* from1 = from; 00758 while (*from1 != '\0' && *from1 != '/') { 00759 if (*from1 == '@') { 00760 from = ++from1; 00761 break; 00762 } 00763 ++from1; 00764 } 00765 00766 char* to = &parseBuffer[0]; 00767 unsigned i; 00768 for (i = 0; i < parseBufferSize; ++i) { 00769 if (*from == '\0' || *from == ':' || *from == '/') { 00770 // We've completed parsing the address 00771 *to = '\0'; 00772 break; 00773 } 00774 *to++ = *from++; 00775 } 00776 if (i == parseBufferSize) { 00777 env.setResultMsg("URL is too long"); 00778 break; 00779 } 00780 00781 NetAddressList addresses(parseBuffer); 00782 if (addresses.numAddresses() == 0) { 00783 env.setResultMsg("Failed to find network address for \"", 00784 parseBuffer, "\""); 00785 break; 00786 } 00787 address = *(addresses.firstAddress()); 00788 00789 portNum = 5060; // default value 00790 char nextChar = *from; 00791 if (nextChar == ':') { 00792 int portNumInt; 00793 if (sscanf(++from, "%d", &portNumInt) != 1) { 00794 env.setResultMsg("No port number follows ':'"); 00795 break; 00796 } 00797 if (portNumInt < 1 || portNumInt > 65535) { 00798 env.setResultMsg("Bad port number"); 00799 break; 00800 } 00801 portNum = (portNumBits)portNumInt; 00802 } 00803 00804 return True; 00805 } while (0); 00806 00807 return False; 00808 }
| Boolean SIPClient::parseSIPURLUsernamePassword | ( | char const * | url, | |
| char *& | username, | |||
| char *& | password | |||
| ) | [static] |
Definition at line 810 of file SIPClient.cpp.
References _strncasecmp, False, NULL, strDup(), and True.
Referenced by invite().
00812 { 00813 username = password = NULL; // by default 00814 do { 00815 // Parse the URL as "sip:<username>[:<password>]@<whatever>" 00816 char const* prefix = "sip:"; 00817 unsigned const prefixLength = 4; 00818 if (_strncasecmp(url, prefix, prefixLength) != 0) break; 00819 00820 // Look for the ':' and '@': 00821 unsigned usernameIndex = prefixLength; 00822 unsigned colonIndex = 0, atIndex = 0; 00823 for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) { 00824 if (url[i] == ':' && colonIndex == 0) { 00825 colonIndex = i; 00826 } else if (url[i] == '@') { 00827 atIndex = i; 00828 break; // we're done 00829 } 00830 } 00831 if (atIndex == 0) break; // no '@' found 00832 00833 char* urlCopy = strDup(url); 00834 urlCopy[atIndex] = '\0'; 00835 if (colonIndex > 0) { 00836 urlCopy[colonIndex] = '\0'; 00837 password = strDup(&urlCopy[colonIndex+1]); 00838 } else { 00839 password = strDup(""); 00840 } 00841 username = strDup(&urlCopy[usernameIndex]); 00842 delete[] urlCopy; 00843 00844 return True; 00845 } while (0); 00846 00847 return False; 00848 }
| 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 714 of file SIPClient.cpp.
References Groupsock::changeDestinationParameters(), NetAddress::data(), Medium::envir(), False, fOurSocket, fServerAddress, fServerPortNum, NULL, parseSIPURL(), and True.
Referenced by invite().
00714 { 00715 do { 00716 // If we don't already have a server address/port, then 00717 // get these by parsing the URL: 00718 if (fServerAddress.s_addr == 0) { 00719 NetAddress destAddress; 00720 if (!parseSIPURL(envir(), url, destAddress, fServerPortNum)) break; 00721 fServerAddress.s_addr = *(unsigned*)(destAddress.data()); 00722 00723 if (fOurSocket != NULL) { 00724 fOurSocket->changeDestinationParameters(fServerAddress, 00725 fServerPortNum, 255); 00726 } 00727 } 00728 00729 return True; 00730 } while (0); 00731 00732 return False; 00733 }
| 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 851 of file SIPClient.cpp.
References Authenticator::computeDigestResponse(), Authenticator::nonce(), NULL, Authenticator::password(), Authenticator::realm(), Authenticator::reclaimDigestResponse(), strDup(), and Authenticator::username().
Referenced by invite1().
00852 { 00853 if (authenticator != NULL && authenticator->realm() != NULL 00854 && authenticator->nonce() != NULL && authenticator->username() != NULL 00855 && authenticator->password() != NULL) { 00856 // We've been provided a filled-in authenticator, so use it: 00857 char const* const authFmt 00858 = "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", response=\"%s\", uri=\"%s\"\r\n"; 00859 char const* response = authenticator->computeDigestResponse(cmd, url); 00860 unsigned authBufSize = strlen(authFmt) 00861 + strlen(authenticator->username()) + strlen(authenticator->realm()) 00862 + strlen(authenticator->nonce()) + strlen(url) + strlen(response); 00863 char* authenticatorStr = new char[authBufSize]; 00864 sprintf(authenticatorStr, authFmt, 00865 authenticator->username(), authenticator->realm(), 00866 authenticator->nonce(), response, url); 00867 authenticator->reclaimDigestResponse(response); 00868 00869 return authenticatorStr; 00870 } 00871 00872 return strDup(""); 00873 }
| Boolean SIPClient::sendRequest | ( | char const * | requestString, | |
| unsigned | requestLength | |||
| ) | [private] |
Definition at line 875 of file SIPClient.cpp.
References Medium::envir(), fOurSocket, fVerbosityLevel, and Groupsock::output().
Referenced by sendACK(), sendBYE(), and sendINVITE().
00876 { 00877 if (fVerbosityLevel >= 1) { 00878 envir() << "Sending request: " << requestString << "\n"; 00879 } 00880 // NOTE: We should really check that "requestLength" is not ##### 00881 // too large for UDP (see RFC 3261, section 18.1.1) ##### 00882 return fOurSocket->output(envir(), 255, (unsigned char*)requestString, 00883 requestLength); 00884 }
| 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 886 of file SIPClient.cpp.
References Medium::envir(), False, fOurSocket, Groupsock::handleRead(), UsageEnvironment::setResultMsg(), and True.
Referenced by getResponseCode().
00887 { 00888 if (responseBufferSize == 0) return 0; // just in case... 00889 responseBuffer[0] = '\0'; // ditto 00890 00891 // Keep reading data from the socket until we see "\r\n\r\n" (except 00892 // at the start), or until we fill up our buffer. 00893 // Don't read any more than this. 00894 char* p = responseBuffer; 00895 Boolean haveSeenNonCRLF = False; 00896 int bytesRead = 0; 00897 while (bytesRead < (int)responseBufferSize) { 00898 unsigned bytesReadNow; 00899 struct sockaddr_in fromAddr; 00900 unsigned char* toPosn = (unsigned char*)(responseBuffer+bytesRead); 00901 Boolean readSuccess 00902 = fOurSocket->handleRead(toPosn, responseBufferSize-bytesRead, 00903 bytesReadNow, fromAddr); 00904 if (!readSuccess || bytesReadNow == 0) { 00905 envir().setResultMsg("SIP response was truncated"); 00906 break; 00907 } 00908 bytesRead += bytesReadNow; 00909 00910 // Check whether we have "\r\n\r\n": 00911 char* lastToCheck = responseBuffer+bytesRead-4; 00912 if (lastToCheck < responseBuffer) continue; 00913 for (; p <= lastToCheck; ++p) { 00914 if (haveSeenNonCRLF) { 00915 if (*p == '\r' && *(p+1) == '\n' && 00916 *(p+2) == '\r' && *(p+3) == '\n') { 00917 responseBuffer[bytesRead] = '\0'; 00918 00919 // Before returning, trim any \r or \n from the start: 00920 while (*responseBuffer == '\r' || *responseBuffer == '\n') { 00921 ++responseBuffer; 00922 --bytesRead; 00923 } 00924 return bytesRead; 00925 } 00926 } else { 00927 if (*p != '\r' && *p != '\n') { 00928 haveSeenNonCRLF = True; 00929 } 00930 } 00931 } 00932 } 00933 00934 return 0; 00935 }
| Boolean SIPClient::parseResponseCode | ( | char const * | line, | |
| unsigned & | responseCode | |||
| ) | [private] |
Definition at line 937 of file SIPClient.cpp.
References Medium::envir(), False, UsageEnvironment::setResultMsg(), and True.
Referenced by getResponseCode().
00938 { 00939 if (sscanf(line, "%*s%u", &responseCode) != 1) { 00940 envir().setResultMsg("no response code in line: \"", line, "\""); 00941 return False; 00942 } 00943 00944 return True; 00945 }
| Boolean Medium::lookupByName | ( | UsageEnvironment & | env, | |
| char const * | mediumName, | |||
| Medium *& | resultMedium | |||
| ) | [static, inherited] |
Definition at line 65 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().
00066 { 00067 resultMedium = MediaLookupTable::ourMedia(env)->lookup(mediumName); 00068 if (resultMedium == NULL) { 00069 env.setResultMsg("Medium ", mediumName, " does not exist"); 00070 return False; 00071 } 00072 00073 return True; 00074 }
| void Medium::close | ( | UsageEnvironment & | env, | |
| char const * | mediumName | |||
| ) | [static, inherited] |
Definition at line 76 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(), MP3HTTPSource::createNew(), MP3FileSource::createNew(), AVIFileSink::createNew(), AMRAudioRTPSource::createNew(), WAVAudioFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), MediaSubsession::deInitiate(), MediaSubsession::initiate(), MPEG1or2ProgramStreamFileDuration(), MPEG1or2Demux::noteElementaryStreamDeletion(), ByteStreamMultiFileSource::onSourceClosure1(), StreamState::reclaim(), RTSPServer::removeServerMediaSession(), OnDemandServerMediaSubsession::sdpLines(), H264VideoRTPSink::stopPlaying(), subsessionAfterPlaying(), ClientTrickPlayState::updateStateOnScaleChange(), AMRDeinterleaver::~AMRDeinterleaver(), ByteStreamMultiFileSource::~ByteStreamMultiFileSource(), DarwinInjector::~DarwinInjector(), FramedFilter::~FramedFilter(), H264VideoRTPSink::~H264VideoRTPSink(), InputESSourceRecord::~InputESSourceRecord(), MPEG1or2Demux::~MPEG1or2Demux(), MPEG1or2FileServerDemux::~MPEG1or2FileServerDemux(), MPEG2TransportFileServerMediaSubsession::~MPEG2TransportFileServerMediaSubsession(), MPEG2TransportStreamFromPESSource::~MPEG2TransportStreamFromPESSource(), ServerMediaSession::~ServerMediaSession(), and ServerMediaSubsession::~ServerMediaSubsession().
00076 { 00077 MediaLookupTable::ourMedia(env)->remove(name); 00078 }
| void Medium::close | ( | Medium * | medium | ) | [static, inherited] |
Definition at line 80 of file Media.cpp.
References Medium::close(), Medium::envir(), Medium::name(), and NULL.
00080 { 00081 if (medium == NULL) return; 00082 00083 close(medium->envir(), medium->name()); 00084 }
| 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::afterGettingBytes(), MultiFramedRTPSink::afterGettingFrame1(), InputESSourceRecord::afterGettingFrame1(), MPEG2TransportStreamFramer::afterGettingFrame1(), MPEG2IFrameIndexFromTransportStream::afterGettingFrame1(), HTTPSink::afterGettingFrame1(), BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoStreamParser::analyzeVOLHeader(), announceStream(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), Medium::close(), MPEG2IFrameIndexFromTransportStream::compactParseBuffer(), RTSPClient::connectionHandler1(), RTSPClient::connectToServer(), QuickTimeFileSink::continuePlaying(), HTTPSink::continuePlaying(), H264VideoRTPSink::continuePlaying(), AVIFileSink::continuePlaying(), MPEG4VideoFileServerMediaSubsession::createNewRTPSink(), MPEG2TransportFileServerMediaSubsession::createNewRTPSink(), MPEG1or2VideoFileServerMediaSubsession::createNewRTPSink(), MPEG1or2DemuxedServerMediaSubsession::createNewRTPSink(), H263plusVideoFileServerMediaSubsession::createNewRTPSink(), DVVideoFileServerMediaSubsession::createNewRTPSink(), AMRAudioFileServerMediaSubsession::createNewRTPSink(), ADTSAudioFileServerMediaSubsession::createNewRTPSink(), MPEG4VideoFileServerMediaSubsession::createNewStreamSource(), MPEG2TransportFileServerMediaSubsession::createNewStreamSource(), MPEG1or2VideoFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), H263plusVideoFileServerMediaSubsession::createNewStreamSource(), DVVideoFileServerMediaSubsession::createNewStreamSource(), AMRAudioFileServerMediaSubsession::createNewStreamSource(), ADTSAudioFileServerMediaSubsession::createNewStreamSource(), MPEG2IFrameIndexFromTransportStream::deliverIndexRecord(), SegmentQueue::dequeue(), WAVAudioFileSource::doGetNextFrame(), MPEG2IFrameIndexFromTransportStream::doGetNextFrame(), MP3FileSource::doGetNextFrame(), H264FUAFragmenter::doGetNextFrame(), ByteStreamMultiFileSource::doGetNextFrame(), ByteStreamFileSource::doGetNextFrame(), BasicUDPSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), MP3FileSource::doGetNextFrame1(), ADUFromMP3Source::doGetNextFrame1(), doInviteStateMachine(), ByteStreamFileSource::doReadFromFile(), MPEG1or2VideoRTPSink::doSpecialFrameHandling(), MP3ADURTPSink::doSpecialFrameHandling(), H263plusVideoRTPSink::doSpecialFrameHandling(), ByteStreamFileSource::doStopGettingFrames(), BasicUDPSource::doStopGettingFrames(), SegmentQueue::enqueueNewSegment(), StreamParser::ensureValidBytes1(), MediaSubsession::env(), SubsessionIOState::envir(), RTSPServer::RTSPClientSession::envir(), RTSPOverHTTPServer::HTTPClientConnection::envir(), RTPInterface::envir(), AVISubsessionIOState::envir(), ServerMediaSession::generateSDPDescription(), RTPSource::getAttributes(), MP3FileSource::getAttributes(), MP3ADUTranscoder::getAttributes(), MediaSource::getAttributes(), MPEG4VideoFileServerMediaSubsession::getAuxSDPLine(), getMPEG1or2TimeCode(), FramedSource::getNextFrame(), getOptions(), DVVideoStreamFramer::getProfile(), getResponse(), getResponseCode(), getSDPDescription(), OnDemandServerMediaSubsession::getStreamParameters(), RTSPClient::handleGET_PARAMETERResponse(), RTSPClient::handleIncomingRequest(), RTSPClient::handlePLAYResponse(), RTSPClient::handleRequestError(), RTSPClient::handleResponseBytes(), RTSPClient::handleSETUPResponse(), RTSPServer::incomingConnectionHandler1(), RTSPOverHTTPServer::incomingConnectionHandler1(), RTSPClient::incomingDataHandler1(), RTCPInstance::incomingReportHandler1(), MP3FileSource::initializeStream(), MediaSession::initializeWithSDP(), MediaSession::initiateByMediaType(), invite1(), DynamicRTSPServer::lookupServerMediaSession(), MPEG4GenericRTPSource::MPEG4GenericRTPSource(), MPEG1or2FileServerDemux::newElementaryStream(), MPEG1or2Demux::newElementaryStream(), MPEG4GenericBufferedPacket::nextEnclosedFrameSize(), AMRBufferedPacket::nextEnclosedFrameSize(), RTSPClient::openConnection(), MPEG2TransportStreamIndexFile::openFid(), MPEG2IFrameIndexFromTransportStream::parseFrame(), AC3AudioStreamParser::parseFrame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), parseResponseCode(), MediaSession::parseSDPLine(), MPEG1or2VideoStreamParser::parseSlice(), MPEGProgramStreamParser::parseSystemHeader(), MPEG4VideoStreamParser::parseVideoObjectLayer(), MPEG4VideoStreamParser::parseVideoObjectPlane(), MPEG4VideoStreamParser::parseVisualObject(), AC3AudioRTPSource::processSpecialHeader(), processURL(), AC3AudioStreamParser::readAndSaveAFrame(), MPEG1or2Demux::registerReadInterest(), RTCPInstance::reschedule(), RTSPClient::resendCommand(), RTSPClient::resetTCPSockets(), RTSPClient::responseHandlerForHTTP_GET1(), RTSPServer::rtspURLPrefix(), RTCPInstance::schedule(), OnDemandServerMediaSubsession::sdpLines(), sendACK(), sendBYE(), sendINVITE(), MultiFramedRTPSink::sendPacketIfNecessary(), sendRequest(), RTSPClient::sendRequest(), DarwinInjector::setDestination(), RTSPClient::setupHTTPTunneling1(), QuickTimeFileSink::setWord(), AVIFileSink::setWord(), QuickTimeFileSink::setWord64(), SIPClient(), AMRAudioRTPSink::sourceIsCompatibleWithUs(), QuickTimeFileSink::startPlaying(), StreamState::startPlaying(), MediaSink::startPlaying(), AVIFileSink::startPlaying(), startPlayingSession(), PassiveServerMediaSubsession::startStream(), MediaSink::stopPlaying(), tearDownSession(), timerAHandler(), timerBHandler(), timerDHandler(), ClientTrickPlayState::updateStateOnScaleChange(), MPEG2TransportStreamFramer::updateTSPacketDurationEstimate(), BasicUDPSource::~BasicUDPSource(), ByteStreamFileSource::~ByteStreamFileSource(), RTSPOverHTTPServer::HTTPClientConnection::~HTTPClientConnection(), and RTSPServer::~RTSPServer().
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 86 of file Media.cpp.
References False.
Referenced by MediaSource::lookupByName().
00086 { 00087 return False; // default implementation 00088 }
| Boolean Medium::isSink | ( | ) | const [virtual, inherited] |
| Boolean Medium::isRTCPInstance | ( | ) | const [virtual, inherited] |
Reimplemented in RTCPInstance.
Definition at line 94 of file Media.cpp.
References False.
Referenced by RTCPInstance::lookupByName().
00094 { 00095 return False; // default implementation 00096 }
| Boolean Medium::isRTSPClient | ( | ) | const [virtual, inherited] |
Reimplemented in RTSPClient.
Definition at line 98 of file Media.cpp.
References False.
Referenced by RTSPClient::lookupByName().
00098 { 00099 return False; // default implementation 00100 }
| Boolean Medium::isRTSPServer | ( | ) | const [virtual, inherited] |
Reimplemented in RTSPServer.
Definition at line 102 of file Media.cpp.
References False.
Referenced by RTSPServer::lookupByName().
00102 { 00103 return False; // default implementation 00104 }
| Boolean Medium::isMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in MediaSession.
Definition at line 106 of file Media.cpp.
References False.
Referenced by MediaSession::lookupByName().
00106 { 00107 return False; // default implementation 00108 }
| Boolean Medium::isServerMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in ServerMediaSession.
Definition at line 110 of file Media.cpp.
References False.
Referenced by ServerMediaSession::lookupByName().
00110 { 00111 return False; // default implementation 00112 }
| Boolean Medium::isDarwinInjector | ( | ) | const [virtual, inherited] |
Reimplemented in DarwinInjector.
Definition at line 114 of file Media.cpp.
References False.
Referenced by DarwinInjector::lookupByName().
00114 { 00115 return False; // default implementation 00116 }
| TaskToken& Medium::nextTask | ( | ) | [inline, protected, inherited] |
Definition at line 77 of file Media.hh.
References Medium::fNextTask.
Referenced by BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), WAVAudioFileSource::doGetNextFrame(), MP3FileSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), ByteStreamFileSource::doReadFromFile(), RTCPInstance::reschedule(), RTCPInstance::schedule(), MultiFramedRTPSink::sendPacketIfNecessary(), and MediaSink::stopPlaying().
00077 { 00078 return fNextTask; 00079 }
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