reSIProcate/stack  9694
Classes | Public Types | Static Public Member Functions | Static Public Attributes | Static Private Attributes
resip::Helper Class Reference

An aggregation of useful static functions. More...

#include <Helper.hxx>

Collaboration diagram for resip::Helper:
Collaboration graph
[legend]

List of all members.

Classes

struct  ContentsSecAttrs
class  NonceHelperPtr

Public Types

enum  AuthResult { Failed = 1, Authenticated, Expired, BadlyFormed }
enum  FailureMessageEffect {
  DialogTermination, TransactionTermination, UsageTermination, RetryAfter,
  OptionalRetryAfter, ApplicationDependant
}

Static Public Member Functions

template<typename T >
static T aBitSmallerThan (T secs)
 Used by Registration, Publication and Subscription refreshes, to calculate the time at which a refresh should be performed (which is some time, that is a bit smaller than the Expiration interval).
static void integer2hex (char *_d, unsigned int _s, bool _l=true)
 Converts an interger in a character string containing the hexidecimal representation of the integer.
static unsigned int hex2integer (const char *_s)
 Converts a character string containing a hexidecimal value into an unsigned int.
static int jitterValue (int input, int lowerPercentage, int upperPercentage, int minimum=0)
 Used to jitter the expires in a SUBSCRIBE or REGISTER expires header.
static SipMessagemakeInvite (const NameAddr &target, const NameAddr &from)
 Make an invite request - Empty Contact and Via is added and will be populated by the stack when sent.
static SipMessagemakeInvite (const NameAddr &target, const NameAddr &from, const NameAddr &contact)
 Make an invite request using a overridden contact header - Empty Via is added and will be populated by the stack when sent.
static void makeResponse (SipMessage &response, const SipMessage &request, int responseCode, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
 Make a response to a provided request.
static void makeResponse (SipMessage &response, const SipMessage &request, int responseCode, const NameAddr &myContact, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
 Make a response to a provided request with an overridden Contact.
static SipMessagemakeResponse (const SipMessage &request, int responseCode, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
 Make a new response to a provided request.
static SipMessagemakeResponse (const SipMessage &request, int responseCode, const NameAddr &myContact, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
 Make a new response to a provided request with an overridden Contact.
static void makeRawResponse (Data &rawBuffer, const SipMessage &request, int responseCode, const Data &additionalHeaders=Data::Empty, const Data &body=Data::Empty)
static SipMessagemake405 (const SipMessage &request, const int *allowedMethods=0, int nMethods=-1)
 Make a 405 response to a provided request.
static void getResponseCodeReason (int responseCode, Data &reason)
 Returns the default reason string for a particular response code.
static SipMessagemakeRequest (const NameAddr &target, const NameAddr &from, const NameAddr &contact, MethodTypes method)
 Make a new request with a overridden Contact.
static SipMessagemakeRequest (const NameAddr &target, const NameAddr &from, MethodTypes method)
 Make a new request.
static SipMessagemakeCancel (const SipMessage &request)
 Make a new Cancel request for the specified request.
static SipMessagemakeRegister (const NameAddr &to, const NameAddr &from, const NameAddr &contact)
 Create a Register request with an overriden Contact. See makeRequest.
static SipMessagemakeRegister (const NameAddr &to, const NameAddr &from)
 Create a Register request with an empty Contact. See makeRequest.
static SipMessagemakeRegister (const NameAddr &to, const Data &transport, const NameAddr &contact)
 Create a Register request with an overriden Contact, transport is added to Request URI. See makeRequest.
static SipMessagemakeRegister (const NameAddr &to, const Data &transport)
 Create a Register request with an empty Contact, transport is added to Request URI. See makeRequest.
static SipMessagemakeSubscribe (const NameAddr &target, const NameAddr &from, const NameAddr &contact)
 Create a Subscribe request with an overriden Contact. See makeRequest.
static SipMessagemakeSubscribe (const NameAddr &target, const NameAddr &from)
 Create a Subscribe request with an empty Contact. See makeRequest.
static SipMessagemakeMessage (const NameAddr &target, const NameAddr &from, const NameAddr &contact)
 Create a Message request with an overriden Contact. See makeRequest.
static SipMessagemakeMessage (const NameAddr &target, const NameAddr &from)
 Create a Message request with an empty Contact. See makeRequest.
static SipMessagemakePublish (const NameAddr &target, const NameAddr &from, const NameAddr &contact)
 Create a Publish request with an overriden Contact. See makeRequest.
static SipMessagemakePublish (const NameAddr &target, const NameAddr &from)
 Create a Publish request with an empty Contact. See makeRequest.
static SipMessagemakeFailureAck (const SipMessage &request, const SipMessage &response)
 This interface should be used by the stack (TransactionState) to create an AckMsg to a failure response.
static Data computeUniqueBranch ()
 Creates and returns a unique branch parameter.
static Data computeProxyBranch (const SipMessage &request)
static Data computeCallId ()
static Data computeTag (int numBytes)
static AuthResult authenticateRequest (const SipMessage &request, const Data &realm, const Data &password, int expiresDelta=0)
static AuthResult authenticateRequestWithA1 (const SipMessage &request, const Data &realm, const Data &hA1, int expiresDelta=0)
static std::pair< AuthResult,
Data
advancedAuthenticateRequest (const SipMessage &request, const Data &realm, const Data &a1, int expiresDelta=0, bool proxyAuthorization=true)
static SipMessagemakeProxyChallenge (const SipMessage &request, const Data &realm, bool useAuth=true, bool stale=false)
static SipMessagemakeWWWChallenge (const SipMessage &request, const Data &realm, bool useAuth=true, bool stale=false)
static SipMessagemakeChallenge (const SipMessage &request, const Data &realm, bool useAuth=true, bool stale=false, bool proxy=false)
static Data qopOption (const Auth &challenge)
static void updateNonceCount (unsigned int &nonceCount, Data &nonceCountString)
static bool algorithmAndQopSupported (const Auth &challenge)
static SipMessageaddAuthorization (SipMessage &request, const SipMessage &challenge, const Data &username, const Data &password, const Data &cnonce, unsigned int &nonceCount)
static Auth makeChallengeResponseAuth (const SipMessage &request, const Data &username, const Data &password, const Auth &challenge, const Data &cnonce, unsigned int &nonceCount, Data &nonceCountString)
static void makeChallengeResponseAuth (const SipMessage &request, const Data &username, const Data &password, const Auth &challenge, const Data &cnonce, const Data &authQop, const Data &nonceCountString, Auth &auth)
static Auth makeChallengeResponseAuthWithA1 (const SipMessage &request, const Data &username, const Data &passwordHashA1, const Auth &challenge, const Data &cnonce, unsigned int &nonceCount, Data &nonceCountString)
static void makeChallengeResponseAuthWithA1 (const SipMessage &request, const Data &username, const Data &passwordHashA1, const Auth &challenge, const Data &cnonce, const Data &authQop, const Data &nonceCountString, Auth &auth)
static Data makeResponseMD5WithA1 (const Data &a1, const Data &method, const Data &digestUri, const Data &nonce, const Data &qop=Data::Empty, const Data &cnonce=Data::Empty, const Data &cnonceCount=Data::Empty, const Contents *entityBody=0)
static Data makeResponseMD5 (const Data &username, const Data &password, const Data &realm, const Data &method, const Data &digestUri, const Data &nonce, const Data &qop=Data::Empty, const Data &cnonce=Data::Empty, const Data &cnonceCount=Data::Empty, const Contents *entityBody=0)
static void setNonceHelper (NonceHelper *nonceHelper)
 Note: Helper assumes control of NonceHelper object and will delete when global scope is cleaned up.
static NonceHelpergetNonceHelper ()
static Data makeNonce (const SipMessage &request, const Data &timestamp)
static Uri makeUri (const Data &aor, const Data &scheme=Symbols::DefaultSipScheme)
static void processStrictRoute (SipMessage &request)
static int getPortForReply (SipMessage &request)
static void massageRoute (const SipMessage &request, NameAddr &route)
static Uri fromAor (const Data &aor, const Data &scheme=Symbols::DefaultSipScheme)
static bool validateMessage (const SipMessage &message, resip::Data *reason=0)
static Data gruuUserPart (const Data &instanceId, const Data &aor, const Data &key)
static std::pair< Data, DatafromGruuUserPart (const Data &gruuUserPart, const Data &key)
static ContentsSecAttrs extractFromPkcs7 (const SipMessage &message, Security &security)
static FailureMessageEffect determineFailureMessageEffect (const SipMessage &response)
static std::auto_ptr< SdpContentsgetSdp (Contents *tree)
static bool isClientBehindNAT (const SipMessage &request, bool privateToPublicOnly=true)
 Looks at SIP headers and message source for a mismatch to make an assumption that the sender is behind a NAT device.
static Tuple getClientPublicAddress (const SipMessage &request)
 Look at Via headers, and find the first public IP address closest to the sending client.

Static Public Attributes

static const int tagSize = 4
 bytes in to-tag& from-tag, should prob. live somewhere else

Static Private Attributes

static NonceHelperPtr mNonceHelperPtr

Detailed Description

An aggregation of useful static functions.

These are mostly involved with

Definition at line 43 of file Helper.hxx.


Member Enumeration Documentation

Enumerator:
Failed 
Authenticated 
Expired 
BadlyFormed 

Definition at line 397 of file Helper.hxx.

Enumerator:
DialogTermination 
TransactionTermination 
UsageTermination 
RetryAfter 
OptionalRetryAfter 
ApplicationDependant 

Definition at line 540 of file Helper.hxx.


Member Function Documentation

template<typename T >
static T resip::Helper::aBitSmallerThan ( secs) [inline, static]

Used by Registration, Publication and Subscription refreshes, to calculate the time at which a refresh should be performed (which is some time, that is a bit smaller than the Expiration interval).

The recommended calculation from the RFC's is the minimnum of the Exipiration interval less 5 seconds and nine tenths of the exipiration interval.

Definition at line 59 of file Helper.hxx.

References resip::resipMax(), and resip::resipMin().

Referenced by main().

      {
         return resipMax(T(0), resipMin(T(secs-5), T(9*secs/10)));
      }

Here is the call graph for this function:

SipMessage & Helper::addAuthorization ( SipMessage request,
const SipMessage challenge,
const Data username,
const Data password,
const Data cnonce,
unsigned int &  nonceCount 
) [static]

Definition at line 1565 of file Helper.cxx.

References resip::ParserContainer< T >::begin(), resip::Data::Empty, resip::ParserContainer< T >::end(), resip::SipMessage::exists(), resip::SipMessage::header(), and resip::SipMessage::isResponse().

Referenced by resip::TuIM::processRegisterResponse().

{
   Data nonceCountString = Data::Empty;
   
   assert(challenge.isResponse());
   assert(challenge.header(h_StatusLine).responseCode() == 401 ||
          challenge.header(h_StatusLine).responseCode() == 407);

   if (challenge.exists(h_ProxyAuthenticates))
   {
      const ParserContainer<Auth>& auths = challenge.header(h_ProxyAuthenticates);
      for (ParserContainer<Auth>::const_iterator i = auths.begin();
           i != auths.end(); i++)
      {
         request.header(h_ProxyAuthorizations).push_back(makeChallengeResponseAuth(request, username, password, *i, 
                                                                                    cnonce, nonceCount, nonceCountString));
      }
   }
   if (challenge.exists(h_WWWAuthenticates))
   {
      const ParserContainer<Auth>& auths = challenge.header(h_WWWAuthenticates);
      for (ParserContainer<Auth>::const_iterator i = auths.begin();
           i != auths.end(); i++)
      {
         request.header(h_Authorizations).push_back(makeChallengeResponseAuth(request, username, password, *i,
                                                                               cnonce, nonceCount, nonceCountString));
      }
   }
   return request;
}

Here is the call graph for this function:

std::pair< Helper::AuthResult, Data > Helper::advancedAuthenticateRequest ( const SipMessage request,
const Data realm,
const Data a1,
int  expiresDelta = 0,
bool  proxyAuthorization = true 
) [static]

Definition at line 767 of file Helper.cxx.

References resip::Symbols::auth, resip::Symbols::authInt, resip::ParserContainer< T >::begin(), DebugLog, digest, resip::ParserContainer< T >::end(), resip::SipMessage::exists(), resip::SipMessage::getContents(), resip::NonceHelper::Nonce::getCreationTime(), resip::RequestLine::getMethod(), resip::Timer::getTimeSecs(), resip::SipMessage::header(), InfoLog, and resip::isEqualNoCase().

{
   Data username;
   DebugLog(<< "Authenticating: realm=" << realm << " expires=" << expiresDelta);
   //DebugLog(<< request);
   
   const ParserContainer<Auth>* auths = 0;
   if(proxyAuthorization)
   {
      if(request.exists(h_ProxyAuthorizations))
      {
         auths = &request.header(h_ProxyAuthorizations);
      }
   }
   else
   {
      if(request.exists(h_Authorizations))
      {
         auths = &request.header(h_Authorizations);
      }
   }

   if (auths)
   {
      for (ParserContainer<Auth>::const_iterator i = auths->begin(); i != auths->end(); i++)
      {
         if (i->exists(p_realm) && 
             i->exists(p_nonce) &&
             i->exists(p_response) &&
             i->param(p_realm) == realm)
         {
            if(!isEqualNoCase(i->scheme(),digest))
            {
               DebugLog(<< "Scheme must be Digest");
               continue;
            }
            /* ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size());
            if (!pb.eof() && !isdigit(*pb.position()))
            {
               DebugLog(<< "Invalid nonce; expected timestamp.");
               return make_pair(BadlyFormed,username);
            }
            const char* anchor = pb.position();
            pb.skipToChar(Symbols::COLON[0]);

            if (pb.eof())
            {
               DebugLog(<< "Invalid nonce; expected timestamp terminator.");
               return make_pair(BadlyFormed,username);
            }

            Data then;
            pb.data(then, anchor); 
            if (expiresDelta > 0)
            {
               unsigned int now = (unsigned int)(Timer::getTimeMs()/1000);
               if ((unsigned int)then.convertUInt64() + expiresDelta < now)
               {
                  DebugLog(<< "Nonce has expired.");
                  return make_pair(Expired,username);
               }
            } */

            NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce)); 
            if(x_nonce.getCreationTime() == 0) 
               return make_pair(BadlyFormed,username);

            if (expiresDelta > 0)
            {
               UInt64 now = Timer::getTimeSecs();
               if (x_nonce.getCreationTime() + expiresDelta < now)
               {
                  DebugLog(<< "Nonce has expired.");
                  return make_pair(Expired,username);
               }
            }

            Data then(x_nonce.getCreationTime());
            if (i->param(p_nonce) != makeNonce(request, then))
            {
               InfoLog(<< "Not my nonce. expected=" << makeNonce(request, then) 
                       << " received=" << i->param(p_nonce)
                       << " then=" << then);
               
               return make_pair(BadlyFormed,username);
            }
         
            if (i->exists(p_qop))
            {
               if (i->param(p_qop) == Symbols::auth || i->param(p_qop)  == Symbols::authInt)
               {
                  if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc))
                  {
                     if (i->param(p_response) == makeResponseMD5WithA1(a1,
                                                               getMethodName(request.header(h_RequestLine).getMethod()),
                                                               i->param(p_uri),
                                                               i->param(p_nonce),
                                                               i->param(p_qop),
                                                               i->param(p_cnonce),
                                                               i->param(p_nc),
                                                               request.getContents()))
                     {
                        if(i->exists(p_username))
                        {
                           username = i->param(p_username);
                        }
                        return make_pair(Authenticated,username);
                     }
                     else
                     {
                        return make_pair(Failed,username);
                     }
                  }
               }
               else
               {
                  InfoLog (<< "Unsupported qop=" << i->param(p_qop));
                  return make_pair(Failed,username);
               }
            }
            else if(i->exists(p_uri))
            {
               if (i->param(p_response) == makeResponseMD5WithA1(a1,
                                                               getMethodName(request.header(h_RequestLine).getMethod()),
                                                               i->param(p_uri),
                                                               i->param(p_nonce)))
               {
                  if(i->exists(p_username))
                  {
                     username = i->param(p_username);
                  }
                  return make_pair(Authenticated,username);
               }
               else
               {
                  return make_pair(Failed,username);
               }
            }
         }
         else
         {
            return make_pair(BadlyFormed,username);
         }
      }
      return make_pair(BadlyFormed,username);
   }
   DebugLog (<< "No authentication headers. Failing request.");
   return make_pair(Failed,username);
}

