📄 sipmessage.cxx
字号:
/* Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* * Authors: Erik Eliasson <eliasson@it.kth.se> * Johan Bilien <jobi@via.ecp.fr>*//* Name * SipMessage.cxx * Author * Erik Eliasson, eliasson@it.kth.se * Purpose * */#include<config.h>#include<stdio.h>#include<libmsip/SipMessage.h>#include<errno.h>#include<ctype.h>#include<libmnetutil/Socket.h>#include<libmsip/SipMessageContentFactory.h>#include<libmsip/SipHeaderContentLength.h>#include<libmsip/SipHeaderVia.h>#include<libmsip/SipHeaderFrom.h>#include<libmsip/SipHeaderTo.h>#include<libmsip/SipHeaderCSeq.h>#include<libmsip/SipHeaderCallID.h>#include<libmsip/SipHeaderContentLength.h>#include<libmsip/SipHeaderContact.h>#include<libmsip/SipHeaderRecordRoute.h>#include<libmsip/SipHeaderRoute.h>#include<libmsip/SipHeaderRequire.h>#include<libmsip/SipHeaderSupported.h>#include<libmsip/SipHeaderContentType.h>#include<libmsip/SipHeaderWWWAuthenticate.h>#include<libmsip/SipHeaderWarning.h>#include<libmsip/SipRequest.h>#include<libmsip/SipResponse.h>#include<libmsip/SipUtils.h>#include<libmsip/SipMessageContentIM.h>#include<libmsip/SipException.h>#include<libmutil/trim.h>#include<libmutil/dbg.h>#include<libmutil/itoa.h>#include<libmutil/Timestamp.h>using namespace std;const string SipMessage::anyType="";#if defined(_MSC_VER) && !defined(_WIN32_WCE) template class __declspec(dllexport) MRef<SipMessage*>;#endifMRef<SipMessageContent*> sipSipMessageContentFactory(const string & buf, const string &){ string tmp = buf; return (*SipMessage::createMessage(tmp));}SMCFCollection SipMessage::contentFactories=SMCFCollection();string SipMessage::getDescription(){ string ret; ret = getType(); if (ret=="RESPONSE") ret +="_"+itoa(((SipResponse*)(this))->getStatusCode()); return ret;}SipMessage::~SipMessage(){}MRef<SipMessage*> SipMessage::createMessage(string &data){ size_t n = data.size(); if (n>3 && (data[0]=='S'||data[0]=='s') && (data[1]=='I'||data[1]=='i') && (data[2]=='P'||data[2]=='p' )){ return MRef<SipMessage*>(new SipResponse(data)); }else{ return new SipRequest(data);#if 0 if (n> 7 && data.substr(0, 7) == "MESSAGE"){ //return MRef<SipMessage*>(new SipIMMessage(data)); return new SipRequest(TYPE_SIP_MESSAGE_IMMESSAGE, data); } if (n> 6 && data.substr(0, 6) == "CANCEL"){ //return MRef<SipMessage*>(new SipCancel(data)); return new SipRequest(TYPE_SIP_MESSAGE_CANCEL, data); } if (n> 3 && data.substr(0, 3)=="BYE"){ //return MRef<SipMessage*>(new SipBye(data)); return new SipRequest(TYPE_SIP_MESSAGE_BYE, data); } if (n> 6 && data.substr(0, 6)=="INVITE"){ //return MRef<SipMessage*>(new SipInvite(data)); return new SipRequest(TYPE_SIP_MESSAGE_INVITE, data); } if (n> 3 && data.substr(0, 3)=="ACK"){ //return MRef<SipMessage*>(new SipAck(data)); return MRef<SipMessage*>(new SipRequest(TYPE_SIP_MESSAGE_ACK,data)); } if (n> 9 && data.substr(0, 9)=="SUBSCRIBE"){ //return MRef<SipMessage*>(new SipSubscribe(data)); return new SipRequest(TYPE_SIP_MESSAGE_SUBSCRIBE, data); } if (n> 6 && data.substr(0, 6)=="NOTIFY"){ //return MRef<SipMessage*>(new SipNotify(data)); return new SipRequest(TYPE_SIP_MESSAGE_NOTIFY, data); } if (n> 5 && data.substr(0, 5)=="REFER"){ //return MRef<SipMessage*>(new SipRefer(data)); return new SipRequest(TYPE_SIP_MESSAGE_REFER, data); } return MRef<SipMessage*>( new SipRequest( data ));#endif } return NULL;}ostream & operator<<(ostream &out, SipMessage &p){ out << p.getDescription(); return out;}SipMessage::SipMessage(string b):branch(b){ content=NULL;}void SipMessage::addHeader(MRef<SipHeader*> header){ if( header.isNull() ) { merr << "ERROR: trying to add null header to message!"<<end; return; } headers.push_back(header);}MRef<SipHeader*> SipMessage::getHeaderNo(int i){ if (i>=headers.size()){ MRef<SipHeader*> nullhdr; return nullhdr; } return headers[i];}int SipMessage::getNoHeaders(){ return headers.size();}int32_t SipMessage::getContentLength(){ for (int32_t i=0; i< headers.size(); i++){ MRef<SipHeaderValueContentLength*> len; if ((headers[i])->getType() == SIP_HEADER_TYPE_CONTENTLENGTH){ len = MRef<SipHeaderValueContentLength*>((SipHeaderValueContentLength*)*(headers[i]->getHeaderValue(0))); return len->getContentLength(); } } return 0;}string SipMessage::getHeadersAndContent(){ string req=""; int32_t clen=-1; for (int32_t i=0; i< headers.size(); i++){ req=req+headers[i]->getString()+"\r\n"; if ((headers[i])->getType() == SIP_HEADER_TYPE_CONTENTLENGTH){ clen=0; } } if (clen<0){ if ( !content.isNull()) clen=(int)content->getString().length(); else clen=0; SipHeader content_length(new SipHeaderValueContentLength(clen)); req=req+content_length.getString()+"\r\n"; } req=req+"\r\n"; if ( !content.isNull()){ req=req + content->getString(); } return req;}/** * @return Index where the content of the message starts (if any) */int SipMessage::parseHeaders(const string &buf, int startIndex){ int i=startIndex; int endBuf = (int)buf.size(); //This filters the sipfrag messages we receive ... like in NOTIFY ... which most of the times come without any header if( startIndex + 4 >= endBuf ) { #ifdef DEBUG_OUTPUT mdbg << "SipMessage::parseHeaders: Info: SipMessage without headers ... only request line" << end; #endif return i; } do{ if (i+2<=endBuf && buf[i]=='\n' && buf[i+1]=='\n') { // i points to first after header return i+2; // return pointer to start of content } if (i+4<=endBuf && buf[i]=='\r' && buf[i+1]=='\n' && buf[i+2]=='\r' && buf[i+3]=='\n' ){ // i points to first after header return i+4; // return pointer to start of content } if (i+4<=endBuf && buf[i]=='\n' && buf[i+1]=='\r' && buf[i+2]=='\n' && buf[i+3]=='\r' ){ // i points to first after header return i+4; // return pointer to start of content } int eoh = SipUtils::findEndOfHeader(buf, i); // i will be adjusted to start of header string header = buf.substr(i, eoh-i+1);// merr << "SipMessage::parseHeaders: parsing line = ##" << header // << "## [end=" << endBuf << "; i="<< i // << "; eoh=" << eoh << "; length=" // << eoh-i+1 << "]" << end; if( header == "" ) { #ifdef DEBUG_OUTPUT mdbg << "SipMessage::parseHeaders: Info: Could not copy line to new Message: (empty line)" << end; #endif } else if (!addLine(header)){ #ifdef DEBUG_OUTPUT mdbg << "SipMessage::parseHeaders: Info: Could not copy line to new Message: " << header << " (unknown)" << end; #endif } i=eoh+1; }while (i<endBuf); return i;}SipMessage::SipMessage(int, string &buildFrom){ uint32_t i; //string header; for (i=0; buildFrom[i]!='\r' && buildFrom[i]!='\n'; i++){ if(i==buildFrom.size()){#ifdef DEBUG_OUTPUT cerr << "SipMessage::SipMessage: Size is too short - throwing exception"<< endl;#endif throw SipExceptionInvalidMessage("SIP Message too short"); } //header = header + buildFrom[i]; } int contentStart = parseHeaders(buildFrom, i); int clen = getContentLength(); if (clen>0){ string content=buildFrom.substr(contentStart, clen); if ((int)content.length() != clen){ cerr << "WARNING: Length of content was shorter than expected (" << clen <<"!="<<(int)content.length()<<")"<<endl; } MRef<SipHeader*> h = getHeaderOfType(SIP_HEADER_TYPE_CONTENTTYPE); if (h){ MRef<SipMessageContent*> smcref; string contentType = ((SipHeaderValueString*)*(h->getHeaderValue(0) ))->getString();// string b = (SipHeaderValueContentType*)*(h->getHeaderValue(0) )->getParameter("boundary");//cerr <<"boundary="<< b <<endl; SipMessageContentFactoryFuncPtr contentFactory = contentFactories.getFactory( contentType ); if (contentFactory){ MRef<SipMessageContent*> smcref = contentFactory(content, contentType + "; boundary=boun=_dry"); setContent(smcref); }else{ //TODO: Better error handling merr << "WARNING: No SipMessageContentFactory found for content type "<<contentType <<end; } }else{ //TODO: Better error handling merr << "WARNING: Sip message has content, but no content type! Content ignored."<< end; } } branch = getLastViaBranch();}bool SipMessage::addLine(string line){ //ts.save("SipMessage-creating header start"); MRef<SipHeader*> hdr = SipHeader::parseHeader(line); //ts.save("SipMessage-creating header end"); if( hdr.isNull() ) //do not add if null return false; addHeader(hdr);#if 0 string ln = line; //Hack to get realm an nonce... FIXME if (/*getType()==SipResponse::type &&*/ (SipUtils::startsWith(ln,"Proxy-Authenticate:") || SipUtils::startsWith(ln,"WWW-Authenticate")) ){ size_t r_pos = ln.find("realm="); size_t n_pos = ln.find("nonce="); if (r_pos == string::npos || n_pos ==string::npos){ merr << "ERROR: could not extract nonce and realm in line: " << ln << end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -