SIPClient Class Reference

#include <SIPClient.hh>

Inheritance diagram for SIPClient:

Inheritance graph
[legend]
Collaboration diagram for SIPClient:

Collaboration graph
[legend]

Public Member Functions

void setProxyServer (unsigned proxyServerAddress, portNumBits proxyServerPortNum)
void setClientStartPortNum (portNumBits clientStartPortNum)
char * invite (char const *url, Authenticator *authenticator=NULL)
char * inviteWithPassword (char const *url, char const *username, char const *password)
Boolean sendACK ()
Boolean sendBYE ()
unsigned inviteStatus () const
UsageEnvironmentenvir () 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 SIPClientcreateNew (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 ()
TaskTokennextTask ()

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
GroupsockfOurSocket
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
AuthenticatorfWorkingAuthenticator
inviteClientState fInviteClientState
char fEventLoopStopFlag
unsigned fInviteStatusCode

Detailed Description

Definition at line 37 of file SIPClient.hh.


Constructor & Destructor Documentation

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 }


Member Function Documentation

SIPClient * SIPClient::createNew ( UsageEnvironment env,
unsigned char  desiredAudioRTPPayloadFormat,
char const *  mimeSubtype = NULL,
int  verbosityLevel = 0,
char const *  applicationName = NULL 
) [static]

Definition at line 33 of file SIPClient.cpp.

References env.

Referenced by createClient().

00036                                                              {
00037   return new SIPClient(env, desiredAudioRTPPayloadFormat, mimeSubtype,
00038                        verbosityLevel, applicationName);
00039 }

void SIPClient::setProxyServer ( unsigned  proxyServerAddress,
portNumBits  proxyServerPortNum 
)

Definition at line 145 of file SIPClient.cpp.

References Groupsock::changeDestinationParameters(), fOurSocket, fServerAddress, fServerPortNum, and NULL.

Referenced by getSDPDescriptionFromURL().

00146                                                                {
00147   fServerAddress.s_addr = proxyServerAddress;
00148   fServerPortNum = proxyServerPortNum;
00149   if (fOurSocket != NULL) {
00150     fOurSocket->changeDestinationParameters(fServerAddress,
00151                                             fServerPortNum, 255);
00152   }
00153 }

void SIPClient::setClientStartPortNum ( portNumBits  clientStartPortNum  )  [inline]

Definition at line 48 of file SIPClient.hh.

References fClientStartPortNum.

Referenced by getSDPDescriptionFromURL().

00048                                                              {
00049     fClientStartPortNum = clientStartPortNum;
00050   }

char * SIPClient::invite ( char const *  url,
Authenticator authenticator = NULL 
)

Definition at line 169 of file SIPClient.cpp.

References fCallId, fFromTag, fInviteStatusCode, fURL, fURLSize, invite1(), inviteWithPassword(), NULL, our_random(), parseSIPURLUsernamePassword(), password, processURL(), strDup(), and username.

Referenced by getSDPDescriptionFromURL(), and inviteWithPassword().

00169                                                                      {
00170   // First, check whether "url" contains a username:password to be used:
00171   fInviteStatusCode = 0;
00172   char* username; char* password;
00173   if (authenticator == NULL
00174       && parseSIPURLUsernamePassword(url, username, password)) {
00175     char* result = inviteWithPassword(url, username, password);
00176     delete[] username; delete[] password; // they were dynamically allocated
00177     return result;
00178   }
00179 
00180   if (!processURL(url)) return NULL;
00181 
00182   delete[] (char*)fURL; fURL = strDup(url);
00183   fURLSize = strlen(fURL);
00184 
00185   fCallId = our_random();
00186   fFromTag = our_random();
00187 
00188   return invite1(authenticator);
00189 }

char * SIPClient::inviteWithPassword ( char const *  url,
char const *  username,
char const *  password 
)

Definition at line 606 of file SIPClient.cpp.

References fUserName, fUserNameSize, fValidAuthenticator, invite(), invite1(), Authenticator::nonce(), NULL, Authenticator::realm(), Authenticator::setUsernameAndPassword(), and strDup().

Referenced by getSDPDescriptionFromURL(), and invite().