Here is the call graph for this function:

bool Helper::algorithmAndQopSupported ( const Auth challenge) [static]

Definition at line 1551 of file Helper.cxx.

References resip::Symbols::auth, resip::Symbols::authInt, resip::Auth::exists(), resip::isEqualNoCase(), and resip::ParserCategory::param().

{
   if ( !(challenge.exists(p_nonce) && challenge.exists(p_realm)))
   {
      return false;
   }
   return ((!challenge.exists(p_algorithm) 
            || isEqualNoCase(challenge.param(p_algorithm), "MD5"))
           && (!challenge.exists(p_qop) 
               || isEqualNoCase(challenge.param(p_qop), Symbols::auth)
               || isEqualNoCase(challenge.param(p_qop), Symbols::authInt)));
}

Here is the call graph for this function:

Helper::AuthResult Helper::authenticateRequest ( const SipMessage request,
const Data realm,
const Data password,
int  expiresDelta = 0 
) [static]

Definition at line 922 of file Helper.cxx.

References resip::ParserContainerBase::append(), resip::Symbols::auth, resip::Symbols::authInt, resip::ParserContainer< T >::begin(), DebugLog, digest, resip::ParserContainerBase::empty(), resip::ParserContainer< T >::end(), resip::SipMessage::exists(), resip::SipMessage::getContents(), resip::NonceHelper::Nonce::getCreationTime(), resip::RequestLine::getMethod(), resip::Timer::getTimeSecs(), resip::SipMessage::header(), InfoLog, and resip::isEqualNoCase().

{
   DebugLog(<< "Authenticating: realm=" << realm << " expires=" << expiresDelta);
   //DebugLog(<< request);

   // !bwc! Somewhat inefficient. Maybe optimize later.
   ParserContainer<Auth> auths;

   if(request.exists(h_ProxyAuthorizations))
   {
      auths.append(request.header(h_ProxyAuthorizations));
   }
   
   if(request.exists(h_Authorizations))
   {
      auths.append(request.header(h_Authorizations));
   }

   if(auths.empty())
   {
      DebugLog (<< "No authentication headers. Failing request.");
      return Failed;
   }

   // ?bwc? Why is const_iterator& operator=(const iterator& rhs)
   // not working properly?
   //ParserContainer<Auth>::const_iterator i = auths.begin();
   
   ParserContainer<Auth>::iterator i = auths.begin();
         
   for (; i != auths.end(); i++)
   {
      if (i->exists(p_realm) && 
          i->exists(p_nonce) &&
          i->exists(p_response) &&
          i->param(p_realm) == realm)
      {
         if(!isEqualNoCase(i->scheme(),digest))
         {
            DebugLog(<< "Scheme must be Digest");
            continue;
         }
         /*
         ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size());
         if (!pb.eof() && !isdigit(*pb.position()))
         {
            DebugLog(<< "Invalid nonce; expected timestamp.");
            return BadlyFormed;
         }
         const char* anchor = pb.position();
         pb.skipToChar(Symbols::COLON[0]);

         if (pb.eof())
         {
            DebugLog(<< "Invalid nonce; expected timestamp terminator.");
            return BadlyFormed;
         }

         Data then;
         pb.data(then, anchor);
         */
         NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce));
         if(x_nonce.getCreationTime() == 0)
            return BadlyFormed;


         
         
         
         if (expiresDelta > 0)
         {
            UInt64 now = Timer::getTimeSecs();
            if (x_nonce.getCreationTime() + expiresDelta < now)
            {
               DebugLog(<< "Nonce has expired.");
               return Expired;
            }
         }

         Data then(x_nonce.getCreationTime());
         if (i->param(p_nonce) != makeNonce(request, then))
         {
            InfoLog(<< "Not my nonce.");
            return Failed;
         }
      
         InfoLog (<< " username=" << (i->param(p_username))
                  << " password=" << password
                  << " realm=" << realm
                  << " method=" << getMethodName(request.header(h_RequestLine).getMethod())
                  << " uri=" << i->param(p_uri)
                  << " nonce=" << i->param(p_nonce));
         
         if (i->exists(p_qop))
         {
            if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt)
            {
               if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc))
               {
                  if (i->param(p_response) == makeResponseMD5(i->param(p_username), 
                                                            password,
                                                            realm, 
                                                            getMethodName(request.header(h_RequestLine).getMethod()),
                                                            i->param(p_uri),
                                                            i->param(p_nonce),
                                                            i->param(p_qop),
                                                            i->param(p_cnonce),
                                                            i->param(p_nc)),
                                                            request.getContents())
                  {
                     return Authenticated;
                  }
                  else
                  {
                     return Failed;
                  }
               }
            }
            else
            {
               InfoLog (<< "Unsupported qop=" << i->param(p_qop));
               return Failed;
            }
         }
         else if(i->exists(p_uri))
         {
         
            if (i->param(p_response) == makeResponseMD5(i->param(p_username), 
                                                            password,
                                                            realm, 
                                                            getMethodName(request.header(h_RequestLine).getMethod()),
                                                            i->param(p_uri),
                                                            i->param(p_nonce)))
            {
               return Authenticated;
            }
            else
            {
               return Failed;
            }
         }
      }
      else
      {
         return BadlyFormed;
      }
   }

   return BadlyFormed;

}

Here is the call graph for this function:

Helper::AuthResult Helper::authenticateRequestWithA1 ( const SipMessage request,
const Data realm,
const Data hA1,
int  expiresDelta = 0 
) [static]

Definition at line 1078 of file Helper.cxx.

References resip::ParserContainerBase::append(), resip::Symbols::auth, resip::Symbols::authInt, resip::ParserContainer< T >::begin(), DebugLog, digest, resip::ParserContainerBase::empty(), resip::ParserContainer< T >::end(), resip::SipMessage::exists(), resip::SipMessage::getContents(), resip::NonceHelper::Nonce::getCreationTime(), resip::RequestLine::getMethod(), resip::Timer::getTimeSecs(), resip::SipMessage::header(), InfoLog, and resip::isEqualNoCase().

{
   DebugLog(<< "Authenticating with HA1: realm=" << realm << " expires=" << expiresDelta);
   //DebugLog(<< request);

   // !bwc! Somewhat inefficient. Maybe optimize later.
   ParserContainer<Auth> auths;
   
   if(request.exists(h_ProxyAuthorizations))
   {
      auths.append(request.header(h_ProxyAuthorizations));
   }
   
   if(request.exists(h_Authorizations))
   {
      auths.append(request.header(h_Authorizations));
   }

   if(auths.empty())
   {
      DebugLog (<< "No authentication headers. Failing request.");
      return Failed;
   }

   // ?bwc? Why is const_iterator& operator=(const iterator& rhs)
   // not working properly?
   //ParserContainer<Auth>::const_iterator i = auths.begin();
   
   ParserContainer<Auth>::iterator i = auths.begin();
      
   for (;i != auths.end(); i++) 
   {
      if (i->exists(p_realm) && 
          i->exists(p_nonce) &&
          i->exists(p_response) &&
          i->param(p_realm) == realm)
      {
         if(!isEqualNoCase(i->scheme(),digest))
         {
            DebugLog(<< "Scheme must be Digest");
            continue;
         }
         /*
         ParseBuffer pb(i->param(p_nonce).data(), i->param(p_nonce).size());
         if (!pb.eof() && !isdigit(*pb.position()))
         {
            DebugLog(<< "Invalid nonce; expected timestamp.");
            return BadlyFormed;
         }
         const char* anchor = pb.position();
         pb.skipToChar(Symbols::COLON[0]);

         if (pb.eof())
         {
            DebugLog(<< "Invalid nonce; expected timestamp terminator.");
            return BadlyFormed;
         }

         Data then;
         pb.data(then, anchor);
         */

         NonceHelper::Nonce x_nonce = getNonceHelper()->parseNonce(i->param(p_nonce));
         if(x_nonce.getCreationTime() == 0)
            return BadlyFormed;



         if (expiresDelta > 0)
         {
            UInt64 now = Timer::getTimeSecs();
            if (x_nonce.getCreationTime() + expiresDelta < now)
            {
               DebugLog(<< "Nonce has expired.");
               return Expired;
            }
         }

         Data then(x_nonce.getCreationTime());

         if (i->param(p_nonce) != makeNonce(request, then))
         {
            InfoLog(<< "Not my nonce.");
            return Failed;
         }
      
         InfoLog (<< " username=" << (i->param(p_username))
                  << " H(A1)=" << hA1
                  << " realm=" << realm
                  << " method=" << getMethodName(request.header(h_RequestLine).getMethod())
                  << " uri=" << i->param(p_uri)
                  << " nonce=" << i->param(p_nonce));
         
         if (i->exists(p_qop))
         {
            if (i->param(p_qop) == Symbols::auth || i->param(p_qop) == Symbols::authInt)
            {
               if(i->exists(p_uri) && i->exists(p_cnonce) && i->exists(p_nc))
               {
                  if (i->param(p_response) == makeResponseMD5WithA1(hA1, 
                                                                  getMethodName(request.header(h_RequestLine).getMethod()),
                                                                  i->param(p_uri),
                                                                  i->param(p_nonce),
                                                                  i->param(p_qop),
                                                                  i->param(p_cnonce),
                                                                  i->param(p_nc),
                                                                  request.getContents()))
                  {
                     return Authenticated;
                  }
                  else
                  {
                     return Failed;
                  }
               }
            }
            else
            {
               InfoLog (<< "Unsupported qop=" << i->param(p_qop));
               return Failed;
            }
         }
         else if(i->exists(p_uri))
         {
            if (i->param(p_response) == makeResponseMD5WithA1(hA1,
                                                                  getMethodName(request.header(h_RequestLine).getMethod()),
                                                                  i->param(p_uri),
                                                                  i->param(p_nonce)))
            {
               return Authenticated;
            }
            else
            {
               return Failed;
            }
         }
      }
      else
      {
         return BadlyFormed;
      }
   }

   return BadlyFormed;

}

Here is the call graph for this function:

Data Helper::computeCallId ( ) [static]

Definition at line 650 of file Helper.cxx.

References resip::Data::append(), resip::Data::BASE64, resip::Random::getRandomHex(), localhostname, and resip::Data::md5().

Referenced by main(), makeMessage(), makePublish(), makeRegister(), makeRequest(), and makeSubscribe().

{
   Data hostAndSalt(localhostname + Random::getRandomHex(16));
#ifndef USE_SSL // .bwc. None of this is neccessary if we're using openssl
#if defined(__linux__) || defined(__APPLE__)
   pid_t pid = getpid();
   hostAndSalt.append((char*)&pid,sizeof(pid));
#endif
#ifdef __APPLE__
   pthread_t thread = pthread_self();
   hostAndSalt.append((char*)&thread,sizeof(thread));
#endif
#ifdef WIN32
   DWORD proccessId = ::GetCurrentProcessId();
   DWORD threadId = ::GetCurrentThreadId();
   hostAndSalt.append((char*)&proccessId,sizeof(proccessId));
   hostAndSalt.append((char*)&threadId,sizeof(threadId));
#endif
#endif // of USE_SSL
   return hostAndSalt.md5(Data::BASE64);
}

Here is the call graph for this function:

static Data resip::Helper::computeProxyBranch ( const SipMessage request) [static]
Data Helper::computeTag ( int  numBytes) [static]

Definition at line 673 of file Helper.cxx.

References resip::Random::getRandomHex().

Referenced by makeMessage(), makePublish(), makeRegister(), makeRequest(), resip::DeprecatedDialog::makeResponse(), makeResponse(), makeSubscribe(), and Server::thread().

{
   return Random::getRandomHex(numBytes);
}

Here is the call graph for this function:

Data Helper::computeUniqueBranch ( ) [static]

Creates and returns a unique branch parameter.

Generated branch will contain the RFC3261 magic cookie + 4 randome hex characters + "C1" + 2 random hex characters.

Deprecated:
Not used by stack.

Definition at line 637 of file Helper.cxx.

References cookie, resip::Random::getRandomHex(), and resip::Data::Preallocate.

{
   Data result(16, Data::Preallocate);
   result += cookie;
   result += Random::getRandomHex(4);
   result += "C1";
   result += Random::getRandomHex(2);
   return result;
}

Here is the call graph for this function:

Helper::FailureMessageEffect Helper::determineFailureMessageEffect ( const SipMessage response) [static]

Definition at line 1996 of file Helper.cxx.

References ApplicationDependant, DialogTermination, resip::SipMessage::exists(), resip::SipMessage::header(), resip::SipMessage::isResponse(), OptionalRetryAfter, RetryAfter, TransactionTermination, and UsageTermination.

{
   assert(response.isResponse());
   int code = response.header(h_StatusLine).statusCode();
   assert(code >= 400);
   
   switch(code)
   {
      case 404:
      case 410:
      case 416:
      case 480:  // but maybe not, still not quite decided:
      case 481:
      case 482: // but maybe not, still not quite decided:
      case 484:
      case 485:
      case 502:
      case 604:
         return DialogTermination;
      case 403:
      case 489: //only for only subscription
      case 408:  //again, maybe not. This seems best.
         return UsageTermination;      
      case 400:
      case 401:
      case 402:
      case 405:  //doesn't agree w/  -00 of dialogusage
      case 406:
      case 412:
      case 413:
      case 414:
      case 415:
      case 420:
      case 421:
      case 423:

      case 429: // but if this the refer creating the Subscription, no sub will be created.
      case 486:
      case 487:
      case 488:
      case 491: 
      case 493:
      case 494:
      case 500:
      case 505:
      case 513:
      case 603:
      case 606:
         return TransactionTermination;
      case 483: // who knows, gravefully terminate or just destroy dialog
      case 501:
         return ApplicationDependant;
      default:
         if (code < 600)
         {
            if (response.exists(h_RetryAfter))

            {
               return RetryAfter;
            }
            else
            {
               return OptionalRetryAfter;
            }
         }
         else
         {
            if (response.exists(h_RetryAfter))
            {
               return RetryAfter;
            }
            else
            {
               return ApplicationDependant;
            }
         }
   }
}

Here is the call graph for this function:

Helper::ContentsSecAttrs Helper::extractFromPkcs7 ( const SipMessage message,
Security security 
) [static]

Definition at line 1969 of file Helper.cxx.

References extractFromPkcs7Recurse(), fromAor(), resip::Uri::getAor(), resip::SipMessage::getContents(), resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::SecurityAttributes::setIdentity(), and resip::RequestLine::uri().

{
   SecurityAttributes* attr = new SecurityAttributes;
   // .dlb. currently flattening SecurityAttributes?
   //attr->setIdentity(message.getIdentity());
   attr->setIdentity(message.header(h_From).uri().getAor());
   Contents *b = message.getContents();
   if (b) 
   {
      Data fromAor(message.header(h_From).uri().getAor());
      Data toAor(message.header(h_To).uri().getAor());
      if (message.isRequest())
      {
         b = extractFromPkcs7Recurse(b, fromAor, toAor, attr, security);
      }
      else // its a response
      {
         b = extractFromPkcs7Recurse(b, toAor, fromAor, attr, security);
      }
   }
   std::auto_ptr<Contents> c(b);
   std::auto_ptr<SecurityAttributes> a(attr);
   return ContentsSecAttrs(c, a);
}

Here is the call graph for this function:

Uri Helper::fromAor ( const Data aor,
const Data scheme = Symbols::DefaultSipScheme 
) [static]

Definition at line 1699 of file Helper.cxx.

Referenced by extractFromPkcs7().

{
   return makeUri(aor, scheme);
}
static std::pair<Data,Data> resip::Helper::fromGruuUserPart ( const Data gruuUserPart,
const Data key 
) [static]
Tuple Helper::getClientPublicAddress ( const SipMessage request) [static]

Look at Via headers, and find the first public IP address closest to the sending client.

Parameters:
requestRequest message that we use for checking.
Note:
If no public IP's are found, then an empty Tuple is returned. This can be tested by checking if Tuple::getType() returns UNKNOWN_TRANSPORT.

Definition at line 2210 of file Helper.cxx.

References resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::Tuple::setPort(), resip::Tuple::toTransport(), and resip::UNKNOWN_TRANSPORT.

{
   assert(request.isRequest());
   assert(!request.header(h_Vias).empty());

   // Iterate through Via's starting at the bottom (closest to the client).  Return the first
   // public address found from received parameter if present, or Via host.
   Vias::const_iterator it = request.header(h_Vias).end();
   while(true)
   {
      it--;
      if(it->exists(p_received))
      {
         // Check IP from received parameter
         Tuple address(it->param(p_received), 0, UNKNOWN_TRANSPORT);
         if(!address.isPrivateAddress())
         {
            address.setPort(it->exists(p_rport) ? it->param(p_rport).port() : it->sentPort());
            address.setType(Tuple::toTransport(it->transport()));
            return address;
         }
      }

      // Check IP from Via sentHost
      Tuple address(it->sentHost(), 0, UNKNOWN_TRANSPORT);
      if(!address.isPrivateAddress())
      {
         address.setPort(it->exists(p_rport) ? it->param(p_rport).port() : it->sentPort());
         address.setType(Tuple::toTransport(it->transport()));
         return address;
      }

      if(it == request.header(h_Vias).begin()) break;
   }
   return Tuple();
}

Here is the call graph for this function:

NonceHelper * Helper::getNonceHelper ( ) [static]
int Helper::getPortForReply ( SipMessage request) [static]

Definition at line 1656 of file Helper.cxx.

References resip::SipMessage::const_header(), resip::Symbols::DefaultSipPort, resip::Symbols::DefaultSipsPort, resip::DTLS, resip::Tuple::getPort(), resip::SipMessage::getSource(), resip::SipMessage::isRequest(), resip::Symbols::TCP, resip::TLS, and resip::Symbols::TLS.

Referenced by resip::TransactionState::processSipMessageAsNew().

{
   assert(request.isRequest());
   int port = 0;
   if(request.const_header(h_Vias).front().transport() == Symbols::TCP ||
      request.const_header(h_Vias).front().transport() == Symbols::TLS)
   {
      // 18.2.2 - bullet 1 and 2 
      port = request.getSource().getPort();
      if(port == 0) // .slg. not sure if it makes sense for sourcePort to be 0
      {
         port = request.const_header(h_Vias).front().sentPort();
      }
   }
   else   // unreliable transport 18.2.2 bullets 3 and 4
   {
      if (request.const_header(h_Vias).front().exists(p_rport))
      {
         port = request.getSource().getPort();
      }
      else
      {
         port = request.const_header(h_Vias).front().sentPort();
      }
   }

   // If we haven't got a valid port yet, then use the default
   if (port <= 0 || port > 65535) 
   {
      if(request.const_header(h_Vias).front().transport() == Symbols::TLS ||
         request.const_header(h_Vias).front().transport() == Symbols::DTLS)
      {
         port = Symbols::DefaultSipsPort;
      }
      else
      {
         port = Symbols::DefaultSipPort;
      }
   }
   return port;
}

Here is the call graph for this function:

void Helper::getResponseCodeReason ( int  responseCode,
Data reason 
) [static]

Returns the default reason string for a particular response code.

Parameters:
responseCodeResponse code to get reason for
reasonData where the reason string associated with the responseCode will be set.

Definition at line 509 of file Helper.cxx.

{
   switch (responseCode)
   {
      case 100: reason = "Trying"; break;
      case 180: reason = "Ringing"; break;
      case 181: reason = "Call Is Being Forwarded"; break;
      case 182: reason = "Queued"; break;
      case 183: reason = "Session Progress"; break;
      case 200: reason = "OK"; break;
      case 202: reason = "Accepted"; break;
      case 300: reason = "Multiple Choices"; break;
      case 301: reason = "Moved Permanently"; break;
      case 302: reason = "Moved Temporarily"; break;
      case 305: reason = "Use Proxy"; break;
      case 380: reason = "Alternative Service"; break;
      case 400: reason = "Bad Request"; break;
      case 401: reason = "Unauthorized"; break;
      case 402: reason = "Payment Required"; break;
      case 403: reason = "Forbidden"; break;
      case 404: reason = "Not Found"; break;
      case 405: reason = "Method Not Allowed"; break;
      case 406: reason = "Not Acceptable"; break;
      case 407: reason = "Proxy Authentication Required"; break;
      case 408: reason = "Request Timeout"; break;
      case 410: reason = "Gone"; break;
      case 412: reason = "Precondition Failed"; break;
      case 413: reason = "Request Entity Too Large"; break;
      case 414: reason = "Request-URI Too Long"; break;
      case 415: reason = "Unsupported Media Type"; break;
      case 416: reason = "Unsupported URI Scheme"; break;
      case 420: reason = "Bad Extension"; break;
      case 421: reason = "Extension Required"; break;
      case 422: reason = "Session Interval Too Small"; break;
      case 423: reason = "Interval Too Brief"; break;
      case 430: reason = "Flow failed"; break;
      case 439: reason = "First Hop Lacks Outbound Support"; break;
      case 480: reason = "Temporarily Unavailable"; break;
      case 481: reason = "Call/Transaction Does Not Exist"; break;
      case 482: reason = "Loop Detected"; break;
      case 483: reason = "Too Many Hops"; break;
      case 484: reason = "Address Incomplete"; break;
      case 485: reason = "Ambiguous"; break;
      case 486: reason = "Busy Here"; break;
      case 487: reason = "Request Terminated"; break;
      case 488: reason = "Not Acceptable Here"; break;
      case 489: reason = "Event Package Not Supported"; break;
      case 491: reason = "Request Pending"; break;
      case 493: reason = "Undecipherable"; break;
      case 500: reason = "Server Internal Error"; break;
      case 501: reason = "Not Implemented"; break;
      case 502: reason = "Bad Gateway"; break;
      case 503: reason = "Service Unavailable"; break;
      case 504: reason = "Server Time-out"; break;
      case 505: reason = "Version Not Supported"; break;
      case 513: reason = "Message Too Large"; break;
      case 600: reason = "Busy Everywhere"; break;
      case 603: reason = "Decline"; break;
      case 604: reason = "Does Not Exist Anywhere"; break;
      case 606: reason = "Not Acceptable"; break;
   }
}
auto_ptr< SdpContents > Helper::getSdp ( Contents tree) [static]

Definition at line 2162 of file Helper.cxx.

References resip::SdpContents::clone(), DebugLog, emptysdp, and getSdpRecurse().

{
   if (tree) 
   {
      SdpContents* sdp = getSdpRecurse(tree);

      if (sdp)
      {
         DebugLog(<< "Got sdp" << endl);
         return auto_ptr<SdpContents>(static_cast<SdpContents*>(sdp->clone()));
      }
   }

   //DebugLog(<< "No sdp" << endl);
   return emptysdp;
}

Here is the call graph for this function:

static Data resip::Helper::gruuUserPart ( const Data instanceId,
const Data aor,
const Data key 
) [static]
unsigned int Helper::hex2integer ( const char *  _s) [static]

Converts a character string containing a hexidecimal value into an unsigned int.

Note: Parsing stops after the first non-hex character, or after 8 characters have been processed.

Parameters:
_sA pointer to the character buffer to convert.
Returns:
The integer value of the coverted hex string.

Definition at line 86 of file Helper.cxx.

Referenced by resip::SdpContents::Session::Medium::parse(), and resip::SERNonceHelper::parseNonce().

{
   unsigned int i, res = 0;

   for(i = 0; i < 8; i++) 
   {
      if ((_s[i] >= '0') && (_s[i] <= '9')) 
      {
         res *= 16;
         res += _s[i] - '0';
      }
      else if ((_s[i] >= 'a') && (_s[i] <= 'f')) 
      {
         res *= 16;
         res += _s[i] - 'a' + 10;
      } 
      else if ((_s[i] >= 'A') && (_s[i] <= 'F')) 
      {
         res *= 16;
         res += _s[i] - 'A' + 10;
      }
      else 
      {
         return res;
      }
   }

   return res;
}
void Helper::integer2hex ( char *  _d,
unsigned int  _s,
bool  _l = true 
) [static]

Converts an interger in a character string containing the hexidecimal representation of the integer.

Note: The string buffer provided should be at least 8 characters long. This function will NOT NULL terminate the string.

Parameters:
_dA pointer to the character buffer to write the hex string
_sThe integer value to convert.
_lBoolean flag to include leading 0 zeros or not.

Definition at line 46 of file Helper.cxx.

Referenced by resip::SERNonceHelper::makeNonce(), and resip::SdpContents::Session::Medium::parse().

{
   int i;
   unsigned char j;
   int k = 0;
   char* s;

   _s = htonl(_s);
   s = (char*)&_s;

   for (i = 0; i < 4; i++) 
   {
      j = (s[i] >> 4) & 0xf;
      if (j <= 9) 
      {
         if(_l || j != 0 || k != 0)
         {
            _d[k++] = (j + '0');
         }
      }
      else 
      {
         _d[k++] = (j + 'a' - 10);
      }

      j = s[i] & 0xf;
      if (j <= 9) 
      {
         if(_l || j != 0 || k != 0)
         {
            _d[k++] = (j + '0');
         }
      }
      else 
      {
         _d[k++] = (j + 'a' - 10);
      }
   }
}
bool Helper::isClientBehindNAT ( const SipMessage request,
bool  privateToPublicOnly = true 
) [static]

Looks at SIP headers and message source for a mismatch to make an assumption that the sender is behind a NAT device.

Parameters:
requestRequest message that we use for checking.

If enabled then we ensure that the via is private address and that the source was a public address. This allows us to ignore cases of private-private NAT'ing or false detections, when a server behind a load balancer is sending us requests and using the load balancer address in the Via, instead of the real of the adapter.

Definition at line 2180 of file Helper.cxx.

References resip::SipMessage::header(), resip::SipMessage::isRequest(), and resip::UNKNOWN_TRANSPORT.

