/* * Copyright 2008 Free Software Foundation, Inc. * Copyright 2014 Range Networks, Inc. * * This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #define LOG_GROUP LogGroup::SIP // Can set Log.Level.SIP for debugging. If there were any LOG() calls in this file. #include #include #include #include #include #include #include #include "SIPUtility.h" #include #include // #include // (pat 3-2014) Take this out temporarily to avoid referencing gBTS from the SIP directory. //#include "md5.h" namespace SIP { using namespace std; //using namespace MD5; string localIP() { // Replaces mSIPIP. return gConfig.getStr("SIP.Local.IP"); } string localIPAndPort() { // Replaces mSIPIP and mSIPPort. return format("%s:%u", localIP(), (unsigned) gConfig.getNum("SIP.Local.Port")); } // Unused, but here it is if you want it: // Pair is goofed up, so just make our own. It is trivial: // //template //struct Pair { // T1 first; // T2 second; // Pair(T1 a, T2 b) : first(a), second(b) {} //}; //template //Pair make_pair(T1 x, T2 y) //{ // return Pair(x,y); //} //typedef Pair SipParam; // Used for both params and 'headers', which is stuff in a URI. #if 0 // Dont bother. Added isINVITE(), isACK(), etc. // Note that all methods establish a new transaction, including ACK. // This is still not handled correctly. enum SipMethodType { MethodUndefined, MethodACK, MethodBYE, MethodCANCEL, MethodINVITE, MethodMESSAGE, MethodOPTIONS, MethodINFO, MethodREFER, MethodNOTIFY, MethodSUBSCRIBE, MethodPRACK, MethodUPDATE, MethodREGISTER, MethodPUBLISH }; typedef std::pair SipMethodPair; typedef std::map SipMethodMap; static SipMethodMap gMethodMap; SIPMethodType SipMessage::str2MethodType(string &methodname) { if (gMethodMap.size() == 0) { // init the map #define HELPER_ONE_SIP_METHOD(name) gMethodMap.insert(SipMethodPair(#name, Method##name)); HELPER_ONE_SIP_METHOD(ACK) HELPER_ONE_SIP_METHOD(BYE) HELPER_ONE_SIP_METHOD(CANCEL) HELPER_ONE_SIP_METHOD(INVITE) HELPER_ONE_SIP_METHOD(MESSAGE) HELPER_ONE_SIP_METHOD(OPTIONS) HELPER_ONE_SIP_METHOD(INFO) HELPER_ONE_SIP_METHOD(REFER) HELPER_ONE_SIP_METHOD(NOTIFY) HELPER_ONE_SIP_METHOD(SUBSCRIBE) HELPER_ONE_SIP_METHOD(PRACK) HELPER_ONE_SIP_METHOD(UPDATE) HELPER_ONE_SIP_METHOD(REGISTER) HELPER_ONE_SIP_METHOD(PUBLISH) gMethodMap.insert(SipMethodPair("",MethodUndefined)); // empty string maps to Undefined method. } //for (SipMethodMap::iterator i = gMethodMap.begin(); i != gMethodMap.end(); ++i) { // printf("SipMethodMap %s = %d\n",i->first,i->second); //} if (methodname == NULL) { return MethodUndefined; } SipMethodMap::iterator it = gMethodMap.find(methodname); if (it == gMethodMap.end()) { printf("MethodMap %s not found\n",methodname); } return it == gMethodMap.end() ? MethodUndefined : it->second; } SIPMethodType SipMessage::smGetMethod() const { if (omsg()->sip_method == NULL) { return MethodUndefined; // Hmm. } string methname(smGetMethodName()); SIPMethodType result = str2MethodType(methname); LOG(DEBUG)<second; } // On success, set the resolved address stuff, mipValid, and return true. bool IPAddressSpec::ipSet(string addrSpec, const char * provenance) { mipName = addrSpec; // (pat 7-230-2013) Someone else added this, I am preserving it: // Check for illegal hostname length. 253 bytes for domain name + 6 bytes for port and colon. // This isn't "pretty", but it should be fast, and gives us a ballpark. Their hostname will // fail elsewhere if it is longer than 253 bytes (since this assumes a 5 byte port string). if (addrSpec.size() == 0) { LOG(ALERT) << "hostname is empty from "< 259) { LOG(ALERT) << "hostname is greater than 253 bytes from "<26] to [a-z] strcpy(tag,start); char *cp = tag+strlen(start); for (int k=0; k<16; k++) { *cp++ = val%26+'a'; val = val >> 4; } *cp = '\0'; return string(tag); } string make_tag() { return make_tag1("OBTS"); } string make_branch(const char * /*hint*/) // hint is unused. { // RFC3261 17.2.3: The branch parameter should begin with the magic string "z9hG4bK" to // indicate compliance with this specification. return make_tag1("z9hG4bKOBTS"); } string dequote(const string in) { if (in[0] != '"') return in; if (in.size() < 2 || in[in.size() - 1] != '"') { LOG(ERR) << "Invalid quoted string:"< (input.c_str()), input.size()); //MD5_hexdigest(&ctx,buffer); //string str = buffer; // //return str; // alternative to including md5 code in the project, kind of funky but it works for now ostringstream os; os << "echo -n \"" << input << "\" | md5sum | cut -d \" \" -f1"; FILE *f = popen(os.str().c_str(), "r"); if (f == NULL) { LOG(CRIT) << "error: popen failed"; return ""; } char digest[33]; char *buffer = fgets(digest, 33, f); if (buffer != NULL && strlen(buffer) == 33) buffer[32] = 0; if (buffer == NULL || strlen(buffer) != 32) { LOG(CRIT) << "error: popen result failed"; } int st = pclose(f); if (st == -1) { LOG(CRIT) << "error: pclose failed"; } string str = buffer; return str; } string makeResponse(string username, string realm, string password, string method, string uri, string nonce) { static const string separatorStr(":"); string str1 = makeMD5( username + separatorStr + realm + separatorStr + password); string str2 = makeMD5( method + separatorStr + uri); string str3 = makeMD5( str1 + separatorStr + nonce + separatorStr + str2); return str3; } // We will accept prefix or "sips:", which we dont support yet, but ever hopeful. const char * sipSkipPrefix1(const char* in) { if (0 == strncasecmp(in,"sip:",4)) { return in + 4; } else if (0 == strncasecmp(in,"tel:",4)) { return in + 4; } else if (0 == strncasecmp(in,"sips:",5)) { return in + 5; } return in; } string sipSkipPrefix(string in) { if (0 == strncasecmp(in.c_str(),"sip:",4)) { return in.substr(4); } else if (0 == strncasecmp(in.c_str(),"tel:",4)) { return in.substr(4); } else if (0 == strncasecmp(in.c_str(),"sips:",5)) { return in.substr(5); } return in; } }; // namespace SIP // vim: ts=4 sw=4