00607                                                           {
00608   delete[] (char*)fUserName; fUserName = strDup(username);
00609   fUserNameSize = strlen(fUserName);
00610 
00611   Authenticator authenticator;
00612   authenticator.setUsernameAndPassword(username, password);
00613   char* inviteResult = invite(url, &authenticator);
00614   if (inviteResult != NULL) {
00615     // We are already authorized
00616     return inviteResult;
00617   }
00618 
00619   // The "realm" and "nonce" fields should have been filled in:
00620   if (authenticator.realm() == NULL || authenticator.nonce() == NULL) {
00621     // We haven't been given enough information to try again, so fail:
00622     return NULL;
00623   }
00624 
00625   // Try again (but with the same CallId):
00626   inviteResult = invite1(&authenticator);
00627   if (inviteResult != NULL) {
00628     // The authenticator worked, so use it in future requests:
00629     fValidAuthenticator = authenticator;
00630   }
00631 
00632   return inviteResult;
00633 }

Boolean SIPClient::sendACK (  ) 

Definition at line 635 of file SIPClient.cpp.

References Medium::envir(), False, fCallId, fCSeq, fFromTag, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, NULL, sendRequest(), UsageEnvironment::setResultErrMsg(), and True.

Referenced by clientStartPlayingSession(), and doInviteStateMachine().

00635                            {
00636   char* cmd = NULL;
00637   do {
00638     char* const cmdFmt =
00639       "ACK %s SIP/2.0\r\n"
00640       "From: %s <sip:%s@%s>;tag=%u\r\n"
00641       "Via: SIP/2.0/UDP %s:%u\r\n"
00642       "To: %s;tag=%s\r\n"
00643       "Call-ID: %u@%s\r\n"
00644       "CSeq: %d ACK\r\n"
00645       "Content-length: 0\r\n\r\n";
00646     unsigned cmdSize = strlen(cmdFmt)
00647       + fURLSize
00648       + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */
00649       + fOurAddressStrSize + 5 /* max port len */
00650       + fURLSize + fToTagStrSize
00651       + 20 + fOurAddressStrSize
00652       + 20;
00653     cmd = new char[cmdSize];
00654     sprintf(cmd, cmdFmt,
00655             fURL,
00656             fUserName, fUserName, fOurAddressStr, fFromTag,
00657             fOurAddressStr, fOurPortNum,
00658             fURL, fToTagStr,
00659             fCallId, fOurAddressStr,
00660             fCSeq /* note: it's the same as before; not incremented */);
00661 
00662     if (!sendRequest(cmd, strlen(cmd))) {
00663       envir().setResultErrMsg("ACK send() failed: ");
00664       break;
00665     }
00666 
00667     delete[] cmd;
00668     return True;
00669   } while (0);
00670 
00671   delete[] cmd;
00672   return False;
00673 }

Boolean SIPClient::sendBYE (  ) 

Definition at line 675 of file SIPClient.cpp.

References Medium::envir(), False, fCallId, fCSeq, fFromTag, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, NULL, sendRequest(), UsageEnvironment::setResultErrMsg(), and True.

Referenced by clientTearDownSession().

00675                            {
00676   // NOTE: This should really be retransmitted, for reliability #####
00677   char* cmd = NULL;
00678   do {
00679     char* const cmdFmt =
00680       "BYE %s SIP/2.0\r\n"
00681       "From: %s <sip:%s@%s>;tag=%u\r\n"
00682       "Via: SIP/2.0/UDP %s:%u\r\n"
00683       "To: %s;tag=%s\r\n"
00684       "Call-ID: %u@%s\r\n"
00685       "CSeq: %d ACK\r\n"
00686       "Content-length: 0\r\n\r\n";
00687     unsigned cmdSize = strlen(cmdFmt)
00688       + fURLSize
00689       + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */
00690       + fOurAddressStrSize + 5 /* max port len */
00691       + fURLSize + fToTagStrSize
00692       + 20 + fOurAddressStrSize
00693       + 20;
00694     cmd = new char[cmdSize];
00695     sprintf(cmd, cmdFmt,
00696             fURL,
00697             fUserName, fUserName, fOurAddressStr, fFromTag,
00698             fOurAddressStr, fOurPortNum,
00699             fURL, fToTagStr,
00700             fCallId, fOurAddressStr,
00701             ++fCSeq);
00702 
00703     if (!sendRequest(cmd, strlen(cmd))) {
00704       envir().setResultErrMsg("BYE send() failed: ");
00705       break;
00706     }
00707 
00708     delete[] cmd;
00709     return True;
00710   } while (0);
00711 
00712   delete[] cmd;
00713   return False;
00714 }

Boolean SIPClient::parseSIPURL ( UsageEnvironment env,
char const *  url,
NetAddress address,
portNumBits portNum 
) [static]

Definition at line 738 of file SIPClient.cpp.

References _strncasecmp, env, False, NetAddressList::firstAddress(), NetAddressList::numAddresses(), UsageEnvironment::setResultMsg(), and True.

Referenced by processURL().

00740                                                      {
00741   do {
00742     // Parse the URL as "sip:<username>@<address>:<port>/<etc>"
00743     // (with ":<port>" and "/<etc>" optional)
00744     // Also, skip over any "<username>[:<password>]@" preceding <address>
00745     char const* prefix = "sip:";
00746     unsigned const prefixLength = 4;
00747     if (_strncasecmp(url, prefix, prefixLength) != 0) {
00748       env.setResultMsg("URL is not of the form \"", prefix, "\"");
00749       break;
00750     }
00751 
00752     unsigned const parseBufferSize = 100;
00753     char parseBuffer[parseBufferSize];
00754     unsigned addressStartIndex = prefixLength;
00755     while (url[addressStartIndex] != '\0'
00756            && url[addressStartIndex++] != '@') {}
00757     char const* from = &url[addressStartIndex];
00758 
00759     // Skip over any "<username>[:<password>]@"
00760     char const* from1 = from;
00761     while (*from1 != '\0' && *from1 != '/') {
00762       if (*from1 == '@') {
00763         from = ++from1;
00764         break;
00765       }
00766       ++from1;
00767     }
00768 
00769     char* to = &parseBuffer[0];
00770     unsigned i;
00771     for (i = 0; i < parseBufferSize; ++i) {
00772       if (*from == '\0' || *from == ':' || *from == '/') {
00773         // We've completed parsing the address
00774         *to = '\0';
00775         break;
00776       }
00777       *to++ = *from++;
00778     }
00779     if (i == parseBufferSize) {
00780       env.setResultMsg("URL is too long");
00781       break;
00782     }
00783 
00784     NetAddressList addresses(parseBuffer);
00785     if (addresses.numAddresses() == 0) {
00786       env.setResultMsg("Failed to find network address for \"",
00787                            parseBuffer, "\"");
00788       break;
00789     }
00790     address = *(addresses.firstAddress());
00791 
00792     portNum = 5060; // default value
00793     char nextChar = *from;
00794     if (nextChar == ':') {
00795       int portNumInt;
00796       if (sscanf(++from, "%d", &portNumInt) != 1) {
00797         env.setResultMsg("No port number follows ':'");
00798         break;
00799       }
00800       if (portNumInt < 1 || portNumInt > 65535) {
00801         env.setResultMsg("Bad port number");
00802         break;
00803       }
00804       portNum = (portNumBits)portNumInt;
00805     }
00806 
00807     return True;
00808   } while (0);
00809 
00810   return False;
00811 }

Boolean SIPClient::parseSIPURLUsernamePassword ( char const *  url,
char *&  username,
char *&  password 
) [static]

Definition at line 813 of file SIPClient.cpp.

References _strncasecmp, False, NULL, strDup(), and True.

Referenced by invite().

00815                                                                 {
00816   username = password = NULL; // by default
00817   do {
00818     // Parse the URL as "sip:<username>[:<password>]@<whatever>"
00819     char const* prefix = "sip:";
00820     unsigned const prefixLength = 4;
00821     if (_strncasecmp(url, prefix, prefixLength) != 0) break;
00822 
00823     // Look for the ':' and '@':
00824     unsigned usernameIndex = prefixLength;
00825     unsigned colonIndex = 0, atIndex = 0;
00826     for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) {
00827       if (url[i] == ':' && colonIndex == 0) {
00828         colonIndex = i;
00829       } else if (url[i] == '@') {
00830         atIndex = i;
00831         break; // we're done
00832       }
00833     }
00834     if (atIndex == 0) break; // no '@' found
00835 
00836     char* urlCopy = strDup(url);
00837     urlCopy[atIndex] = '\0';
00838     if (colonIndex > 0) {
00839       urlCopy[colonIndex] = '\0';
00840       password = strDup(&urlCopy[colonIndex+1]);
00841     } else {
00842       password = strDup("");
00843     }
00844     username = strDup(&urlCopy[usernameIndex]);
00845     delete[] urlCopy;
00846 
00847     return True;
00848   } while (0);
00849 
00850   return False;
00851 }

unsigned SIPClient::inviteStatus (  )  const [inline]

Definition at line 71 of file SIPClient.hh.

References fInviteStatusCode.

Referenced by getSDPDescriptionFromURL().

00071 { return fInviteStatusCode; }

void SIPClient::reset (  )  [private]

Definition at line 129 of file SIPClient.cpp.

References fApplicationName, fInviteCmd, fInviteCmdSize, fInviteSDPDescription, fServerAddress, fServerPortNum, fToTagStr, fToTagStrSize, fURL, fURLSize, fUserName, fUserNameSize, fValidAuthenticator, fWorkingAuthenticator, NULL, Authenticator::reset(), and strDup().

Referenced by SIPClient(), and ~SIPClient().

00129                       {
00130   fWorkingAuthenticator = NULL;
00131   delete[] fInviteCmd; fInviteCmd = NULL; fInviteCmdSize = 0;
00132   delete[] fInviteSDPDescription; fInviteSDPDescription = NULL;
00133 
00134   delete[] (char*)fUserName; fUserName = strDup(fApplicationName);
00135   fUserNameSize = strlen(fUserName);
00136 
00137   fValidAuthenticator.reset();
00138 
00139   delete[] (char*)fToTagStr; fToTagStr = NULL; fToTagStrSize = 0;
00140   fServerPortNum = 0;
00141   fServerAddress.s_addr = 0;
00142   delete[] (char*)fURL; fURL = NULL; fURLSize = 0;
00143 }

char * SIPClient::invite1 ( Authenticator authenticator  )  [private]

Definition at line 191 of file SIPClient.cpp.

References Calling, createAuthenticatorString(), TaskScheduler::doEventLoop(), Medium::envir(), fApplicationName, fApplicationNameSize, fCallId, fClientStartPortNum, fCSeq, fDesiredAudioRTPPayloadFormat, fEventLoopStopFlag, fFromTag, fInviteClientState, fInviteCmd, fInviteCmdSize, fInviteSDPDescription, fInviteStatusCode, fMIMESubtype, fMIMESubtypeSize, fOurAddressStr, fOurAddressStrSize, fOurPortNum, fOurSocket, fT1, fTimerA, fTimerACount, fTimerALen, fTimerB, fTimerD, fURL, fURLSize, fUserAgentHeaderStr, fUserAgentHeaderStrSize, fUserName, fUserNameSize, fValidAuthenticator, fWorkingAuthenticator, inviteResponseHandler(), NULL, Authenticator::reset(), TaskScheduler::scheduleDelayedTask(), sendINVITE(), Socket::socketNum(), strDup(), UsageEnvironment::taskScheduler(), timerAHandler(), timerBHandler(), TaskScheduler::turnOffBackgroundReadHandling(), TaskScheduler::turnOnBackgroundReadHandling(), and TaskScheduler::unscheduleDelayedTask().

Referenced by invite(), and inviteWithPassword().

00191                                                      {
00192   do {
00193     // Send the INVITE command:
00194 
00195     // First, construct an authenticator string:
00196     fValidAuthenticator.reset();
00197     fWorkingAuthenticator = authenticator;
00198     char* authenticatorStr
00199       = createAuthenticatorString(fWorkingAuthenticator, "INVITE", fURL);
00200 
00201     // Then, construct the SDP description to be sent in the INVITE:
00202     char* rtpmapLine;
00203     unsigned rtpmapLineSize;
00204     if (fMIMESubtypeSize > 0) {
00205       char* const rtpmapFmt =
00206         "a=rtpmap:%u %s/8000\r\n";
00207       unsigned rtpmapFmtSize = strlen(rtpmapFmt)
00208         + 3 /* max char len */ + fMIMESubtypeSize;
00209       rtpmapLine = new char[rtpmapFmtSize];
00210       sprintf(rtpmapLine, rtpmapFmt,
00211               fDesiredAudioRTPPayloadFormat, fMIMESubtype);
00212       rtpmapLineSize = strlen(rtpmapLine);
00213     } else {
00214       // Static payload type => no "a=rtpmap:" line
00215       rtpmapLine = strDup("");
00216       rtpmapLineSize = 0;
00217     }
00218     char* const inviteSDPFmt =
00219       "v=0\r\n"
00220       "o=- %u %u IN IP4 %s\r\n"
00221       "s=%s session\r\n"
00222       "c=IN IP4 %s\r\n"
00223       "t=0 0\r\n"
00224       "m=audio %u RTP/AVP %u\r\n"
00225       "%s";
00226     unsigned inviteSDPFmtSize = strlen(inviteSDPFmt)
00227       + 20 /* max int len */ + 20 + fOurAddressStrSize
00228       + fApplicationNameSize
00229       + fOurAddressStrSize
00230       + 5 /* max short len */ + 3 /* max char len */
00231       + rtpmapLineSize;
00232     delete[] fInviteSDPDescription;
00233     fInviteSDPDescription = new char[inviteSDPFmtSize];
00234     sprintf(fInviteSDPDescription, inviteSDPFmt,
00235             fCallId, fCSeq, fOurAddressStr,
00236             fApplicationName,
00237             fOurAddressStr,
00238             fClientStartPortNum, fDesiredAudioRTPPayloadFormat,
00239             rtpmapLine);
00240     unsigned inviteSDPSize = strlen(fInviteSDPDescription);
00241     delete[] rtpmapLine;
00242 
00243     char* const cmdFmt =
00244       "INVITE %s SIP/2.0\r\n"
00245       "From: %s <sip:%s@%s>;tag=%u\r\n"
00246       "Via: SIP/2.0/UDP %s:%u\r\n"
00247       "To: %s\r\n"
00248       "Contact: sip:%s@%s:%u\r\n"
00249       "Call-ID: %u@%s\r\n"
00250       "CSeq: %d INVITE\r\n"
00251       "Content-Type: application/sdp\r\n"
00252       "%s" /* Proxy-Authorization: line (if any) */
00253       "%s" /* User-Agent: line */
00254       "Content-length: %d\r\n\r\n"
00255       "%s";
00256     unsigned inviteCmdSize = strlen(cmdFmt)
00257       + fURLSize
00258       + 2*fUserNameSize + fOurAddressStrSize + 20 /* max int len */
00259       + fOurAddressStrSize + 5 /* max port len */
00260       + fURLSize
00261       + fUserNameSize + fOurAddressStrSize + 5
00262       + 20 + fOurAddressStrSize
00263       + 20
00264       + strlen(authenticatorStr)
00265       + fUserAgentHeaderStrSize
00266       + 20
00267       + inviteSDPSize;
00268     delete[] fInviteCmd; fInviteCmd = new char[inviteCmdSize];
00269     sprintf(fInviteCmd, cmdFmt,
00270             fURL,
00271             fUserName, fUserName, fOurAddressStr, fFromTag,
00272             fOurAddressStr, fOurPortNum,
00273             fURL,
00274             fUserName, fOurAddressStr, fOurPortNum,
00275             fCallId, fOurAddressStr,
00276             ++fCSeq,
00277             authenticatorStr,
00278             fUserAgentHeaderStr,
00279             inviteSDPSize,
00280             fInviteSDPDescription);
00281     fInviteCmdSize = strlen(fInviteCmd);
00282     delete[] authenticatorStr;
00283 
00284     // Before sending the "INVITE", arrange to handle any response packets,
00285     // and set up timers:
00286     fInviteClientState = Calling;
00287     fEventLoopStopFlag = 0;
00288     TaskScheduler& sched = envir().taskScheduler(); // abbrev.
00289     sched.turnOnBackgroundReadHandling(fOurSocket->socketNum(),
00290                                        &inviteResponseHandler, this);
00291     fTimerALen = 1*fT1; // initially
00292     fTimerACount = 0; // initially
00293     fTimerA = sched.scheduleDelayedTask(fTimerALen, timerAHandler, this);
00294     fTimerB = sched.scheduleDelayedTask(64*fT1, timerBHandler, this);
00295     fTimerD = NULL; // for now
00296 
00297     if (!sendINVITE()) break;
00298 
00299     // Enter the event loop, to handle response packets, and timeouts:
00300     envir().taskScheduler().doEventLoop(&fEventLoopStopFlag);
00301 
00302     // We're finished with this "INVITE".
00303     // Turn off response handling and timers:
00304     sched.turnOffBackgroundReadHandling(fOurSocket->socketNum());
00305     sched.unscheduleDelayedTask(fTimerA);
00306     sched.unscheduleDelayedTask(fTimerB);
00307     sched.unscheduleDelayedTask(fTimerD);
00308 
00309     // NOTE: We return the SDP description that we used in the "INVITE",
00310     // not the one that we got from the server.
00311     // ##### Later: match the codecs in the response (offer, answer) #####
00312     if (fInviteSDPDescription != NULL) {
00313       return strDup(fInviteSDPDescription);
00314     }
00315   } while (0);
00316 
00317   fInviteStatusCode = 2;
00318   return NULL;
00319 }

Boolean SIPClient::processURL ( char const *  url  )  [private]

Definition at line 716 of file SIPClient.cpp.

References Groupsock::changeDestinationParameters(), N