{
   assert(request.isRequest());
   assert(!request.header(h_Vias).empty());

   // If received parameter is on top Via, then the source of the message doesn't match
   // the address provided in the via.  Assume this is because the sender is behind a NAT.
   // The assumption here is that this SipStack instance is the first hop in a public SIP server
   // architecture, and that clients are directly connected to this instance.
   if(request.header(h_Vias).front().exists(p_received))
   {
      if(privateToPublicOnly)
      {
         if(Tuple(request.header(h_Vias).front().sentHost(), 0, UNKNOWN_TRANSPORT).isPrivateAddress() &&
            !Tuple(request.header(h_Vias).front().param(p_received), 0, UNKNOWN_TRANSPORT).isPrivateAddress())
         {
            return true;
         }
         else
         {
            return false;
         }
      }
      return true;
   }
   return false;
}

Here is the call graph for this function:

int Helper::jitterValue ( int  input,
int  lowerPercentage,
int  upperPercentage,
int  minimum = 0 
) [static]

Used to jitter the expires in a SUBSCRIBE or REGISTER expires header.

Parameters:
inputValue to jitter
lowerPercentageThe lower range of the random percentage by which to jitter the value by.
upperPercentageThe upper range of the random percentage by which to jitter the value by. Must be greater than or equal to lowerPercentage
minimumOnly jitter the input if greater than minimum

Definition at line 316 of file Helper.cxx.

References resip::Random::getRandom(), and input.

{
   assert(upperPercentage >= lowerPercentage);
   if (input < minimum)
   {
      return input;
   }
   else if (lowerPercentage == 100 && upperPercentage == 100)
   {
      return input;
   }
   else
   {
      const int rnd = Random::getRandom() % (upperPercentage-lowerPercentage) + lowerPercentage;
      return (input * rnd) / 100;
   }
}

Here is the call graph for this function:

SipMessage * Helper::make405 ( const SipMessage request,
const int *  allowedMethods = 0,
int  nMethods = -1 
) [static]

Make a 405 response to a provided request.

Allows header is added with specified methods, or with all methods the stack knows about. Caller owns the returned pointer and is responsible for deleting it.

Parameters:
requestSipMessage request from which to generate the response
allowedMethodsArray of integers representing a list of Method Types to add to the generated Allows header. See MethodTypes.hxx.
nMethodsNumber of methods specified in the allowedMethods integer array. Specify -1 to have this method fill in the Allows header automatically with each method supported by the stack.
Returns:
SipMessage populated with the appropriate response. Caller must deallocate.

Definition at line 1229 of file Helper.cxx.

References resip::SipMessage::header(), len, makeResponse(), and resip::Token::value().

Referenced by resip::TuIM::processRequest().

{
    SipMessage* resp = Helper::makeResponse(request, 405);

    if (len < 0)
    {
        int upperBound = static_cast<int>(MAX_METHODS);

        // The UNKNOWN method name is the first in the enum
        for (int i = 1 ; i < upperBound; i ++)
        {
            int last = 0;

            // ENUMS must be contiguous in order for this to work.
            assert( i - last <= 1);
            Token t;
            t.value() = getMethodName(static_cast<resip::MethodTypes>(i));
            resp->header(h_Allows).push_back(t);
            last = i;
        }
    }
    else
    {
        // use user's list
        for ( int i = 0 ; i < len ; i++)
        {
            Token t;
            t.value() = getMethodName(static_cast<resip::MethodTypes>(allowedMethods[i]));
            resp->header(h_Allows).push_back(t);
        }
    }
    return resp;
}

Here is the call graph for this function:

SipMessage * Helper::makeCancel ( const SipMessage request) [static]

Make a new Cancel request for the specified request.

Caller owns the returned pointer and is responsible for deleting it.

Parameters:
requestRequest for which the Cancel will apply. ie. Invite request.
Returns:
Created Cancel request. Caller must deallocate.

Definition at line 573 of file Helper.cxx.

References resip::SipMessage::exists(), resip::RequestLine::getMethod(), resip::RequestLine::getSipVersion(), resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::RequestLine::method(), and resip::RequestLine::uri().

Referenced by resip::TransactionState::processClientInvite().

{
   assert(request.isRequest());
   assert(request.header(h_RequestLine).getMethod() == INVITE);
   std::auto_ptr<SipMessage> cancel(new SipMessage);

   RequestLine rLine(CANCEL, request.header(h_RequestLine).getSipVersion());
   rLine.uri() = request.header(h_RequestLine).uri();
   cancel->header(h_RequestLine) = rLine;
   cancel->header(h_MaxForwards).value() = 70;
   cancel->header(h_To) = request.header(h_To);
   cancel->header(h_From) = request.header(h_From);
   cancel->header(h_CallId) = request.header(h_CallId);
   if (request.exists(h_ProxyAuthorizations))
   {
      cancel->header(h_ProxyAuthorizations) = request.header(h_ProxyAuthorizations);
   }
   if (request.exists(h_Authorizations))
   {
      cancel->header(h_Authorizations) = request.header(h_Authorizations);
   }
   
   if (request.exists(h_Routes))
   {
      cancel->header(h_Routes) = request.header(h_Routes);
   }
   
   cancel->header(h_CSeq) = request.header(h_CSeq);
   cancel->header(h_CSeq).method() = CANCEL;
   cancel->header(h_Vias).push_back(request.header(h_Vias).front());

   return cancel.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeChallenge ( const SipMessage request,
const Data realm,
bool  useAuth = true,
bool  stale = false,
bool  proxy = false 
) [static]

Definition at line 1279 of file Helper.cxx.

References resip::Symbols::Digest, resip::Timer::getTimeSecs(), resip::SipMessage::header(), makeResponse(), resip::ParserCategory::param(), and resip::Auth::scheme().

{
   Auth auth;
   auth.scheme() = Symbols::Digest;
   Data timestamp(Timer::getTimeSecs());
   auth.param(p_nonce) = makeNonce(request, timestamp);
   auth.param(p_algorithm) = "MD5";
   auth.param(p_realm) = realm;
   if (useAuth)
   {
      auth.param(p_qopOptions) = "auth,auth-int";
   }
   if (stale)
   {
      auth.param(p_stale) = "true";
   }
   SipMessage *response;
   if(proxy)
   {
      response = Helper::makeResponse(request, 407);
      response->header(h_ProxyAuthenticates).push_back(auth);
   }
   else
   {
      response = Helper::makeResponse(request, 401);
      response->header(h_WWWAuthenticates).push_back(auth);
   }
   return response;
}

Here is the call graph for this function:

Auth Helper::makeChallengeResponseAuth ( const SipMessage request,
const Data username,
const Data password,
const Auth challenge,
const Data cnonce,
unsigned int &  nonceCount,
Data nonceCountString 
) [static]

Definition at line 1336 of file Helper.cxx.

References resip::Data::empty().

{
   Auth auth;
   Data authQop = qopOption(challenge);
   if(!authQop.empty())
   {
       updateNonceCount(nonceCount, nonceCountString);
   }
   makeChallengeResponseAuth(request, username, password, challenge, cnonce, authQop, nonceCountString, auth);
   return auth;
}

Here is the call graph for this function:

void Helper::makeChallengeResponseAuth ( const SipMessage request,
const Data username,
const Data password,
const Auth challenge,
const Data cnonce,
const Data authQop,
const Data nonceCountString,
Auth auth 
) [static]

Definition at line 1355 of file Helper.cxx.

References resip::Symbols::Digest, resip::Data::empty(), resip::Auth::exists(), resip::SipMessage::getContents(), resip::RequestLine::getMethod(), resip::SipMessage::header(), makeResponseMD5(), resip::ParserCategory::param(), resip::Auth::scheme(), resip::Data::size(), and resip::RequestLine::uri().

{
   auth.scheme() = Symbols::Digest;
   auth.param(p_username) = username;
   assert(challenge.exists(p_realm));
   auth.param(p_realm) = challenge.param(p_realm);
   assert(challenge.exists(p_nonce));
   auth.param(p_nonce) = challenge.param(p_nonce);
   Data digestUri;
   {
      DataStream s(digestUri);
      //s << request.header(h_RequestLine).uri().host(); // wrong 
      s << request.header(h_RequestLine).uri(); // right 
   }
   auth.param(p_uri) = digestUri;

   if (!authQop.empty())
   {
      auth.param(p_response) = Helper::makeResponseMD5(username, 
                                                       password,
                                                       challenge.param(p_realm), 
                                                       getMethodName(request.header(h_RequestLine).getMethod()), 
                                                       digestUri, 
                                                       challenge.param(p_nonce),
                                                       authQop,
                                                       cnonce,
                                                       nonceCountString,
                                                       request.getContents());
      auth.param(p_cnonce) = cnonce;
      auth.param(p_nc) = nonceCountString;
      auth.param(p_qop) = authQop;
   }
   else
   {
      assert(challenge.exists(p_realm));
      auth.param(p_response) = Helper::makeResponseMD5(username, 
                                                       password,
                                                       challenge.param(p_realm), 
                                                       getMethodName(request.header(h_RequestLine).getMethod()),
                                                       digestUri, 
                                                       challenge.param(p_nonce));
   }
   
   if (challenge.exists(p_algorithm))
   {
      auth.param(p_algorithm) = challenge.param(p_algorithm);
   }
   else
   {
      auth.param(p_algorithm) = "MD5";
   }

   if (challenge.exists(p_opaque) && challenge.param(p_opaque).size() > 0)
   {
      auth.param(p_opaque) = challenge.param(p_opaque);
   }
}

Here is the call graph for this function:

Auth Helper::makeChallengeResponseAuthWithA1 ( const SipMessage request,
const Data username,
const Data passwordHashA1,
const Auth challenge,
const Data cnonce,
unsigned int &  nonceCount,
Data nonceCountString 
) [static]

Definition at line 1468 of file Helper.cxx.

References resip::Data::empty().

{
   Auth auth;
   Data authQop = qopOption(challenge);
   if(!authQop.empty())
   {
       updateNonceCount(nonceCount, nonceCountString);
   }
   makeChallengeResponseAuthWithA1(request, username, passwordHashA1, challenge, cnonce, authQop, nonceCountString, auth);
   return auth;
}

Here is the call graph for this function:

void Helper::makeChallengeResponseAuthWithA1 ( const SipMessage request,
const Data username,
const Data passwordHashA1,
const Auth challenge,
const Data cnonce,
const Data authQop,
const Data nonceCountString,
Auth auth 
) [static]

Definition at line 1487 of file Helper.cxx.

References resip::SipMessage::const_header(), resip::Symbols::Digest, resip::Data::empty(), resip::Auth::exists(), resip::SipMessage::getContents(), resip::RequestLine::getMethod(), resip::SipMessage::header(), makeResponseMD5WithA1(), resip::ParserCategory::param(), resip::Auth::scheme(), resip::Data::size(), and resip::RequestLine::uri().

{
   auth.scheme() = Symbols::Digest;
   auth.param(p_username) = username;
   assert(challenge.exists(p_realm));
   auth.param(p_realm) = challenge.param(p_realm);
   assert(challenge.exists(p_nonce));
   auth.param(p_nonce) = challenge.param(p_nonce);
   Data digestUri;
   {
      DataStream s(digestUri);
      //s << request.const_header(h_RequestLine).uri().host(); // wrong 
      s << request.const_header(h_RequestLine).uri(); // right 
   }
   auth.param(p_uri) = digestUri;

   if (!authQop.empty())
   {
      auth.param(p_response) = Helper::makeResponseMD5WithA1(passwordHashA1,
                                                             getMethodName(request.header(h_RequestLine).getMethod()), 
                                                             digestUri, 
                                                             challenge.param(p_nonce),
                                                             authQop,
                                                             cnonce,
                                                             nonceCountString,
                                                             request.getContents());
      auth.param(p_cnonce) = cnonce;
      auth.param(p_nc) = nonceCountString;
      auth.param(p_qop) = authQop;
   }
   else
   {
      assert(challenge.exists(p_realm));
      auth.param(p_response) = Helper::makeResponseMD5WithA1(passwordHashA1,
                                                             getMethodName(request.header(h_RequestLine).getMethod()),
                                                             digestUri, 
                                                             challenge.param(p_nonce));
   }
   
   if (challenge.exists(p_algorithm))
   {
      auth.param(p_algorithm) = challenge.param(p_algorithm);
   }
   else
   {
      auth.param(p_algorithm) = "MD5";
   }

   if (challenge.exists(p_opaque) && challenge.param(p_opaque).size() > 0)
   {
      auth.param(p_opaque) = challenge.param(p_opaque);
   }
}

Here is the call graph for this function:

SipMessage * Helper::makeFailureAck ( const SipMessage request,
const SipMessage response 
) [static]

This interface should be used by the stack (TransactionState) to create an AckMsg to a failure response.

See RFC3261 section 17.1.1.3. Caller owns the returned pointer and is responsible for deleting it.

Note:
The branch in this ACK needs to be the one from the request. For TU generated ACK, see Dialog::makeAck(...)
Parameters:
requestRequest that this ACK applies to.
responseResponse that we are ACKing - required so that we can get the To tag into the generated ACK.
Returns:
Created Ack request. Caller must deallocate.

Definition at line 609 of file Helper.cxx.

References resip::SipMessage::exists(), resip::RequestLine::getMethod(), resip::RequestLine::getSipVersion(), resip::SipMessage::header(), resip::RequestLine::method(), and resip::RequestLine::uri().

Referenced by resip::TransactionState::processClientInvite().

{
   assert (request.header(h_Vias).size() >= 1);
   assert (request.header(h_RequestLine).getMethod() == INVITE);
   
   std::auto_ptr<SipMessage> ack(new SipMessage);

   RequestLine rLine(ACK, request.header(h_RequestLine).getSipVersion());
   rLine.uri() = request.header(h_RequestLine).uri();
   ack->header(h_RequestLine) = rLine;
   ack->header(h_MaxForwards).value() = 70;
   ack->header(h_CallId) = request.header(h_CallId);
   ack->header(h_From) = request.header(h_From);
   ack->header(h_To) = response.header(h_To); // to get to-tag
   ack->header(h_Vias).push_back(request.header(h_Vias).front());
   ack->header(h_CSeq) = request.header(h_CSeq);
   ack->header(h_CSeq).method() = ACK;
   if (request.exists(h_Routes))
   {
      ack->header(h_Routes) = request.header(h_Routes);
   }
   
   return ack.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeInvite ( const NameAddr target,
const NameAddr from 
) [static]

Make an invite request - Empty Contact and Via is added and will be populated by the stack when sent.

Parameters:
targetEnds up in the RequestURI and To header
fromEnds up in the From header

Definition at line 335 of file Helper.cxx.

References makeRequest().

Referenced by Client::Client(), main(), Client::process(), and Client::thread().

{
   return Helper::makeRequest(target, from, INVITE);
}

Here is the call graph for this function:

SipMessage * Helper::makeInvite ( const NameAddr target,
const NameAddr from,
const NameAddr contact 
) [static]

Make an invite request using a overridden contact header - Empty Via is added and will be populated by the stack when sent.

Parameters:
targetEnds up in the RequestURI and To header
fromEnds up in the From header
contactEnds up in the Contact header. Stack will not change this when sent.

Definition at line 341 of file Helper.cxx.

References makeRequest().

{
   return Helper::makeRequest(target, from, contact, INVITE);
}

Here is the call graph for this function:

SipMessage * Helper::makeMessage ( const NameAddr target,
const NameAddr from,
const NameAddr contact 
) [static]

Create a Message request with an overriden Contact. See makeRequest.

Definition at line 262 of file Helper.cxx.

References computeCallId(), computeTag(), resip::RequestLine::method(), resip::ParserCategory::param(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

Referenced by resip::DeprecatedDialog::makeInitialMessage().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(MESSAGE);
   rLine.uri() = target.uri();

   request->header(h_To) = target;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = MESSAGE;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = from;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_CallId).value() = Helper::computeCallId();
   assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty());
   request->header(h_Contacts).push_back( contact );
   Via via;
   request->header(h_Vias).push_back(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeMessage ( const NameAddr target,
const NameAddr from 
) [static]

Create a Message request with an empty Contact. See makeRequest.

Definition at line 255 of file Helper.cxx.

{
   NameAddr contact;
   return makeMessage(target, from, contact);
}
Data Helper::makeNonce ( const SipMessage request,
const Data timestamp 
) [static]

Definition at line 696 of file Helper.cxx.

{
   return getNonceHelper()->makeNonce(request, timestamp);
}
SipMessage * Helper::makeProxyChallenge ( const SipMessage request,
const Data realm,
bool  useAuth = true,
bool  stale = false 
) [static]

Definition at line 1267 of file Helper.cxx.

{
   return makeChallenge(request,realm,useAuth,stale,true);
}
SipMessage * Helper::makePublish ( const NameAddr target,
const NameAddr from,
const NameAddr contact 
) [static]

Create a Publish request with an overriden Contact. See makeRequest.

Definition at line 232 of file Helper.cxx.

References computeCallId(), computeTag(), resip::RequestLine::method(), resip::ParserCategory::param(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(PUBLISH);
   rLine.uri() = target.uri();

   request->header(h_To) = target;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = PUBLISH;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = from;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_CallId).value() = Helper::computeCallId();
   assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty());
   request->header(h_Contacts).push_back( contact );
   Via via;
   request->header(h_Vias).push_back(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makePublish ( const NameAddr target,
const NameAddr from 
) [static]

Create a Publish request with an empty Contact. See makeRequest.

Definition at line 225 of file Helper.cxx.

{
   NameAddr contact;
   return makePublish(target, from, contact);
}
void Helper::makeRawResponse ( Data rawBuffer,
const SipMessage request,
int  responseCode,
const Data additionalHeaders = Data::Empty,
const Data body = Data::Empty 
) [static]

Definition at line 485 of file Helper.cxx.

References resip::SipMessage::encodeSingleHeader(), resip::Data::reserve(), and resip::Data::size().

Referenced by resip::Transport::make100(), and resip::Transport::make503().

{
   raw.reserve(256);
   {
      DataStream encodeStream(raw);
      encodeStream << "SIP/2.0 " << responseCode << " ";
      Data reason;
      getResponseCodeReason(responseCode, reason);
      encodeStream << reason;
      msg.encodeSingleHeader(Headers::Via,encodeStream);
      msg.encodeSingleHeader(Headers::To,encodeStream);
      msg.encodeSingleHeader(Headers::From,encodeStream);
      msg.encodeSingleHeader(Headers::CallID,encodeStream);
      msg.encodeSingleHeader(Headers::CSeq,encodeStream);
      encodeStream << additionalHeaders;
      encodeStream << "Content-Length: " << body.size() << "\r\n\r\n";
   }
}

Here is the call graph for this function:

SipMessage * Helper::makeRegister ( const NameAddr to,
const NameAddr from,
const NameAddr contact 
) [static]

Create a Register request with an overriden Contact. See makeRequest.

Definition at line 154 of file Helper.cxx.

References computeCallId(), computeTag(), resip::Uri::exists(), resip::Uri::host(), resip::RequestLine::method(), resip::ParserCategory::param(), resip::Uri::port(), resip::Uri::scheme(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

Referenced by doit(), and main().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(REGISTER);

   rLine.uri().scheme() = to.uri().scheme();
   rLine.uri().host() = to.uri().host();
   rLine.uri().port() = to.uri().port();
   if (to.uri().exists(p_transport))
   {
      rLine.uri().param(p_transport) = to.uri().param(p_transport);
   }

   request->header(h_To) = to;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = REGISTER;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = from;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_CallId).value() = Helper::computeCallId();
   assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty());
   request->header(h_Contacts).push_back( contact );
   
   Via via;
   request->header(h_Vias).push_back(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeRegister ( const NameAddr to,
const NameAddr from 
) [static]

Create a Register request with an empty Contact. See makeRequest.

Definition at line 147 of file Helper.cxx.

{
   NameAddr contact;
   return makeRegister(to, from, contact);
}
SipMessage * Helper::makeRegister ( const NameAddr to,
const Data transport,
const NameAddr contact 
) [static]

Create a Register request with an overriden Contact, transport is added to Request URI. See makeRequest.

Definition at line 193 of file Helper.cxx.

References computeCallId(), computeTag(), resip::Data::empty(), resip::Uri::host(), resip::RequestLine::method(), resip::ParserCategory::param(), resip::Uri::port(), resip::Uri::scheme(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(REGISTER);

   rLine.uri().scheme() = to.uri().scheme();
   rLine.uri().host() = to.uri().host();
   rLine.uri().port() = to.uri().port();
   if (!transport.empty())
   {
      rLine.uri().param(p_transport) = transport;
   }

   request->header(h_To) = to;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = REGISTER;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = to;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_CallId).value() = Helper::computeCallId();
   assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty());
   request->header(h_Contacts).push_back( contact );
   
   Via via;
   request->header(h_Vias).push_back(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeRegister ( const NameAddr to,
const Data transport 
) [static]

Create a Register request with an empty Contact, transport is added to Request URI. See makeRequest.

Definition at line 185 of file Helper.cxx.

{
   NameAddr contact;
   return makeRegister(to, transport, contact);
   
}
SipMessage * Helper::makeRequest ( const NameAddr target,
const NameAddr from,
const NameAddr contact,
MethodTypes  method 
) [static]

Make a new request with a overridden Contact.

To, maxforward=70, requestline created, cseq method set, cseq sequence is 1, from and from tag set, contact set, CallId created. Caller owns the returned pointer and is responsible for deleting it.

Note:
While contact is only necessary for requests that establish a dialog, those are the requests most likely created by this method, others will be generated by the dialog.
Parameters:
targetEnds up in the RequestURI and To header
fromEnds up in the From header
contactEnds up in the Contact header. Stack will not change this when sent.
methodType of request to create. Methos is used in the Request Line and the CSeq.
Returns:
SipMessage request created. Caller must deallocate.

Definition at line 117 of file Helper.cxx.

References computeCallId(), computeTag(), resip::RequestLine::method(), resip::ParserCategory::param(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

Referenced by main(), and makeInvite().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(method);
   rLine.uri() = target.uri();
   request->header(h_To) = target;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = method;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = from;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_Contacts).push_back(contact);
   request->header(h_CallId).value() = Helper::computeCallId();
   //request->header(h_ContentLength).value() = 0;
   
   Via via;
   request->header(h_Vias).push_back(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeRequest ( const NameAddr target,
const NameAddr from,
MethodTypes  method 
) [static]

Make a new request.

To, maxforward=70, requestline created, cseq method set, cseq sequence is 1, from and from tag set, CallId created. Caller owns the returned pointer and is responsible for deleting it.

Note:
An empty contact header is added. This signals to the stack that it should be populated by the transports when sent.
Parameters:
targetEnds up in the RequestURI and To header
fromEnds up in the From header
methodType of request to create. Methos is used in the Request Line and the CSeq.
Returns:
SipMessage request created. Caller must deallocate.

Definition at line 140 of file Helper.cxx.

{
   NameAddr contact;
   return makeRequest(target, from, contact, method);
}
void Helper::makeResponse ( SipMessage response,
const SipMessage request,
int  responseCode,
const Data reason = Data::Empty,
const Data hostname = Data::Empty,
const Data warning = Data::Empty 
) [static]

Make a response to a provided request.

Adds a To tag, Contact and Record-Route headers appropriately.

Parameters:
responseSipMessage populated with the appropriate response
requestSipMessage request from which to generate the response
responseCodeResponse code to use on status line.
reasonOptional reason string to use on status line. If not provided then a default reason string will be added for well defined response codes.
hostnameOptional hostname to use in Warning header. Only used if warning is also provided.
warningOptional warning text. If present a Warning header is added and hostname is used in warning header.

Definition at line 366 of file Helper.cxx.

References resip::Message::brief(), resip::WarningCategory::code(), computeTag(), resip::SipMessage::const_header(), DebugLog, resip::Data::empty(), resip::SipMessage::exists(), resip::SipMessage::getRFC2543TransactionId(), resip::SipMessage::header(), resip::WarningCategory::hostname(), resip::SipMessage::isExternal(), resip::LazyParser::isWellFormed(), resip::RequestLine::method(), resip::SipMessage::setFromExternal(), resip::SipMessage::setFromTU(), resip::SipMessage::setRFC2543TransactionId(), resip::Data::size(), tagSize, and resip::WarningCategory::text().

Referenced by doit(), resip::TransactionState::handleBadRequest(), main(), resip::TransactionState::make100(), make405(), makeChallenge(), resip::Transport::makeFailedResponse(), resip::TransactionState::processClientInvite(), resip::TransactionState::processClientNonInvite(), resip::TuIM::processMessageRequest(), resip::TransactionState::processNoDnsResults(), resip::TuIM::processNotifyRequest(), resip::TuIM::processRegisterRequest(), resip::TransactionState::processServerInvite(), resip::TransactionState::processServerNonInvite(), resip::TransactionState::processSipMessageAsNew(), resip::TransactionState::processTransportFailure(), resip::TransactionController::send(), resip::TransactionState::sendToTU(), and Server::thread().

{
   DebugLog(<< "Helper::makeResponse(" << request.brief() << " code=" << responseCode << " reason=" << reason);
   response.header(h_StatusLine).responseCode() = responseCode;
   response.header(h_From) = request.header(h_From);
   response.header(h_To) = request.header(h_To);
   response.header(h_CallId) = request.header(h_CallId);
   response.header(h_CSeq) = request.header(h_CSeq);
   response.header(h_Vias) = request.header(h_Vias);

   if (!warning.empty())
   {
      WarningCategory warn;
      warn.code() = 399;
      warn.hostname() = hostname;
      warn.text() = warning;
      response.header(h_Warnings).push_back(warn);
   }

   if(responseCode > 100 &&
      response.const_header(h_To).isWellFormed() &&
      !response.const_header(h_To).exists(p_tag))
   {
      // Only generate a To: tag if one doesn't exist.  Think Re-INVITE.   
      // No totag for failure responses or 100s   
      // ?bwc? Should we be generating to-tags for failure responses or not?
      // The comments say no, but the code says yes. Which is it?
      response.header(h_To).param(p_tag) = Helper::computeTag(Helper::tagSize);
   }

   // .bwc. This will only throw if the topmost Via is malformed, and that 
   // should have been caught at the transport level.
   response.setRFC2543TransactionId(request.getRFC2543TransactionId());
   
   //response.header(h_ContentLength).value() = 0;
   
   if (responseCode >= 180 && responseCode < 300 && request.exists(h_RecordRoutes))
   {
      response.header(h_RecordRoutes) = request.header(h_RecordRoutes);
   }

   // .bwc. If CSeq is malformed, basicCheck would have already attempted to
   // parse it, meaning we won't throw here (we never try to parse the same
   // thing twice, see LazyParser::checkParsed())
   if (responseCode/100 == 2 &&
         !response.exists(h_Contacts) &&
         !(response.const_header(h_CSeq).method()==CANCEL) )
   {
      // in general, this should not create a Contact header since only requests
      // that create a dialog (or REGISTER requests) should produce a response with
      // a contact(s). 
      
      NameAddr contact;
      response.header(h_Contacts).push_back(contact);
   }

   if (request.isExternal())
   {
       response.setFromTU();
   }
   else
   {
       response.setFromExternal();
   }

   if (reason.size())
   {
      response.header(h_StatusLine).reason() = reason;
   }
   else
   {
      getResponseCodeReason(responseCode, response.header(h_StatusLine).reason());
   }
}

Here is the call graph for this function:

void Helper::makeResponse ( SipMessage response,
const SipMessage request,
int  responseCode,
const NameAddr myContact,
const Data reason = Data::Empty,
const Data hostname = Data::Empty,
const Data warning = Data::Empty 
) [static]

Make a response to a provided request with an overridden Contact.

Adds a To tag, Contact and Record-Route headers appropriately.

Parameters:
responseSipMessage populated with the appropriate response
requestSipMessage request from which to generate the response
responseCodeResponse code to use on status line.
myContactContact header to add to response.
reasonOptional reason string to use on status line. If not provided then a default reason string will be added for well defined response codes.
hostnameOptional hostname to use in Warning header. Only used if warning is also provided.
warningOptional warning text. If present a Warning header is added and hostname is used in warning header.

Definition at line 348 of file Helper.cxx.

References resip::LazyParser::clear(), and resip::SipMessage::header().

{
   makeResponse(response,request, responseCode, reason,hostname, warning);
   // in general, this should not create a Contact header since only requests
   // that create a dialog (or REGISTER requests) should produce a response with
   // a contact(s). 
   response.header(h_Contacts).clear();
   response.header(h_Contacts).push_back(myContact);
}

Here is the call graph for this function:

SipMessage * Helper::makeResponse ( const SipMessage request,
int  responseCode,
const Data reason = Data::Empty,
const Data hostname = Data::Empty,
const Data warning = Data::Empty 
) [static]

Make a new response to a provided request.

Adds a To tag, Contact and Record-Route headers appropriately. Caller owns the returned pointer and is responsible for deleting it.

Parameters:
requestSipMessage request from which to generate the response
responseCodeResponse code to use on status line.
reasonOptional reason string to use on status line. If not provided then a default reason string will be added for well defined response codes.
hostnameOptional hostname to use in Warning header. Only used if warning is also provided.
warningOptional warning text. If present a Warning header is added and hostname is used in warning header
Returns:
SipMessage populated with the appropriate response. Caller must deallocate.

Definition at line 470 of file Helper.cxx.

{
   // .bwc. Exception safety. Catch/rethrow is dicey because we can't rethrow
   // resip::BaseException, since it is abstract.
   std::auto_ptr<SipMessage> response(new SipMessage);
   
   makeResponse(*response, request, responseCode, reason, hostname, warning);
   return response.release();
}
SipMessage * Helper::makeResponse ( const SipMessage request,
int  responseCode,
const NameAddr myContact,
const Data reason = Data::Empty,
const Data hostname = Data::Empty,
const Data warning = Data::Empty 
) [static]

Make a new response to a provided request with an overridden Contact.

Adds a To tag, Contact and Record-Route headers appropriately. Caller owns the returned pointer and is responsible for deleting it.

Parameters:
requestSipMessage request from which to generate the response
responseCodeResponse code to use on status line.
myContactContact header to add to response.
reasonOptional reason string to use on status line. If not provided then a default reason string will be added for well defined response codes.
hostnameOptional hostname to use in Warning header. Only used if warning is also provided.
warningOptional warning text. If present a Warning header is added and hostname is used in warning header.
Returns:
SipMessage populated with the appropriate response. Caller must deallocate.

Definition at line 447 of file Helper.cxx.

{
   // .bwc. Exception safety. Catch/rethrow is dicey because we can't rethrow
   // resip::BaseException, since it is abstract.
   std::auto_ptr<SipMessage> response(new SipMessage);

   makeResponse(*response, request, responseCode, reason, hostname, warning);

   // in general, this should not create a Contact header since only requests
   // that create a dialog (or REGISTER requests) should produce a response with
   // a contact(s). 
   response->header(h_Contacts).clear();
   response->header(h_Contacts).push_back(myContact);
   return response.release();
}
Data Helper::makeResponseMD5 ( const Data username,
const Data password,
const Data realm,
const Data method,
const Data digestUri,
const Data nonce,
const Data qop = Data::Empty,
const Data cnonce = Data::Empty,
const Data cnonceCount = Data::Empty,
const Contents entityBody = 0 
) [static]

Definition at line 749 of file Helper.cxx.

References resip::Symbols::COLON, and resip::MD5Stream::getHex().

Referenced by makeChallengeResponseAuth().

{
   MD5Stream a1;
   a1 << username
      << Symbols::COLON
      << realm
      << Symbols::COLON
      << password;
 
   return makeResponseMD5WithA1(a1.getHex(), method, digestUri, nonce, qop, 
                                cnonce, cnonceCount, entity);
}

Here is the call graph for this function:

Data Helper::makeResponseMD5WithA1 ( const Data a1,
const Data method,
const Data digestUri,
const Data nonce,
const Data qop = Data::Empty,
const Data cnonce = Data::Empty,
const Data cnonceCount = Data::Empty,
const Contents entityBody = 0 
) [static]

Definition at line 703 of file Helper.cxx.

References resip::Symbols::authInt, resip::Symbols::COLON, resip::Data::empty(), resip::MD5Stream::getHex(), and noBody.

Referenced by makeChallengeResponseAuthWithA1().

{
   MD5Stream a2;
   a2 << method
      << Symbols::COLON
      << digestUri;

   if (qop == Symbols::authInt)
   {
      if (entityBody)
      {
         MD5Stream eStream;
         eStream << *entityBody;
         a2 << Symbols::COLON << eStream.getHex();
      }
      else
      {
         a2 << Symbols::COLON << noBody;
      }
   }
   
   MD5Stream r;
   r << a1
     << Symbols::COLON
     << nonce
     << Symbols::COLON;

   if (!qop.empty())
   {
      r << cnonceCount
        << Symbols::COLON
        << cnonce
        << Symbols::COLON
        << qop
        << Symbols::COLON;
   }
   r << a2.getHex();

   return r.getHex();
}

Here is the call graph for this function:

SipMessage * Helper::makeSubscribe ( const NameAddr target,
const NameAddr from,
const NameAddr contact 
) [static]

Create a Subscribe request with an overriden Contact. See makeRequest.

Definition at line 293 of file Helper.cxx.

References computeCallId(), computeTag(), resip::RequestLine::method(), resip::ParserCategory::param(), tagSize, resip::RequestLine::uri(), and resip::NameAddr::uri().

{
   std::auto_ptr<SipMessage> request(new SipMessage);
   RequestLine rLine(SUBSCRIBE);
   rLine.uri() = target.uri();

   request->header(h_To) = target;
   request->header(h_RequestLine) = rLine;
   request->header(h_MaxForwards).value() = 70;
   request->header(h_CSeq).method() = SUBSCRIBE;
   request->header(h_CSeq).sequence() = 1;
   request->header(h_From) = from;
   request->header(h_From).param(p_tag) = Helper::computeTag(Helper::tagSize);
   request->header(h_CallId).value() = Helper::computeCallId();
   assert(!request->exists(h_Contacts) || request->header(h_Contacts).empty());
   request->header(h_Contacts).push_front( contact );
   Via via;
   request->header(h_Vias).push_front(via);
   
   return request.release();
}

Here is the call graph for this function:

SipMessage * Helper::makeSubscribe ( const NameAddr target,
const NameAddr from 
) [static]

Create a Subscribe request with an empty Contact. See makeRequest.

Definition at line 286 of file Helper.cxx.

{
   NameAddr contact;
   return makeSubscribe(target, from, contact);
}
Uri Helper::makeUri ( const Data aor,
const Data scheme = Symbols::DefaultSipScheme 
) [static]

Definition at line 1602 of file Helper.cxx.

References resip::Symbols::COLON, resip::Data::Preallocate, resip::Data::prefix(), and resip::Data::size().

{
   assert(!aor.prefix("sip:"));
   assert(!aor.prefix("sips:"));
   
   Data tmp(aor.size() + scheme.size() + 1, Data::Preallocate);
   tmp += scheme;
   tmp += Symbols::COLON;
   tmp += aor;
   Uri uri(tmp);
   return uri;
}

Here is the call graph for this function:

SipMessage * Helper::makeWWWChallenge ( const SipMessage request,
const Data realm,
bool  useAuth = true,
bool  stale = false 
) [static]

Definition at line 1273 of file Helper.cxx.

{
   return makeChallenge(request,realm,useAuth,stale,false);
}
void Helper::massageRoute ( const SipMessage request,
NameAddr route 
) [static]

Definition at line 1634 of file Helper.cxx.

References resip::SipMessage::empty(), resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::LazyParser::isWellFormed(), resip::ParserCategory::param(), resip::Uri::scheme(), resip::RequestLine::uri(), and resip::NameAddr::uri().

{
   assert(request.isRequest());
   // .bwc. Let's not record-route with a tel uri or something, shall we?
   // If the topmost route header is malformed, we can get along without.
   if (!request.empty(h_Routes) && 
       request.header(h_Routes).front().isWellFormed() &&
       (request.header(h_Routes).front().uri().scheme() == "sip" ||
        request.header(h_Routes).front().uri().scheme() == "sips" ))
   {
      rt.uri().scheme() = request.header(h_Routes).front().uri().scheme();
   }
   else if(request.header(h_RequestLine).uri().scheme() == "sip" ||
           request.header(h_RequestLine).uri().scheme() == "sips")
   {
      rt.uri().scheme() = request.header(h_RequestLine).uri().scheme();
   }
   
   rt.uri().param(p_lr);
}

Here is the call graph for this function:

void Helper::processStrictRoute ( SipMessage request) [static]

Definition at line 1616 of file Helper.cxx.

References resip::SipMessage::const_header(), resip::Uri::exists(), resip::SipMessage::exists(), resip::SipMessage::hasForceTarget(), resip::SipMessage::header(), resip::SipMessage::setForceTarget(), and resip::RequestLine::uri().

Referenced by resip::DeprecatedDialog::makeRequestInternal(), and resip::DeprecatedDialog::updateRequest().

{
   if (request.exists(h_Routes) && 
       !request.const_header(h_Routes).empty() &&
       !request.const_header(h_Routes).front().uri().exists(p_lr))
   {
      // The next hop is a strict router.  Move the next hop into the
      // Request-URI and move the ultimate destination to the end of the
      // route list.  Force the message target to be the next hop router.
      request.header(h_Routes).push_back(NameAddr(request.const_header(h_RequestLine).uri()));
      request.header(h_RequestLine).uri() = request.const_header(h_Routes).front().uri();
      request.header(h_Routes).pop_front(); // !jf!
      assert(!request.hasForceTarget());
      request.setForceTarget(request.const_header(h_RequestLine).uri());
   }
}

Here is the call graph for this function:

Data Helper::qopOption ( const Auth challenge) [static]

Definition at line 1428 of file Helper.cxx.

References resip::Symbols::COMMA, resip::Data::data(), resip::Data::empty(), resip::Data::Empty, resip::Auth::exists(), resip::ParserCategory::param(), preferredTokens, pTokenSize, resip::Data::size(), and resip::ParseBuffer::skipWhitespace().

{
   bool found = false;
   size_t index = pTokenSize;
   if (challenge.exists(p_qopOptions) && !challenge.param(p_qopOptions).empty())
   {
      ParseBuffer pb(challenge.param(p_qopOptions).data(), challenge.param(p_qopOptions).size());
      do
      {
         const char* anchor = pb.skipWhitespace();
         pb.skipToChar(Symbols::COMMA[0]);
         Data q;
         pb.data(q, anchor);
         if (!pb.eof())
            pb.skipChar();
         for (size_t i=0; i < pTokenSize; i++) 
         {
            if (q == preferredTokens[i]) 
            {
               // found a preferred token; is it higher priority?
               if (i < index) 
               {
                  found = true;
                  index = i;
               }
            }
         }
      }
      while(!pb.eof());
   }

   if (found)
      return preferredTokens[index];

   return Data::Empty;
   
}

Here is the call graph for this function:

void Helper::setNonceHelper ( NonceHelper nonceHelper) [static]

Note: Helper assumes control of NonceHelper object and will delete when global scope is cleaned up.

Definition at line 679 of file Helper.cxx.

{
   mNonceHelperPtr.mNonceHelper = nonceHelper;
}
void Helper::updateNonceCount ( unsigned int &  nonceCount,
Data nonceCountString 
) [static]

Definition at line 1310 of file Helper.cxx.

References DebugLog, and resip::Data::empty().

{
   if (!nonceCountString.empty())
   {
      return;
   }
   nonceCount++;
   {
      //DataStream s(nonceCountString);
      
      //s << std::setw(8) << std::setfill('0') << std::hex << nonceCount;
           char buf[128];
           *buf = 0;

#if (defined(_MSC_VER) && _MSC_VER >= 1400)
           sprintf_s(buf,128,"%08x",nonceCount);
#else
           sprintf(buf,"%08x",nonceCount);
#endif
           nonceCountString = buf;
   }
   DebugLog(<< "nonceCount is now: [" << nonceCountString << "]");
}

Here is the call graph for this function:

bool Helper::validateMessage ( const SipMessage message,
resip::Data reason = 0 
) [static]

Definition at line 1705 of file Helper.cxx.

References DebugLog, resip::SipMessage::empty(), resip::SipMessage::header(), InfoLog, resip::SipMessage::isRequest(), resip::LazyParser::isWellFormed(), and resip::RequestLine::method().

Referenced by resip::Transport::basicCheck().

{
   if (message.empty(h_To) || 
       message.empty(h_From) || 
       message.empty(h_CSeq) || 
       message.empty(h_CallId) || 
       message.empty(h_Vias) ||
       message.empty(h_Vias))
   {
      InfoLog(<< "Missing mandatory header fields (To, From, CSeq, Call-Id or Via)");
      DebugLog(<< message);
      if(reason) *reason="Missing mandatory header field";
      return false;
   }
   else
   {
      if(!message.header(h_CSeq).isWellFormed())
      {
         InfoLog(<<"Malformed CSeq header");
         if(reason) *reason="Malformed CSeq header";
         return false;
      }
      
      if(!message.header(h_Vias).front().isWellFormed())
      {
         InfoLog(<<"Malformed topmost Via header");
         if(reason) *reason="Malformed topmost Via header";
         return false;
      }
      
      if (message.isRequest())
      {
         if(!message.header(h_RequestLine).isWellFormed())
         {
            InfoLog(<< "Illegal request line");
            if(reason) *reason="Malformed Request Line";
            return false;            
         }
         
         if(message.header(h_RequestLine).method()!=message.header(h_CSeq).method())
         {
            InfoLog(<< "Method mismatch btw Request Line and CSeq");
            if(reason) *reason="Method mismatch btw Request Line and CSeq";
            return false;
         }
      }
      else
      {
         if(!message.header(h_StatusLine).isWellFormed())
         {
            InfoLog(<< "Malformed status line");
            if(reason) *reason="Malformed status line";
            return false;            
         }
      }
      
      return true;
   }
}

Here is the call graph for this function:


Member Data Documentation

Definition at line 581 of file Helper.hxx.

const int Helper::tagSize = 4 [static]

bytes in to-tag& from-tag, should prob. live somewhere else

Definition at line 48 of file Helper.hxx.

Referenced by makeMessage(), makePublish(), makeRegister(), makeRequest(), resip::DeprecatedDialog::makeResponse(), makeResponse(), and makeSubscribe().


The documentation for this class was generated from the following files: