/* * Copyright (C) 2005 Luca Veltri - University of Parma - Italy * * This file is part of MjSip (http://www.mjsip.org) * * MjSip is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MjSip 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MjSip; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author(s): * Luca Veltri (luca.veltri@unipr.it) */ package org.zoolu.sip.message; import org.zoolu.sip.provider.*; import org.zoolu.sip.header.*; import org.zoolu.sip.address.*; import org.zoolu.sip.message.SipMethods; import org.zoolu.net.UdpPacket; import java.util.*; /** Class BaseMessage implements a generic SIP Message. */ public abstract class BaseMessage { /** UDP */ public static final String PROTO_UDP="udp"; /** TCP */ public static final String PROTO_TCP="tcp"; /** TLS */ public static final String PROTO_TLS="tls"; /** SCTP */ public static final String PROTO_SCTP="sctp"; /** Maximum receiving packet size */ protected static int MAX_PKT_SIZE=8000; /** The remote ip address */ protected String remote_addr; /** The remote port */ protected int remote_port; /** Transport protocol */ protected String transport_proto; /** Connection identifier */ protected ConnectionIdentifier connection_id; /** Packet length */ //protected int packet_length; /** The message string */ private String message; /** Inits empty Message */ private void init() { //message=""; remote_addr=null; remote_port=0; transport_proto=null; connection_id=null; } /** Costructs a new empty Message */ public BaseMessage() { init(); message=""; } /** Costructs a new Message */ public BaseMessage(byte[] data, int offset, int len) { init(); message=new String(data,offset,len); } /** Costructs a new Message */ public BaseMessage(UdpPacket packet) { init(); message=new String(packet.getData(),packet.getOffset(),packet.getLength()); } /** Costructs a new Message */ public BaseMessage(String str) { init(); message=new String(str); } /** Costructs a new Message */ public BaseMessage(BaseMessage msg) { //message=new String(msg.message); message=msg.message; remote_addr=msg.remote_addr; remote_port=msg.remote_port; transport_proto=msg.transport_proto; connection_id=msg.connection_id; //packet_length=msg.packet_length; } /** Creates and returns a clone of the Message */ abstract public Object clone(); //{ return new Message(message); //} /** Sets the entire message */ public void setMessage(String message) { this.message=message; } /** Gets string representation of Message */ public String toString() { return message; } /** Gets remote ip address */ public String getRemoteAddress() { return remote_addr; } /** Gets remote port */ public int getRemotePort() { return remote_port; } /** Gets transport protocol */ public String getTransportProtocol() { return transport_proto; } /** Gets connection identifier */ public ConnectionIdentifier getConnectionId() { return connection_id; } /** Gets message length */ public int getLength() { return message.length(); } /** Sets remote ip address */ public void setRemoteAddress(String addr) { remote_addr=addr; } /** Sets remote port */ public void setRemotePort(int port) { remote_port=port; } /** Sets transport protocol */ public void setTransport(String proto) { transport_proto=proto; } /** Sets connection identifier */ public void setConnectionId(ConnectionIdentifier conn_id) { connection_id=conn_id; } /** Gets the inique DialogIdentifier for an INCOMING message */ public DialogIdentifier getDialogId() { String call_id=getCallIdHeader().getCallId(); String local_tag, remote_tag; if (isRequest()) { local_tag=getToHeader().getTag(); remote_tag=getFromHeader().getTag(); } else { local_tag=getFromHeader().getTag(); remote_tag=getToHeader().getTag(); } return new DialogIdentifier(call_id,local_tag,remote_tag); } /** Gets the inique TransactionIdentifier */ public TransactionIdentifier getTransactionId() { String call_id=getCallIdHeader().getCallId(); ViaHeader top_via=getViaHeader(); String branch=null; if (top_via.hasBranch()) branch=top_via.getBranch(); String sent_by=top_via.getSentBy(); CSeqHeader cseqh=getCSeqHeader(); long seqn=cseqh.getSequenceNumber(); String method=cseqh.getMethod(); return new TransactionIdentifier(call_id,seqn,method,sent_by,branch); } /** Gets the MethodIdentifier */ public MethodIdentifier getMethodId() { String method=getCSeqHeader().getMethod(); return new MethodIdentifier(method); } //**************************** Requests ****************************/ /** Whether Message is a Request */ public boolean isRequest() throws NullPointerException { // Req-Line = Method ' ' SIP-URL ' ' "SIP/2.0" CRLF if (message==null || isResponse()) return false; String firstline=(new SipParser(message)).getLine(); String version=(new SipParser(firstline)).skipString().skipString().getString(); if (version==null || version.length()<4) return false; version=version.substring(0,4); String target="SIP/"; //if (version.compareToIgnoreCase(target)==0) return true; if (version.equalsIgnoreCase(target)) return true; return false; } /** Whether Message is a <i>method</i> request */ public boolean isRequest(String method) { //if (message==null) return false; if (message.startsWith(method)) return true; else return false; } /** Whether Message is a Method that creates a dialog */ public boolean createsDialog() { if (!isRequest()) return false; //else String method=getRequestLine().getMethod(); for (int i=0; i<SipMethods.dialog_methods.length; i++) if (method.equalsIgnoreCase(SipMethods.dialog_methods[i])) return true; //else return false; } /** Whether Message is an Invite */ public boolean isInvite() { return isRequest(SipMethods.INVITE); } /** Whether Message is a Register */ public boolean isRegister() { return isRequest(SipMethods.REGISTER); } /** Whether Message is a Cancel */ public boolean isCancel() { return isRequest(SipMethods.CANCEL); } /** Whether Message is a Bye */ public boolean isBye() { return isRequest(SipMethods.BYE); } /** Whether Message is an Ack */ public boolean isAck() { return isRequest(SipMethods.ACK); } /** Whether Message is an Info */ public boolean isInfo() { return isRequest(SipMethods.INFO); } /** Whether Message is an Option */ public boolean isOption() { return isRequest(SipMethods.OPTION); } /** Whether Message has Request-line */ protected boolean hasRequestLine() { return isRequest(); } /** Gets RequestLine in Message (Returns null if called for no request message) */ public RequestLine getRequestLine() { if (!isRequest()) { //printWarning("getRequestLine(): called for no request message\n",1); return null; } SipParser par=new SipParser(message); String method=par.getString(); par.skipWSP(); par=new SipParser(par.subParser(par.indexOfEOH()-par.getPos())); return new RequestLine(method,par.getSipURL()); } /** Sets RequestLine of the Message */ public void setRequestLine(RequestLine rl) { if (hasRequestLine()) removeRequestLine(); String value=rl.toString(); message=value+message; } /** Removes RequestLine of the Message */ public void removeRequestLine() { if(!isRequest()) return; removeFirstLine(); } //**************************** Responses ****************************/ /** Whether Message is a Response */ public boolean isResponse() throws NullPointerException { // Status-Line = "SIP/2.0" ' ' Status-Code ' 'Reason-Phrase" CRLF //if (message==null) return false; if (message==null || message.length()<4) return false; String version=message.substring(0,4); String target="SIP/"; //if (version.compareToIgnoreCase(target)==0) return true; if (version.equalsIgnoreCase(target)) return true; return false; } /** Whether Message has Status-line */ protected boolean hasStatusLine() { return isResponse(); } /** Gets StautsLine in Message (Returns null if called for no response message) */ public StatusLine getStatusLine() { if (!isResponse()) { //printWarning("getStatusLine(): called for no response message\n",1); return null; } SipParser par=new SipParser(message); par.skipString().skipWSP(); // "SIP/2.0 " int code=par.getInt(); int begin=par.getPos(); int end=par.indexOfEOH(); String reason=message.substring(begin,end).trim(); return new StatusLine(code,reason); } /** Sets StatusLine of the Message */ public void setStatusLine(StatusLine sl) { if (hasStatusLine()) removeStatusLine(); message=sl.toString()+message; } /** Removes StatusLine of the Message */ public void removeStatusLine() { if(!isResponse()) return; removeFirstLine(); } //**************************** Generic Headers ****************************/ /** Returns the transaction method */ public String getTransactionMethod() { return getCSeqHeader().getMethod(); } /** Gets the first line of the Message */ public String getFirstLine() { if (isRequest()) return getRequestLine().toString(); if (isResponse()) return getStatusLine().toString(); return null; } /** Sets Request/Status Line of the Message */ /*private void setFirstLine(String value) { message=value+" \r\n"+message; } */ /** Removes Request\Status Line of the Message */ protected void removeFirstLine() { message=message.substring((new SipParser(message)).indexOfNextHeader()); } /** Whether Message has any headers of specified name */ public boolean hasHeader(String name) { Header hd=getHeader(name); if (hd==null) return false; else return true; } /** Gets the first Header of specified name (Returns null if no Header is found) */ public Header getHeader(String hname) { SipParser par=new SipParser(message); return par.getHeader(hname); } /** Gets a Vector of all Headers of specified name (Returns empty Vector if no Header is found) */ public Vector getHeaders(String hname) { Vector v=new Vector(); SipParser par=new SipParser(message); Header h; while ((h=par.getHeader(hname))!=null) { v.addElement(h); } return v; } /** Adds Header at the top/bottom. * The bottom is considered before the Content-Length and Content-Type headers */ public void addHeader(Header header, boolean top) { addHeaders(header.toString(),top); } /** Adds a Vector of Headers at the top/bottom */ public void addHeaders(Vector headers, boolean top) { String str=""; for (int i=0; i<headers.size(); i++) str+=((Header)headers.elementAt(i)).toString(); addHeaders(str,top); } /** Adds MultipleHeader(s) <i>mheader</i> at the top/bottom */ public void addHeaders(MultipleHeader mheader, boolean top) { addHeaders(mheader.toString(),top); } /** Adds a one or more Headers at the top/bottom. * The bottom is considered before the Content-Length and Content-Type headers */ protected void addHeaders(String str, boolean top) { int i,aux; if (top) { if (this.hasRequestLine() || this.hasStatusLine()) { SipParser par=new SipParser(message); par.goToNextHeader(); i=par.getPos(); } else i=0; } else { SipParser par=new SipParser(message); // index the end of headers i=par.goToEndOfLastHeader().goToNextLine().getPos(); par=new SipParser(message); // if Content_Length is present, jump before aux=par.indexOfHeader(SipHeaders.Content_Length); if (aux<i) i=aux; // if Content_Type is present, jump before aux=par.indexOfHeader(SipHeaders.Content_Type); if (aux<i) i=aux; } String head=message.substring(0,i); String tail=message.substring(i); String new_message=head.concat(str); new_message=new_message.concat(tail); message=new_message; } /** Adds Headers on position <i>index</i> within the Message */ protected void addHeaders(String str, int index) { if (index>message.length()) index=message.length(); message=message.substring(0,index)+str+message.substring(index); } /** Adds Header before the first header <i>refer_header</i> * . <p>If there is no header of such type, it is added at top */ public void addHeaderBefore(Header new_header, String refer_header) { addHeadersBefore(new_header.toString(),refer_header); } /** Adds MultipleHeader(s) before the first header <i>refer_header</i> * . <p>If there is no header of such type, they are added at top */ public void addHeadersBefore(MultipleHeader mheader, String refer_header) { addHeadersBefore(mheader.toString(),refer_header); } /** Adds Headers before the first header <i>refer_header</i> * . <p>If there is no header of such type, they are added at top */ protected void addHeadersBefore(String str, String refer_header) { if (!hasHeader(refer_header)) addHeaders(str,true); else { SipParser par=new SipParser(message); par.goTo(refer_header); int here=par.getPos(); message=message.substring(0,here)+str+message.substring(here); } } /** Adds Header after the first header <i>refer_header</i> * . <p>If there is no header of such type, it is added at bottom */ public void addHeaderAfter(Header new_header, String refer_header) { addHeadersAfter(new_header.toString(),refer_header); } /** Adds MultipleHeader(s) after the first header <i>refer_header</i> * . <p>If there is no header of such type, they are added at bottom */ public void addHeadersAfter(MultipleHeader mheader, String refer_header) { addHeadersAfter(mheader.toString(),refer_header); } /** Adds Headers after the first header <i>refer_header</i> * . <p>If there is no header of such type, they are added at bottom */ protected void addHeadersAfter(String str, String refer_header) { if (!hasHeader(refer_header)) addHeaders(str,false); else { SipParser par=new SipParser(message); par.goTo(refer_header); int here=par.indexOfNextHeader(); message=message.substring(0,here)+str+message.substring(here); } } /** Removes first Header of specified name */ public void removeHeader(String hname) { removeHeader(hname,true); } /** Removes first (or last) Header of specified name */ public void removeHeader(String hname, boolean first) { String[] target={'\n'+hname, '\r'+hname}; SipParser par=new SipParser(message); par.goTo(target); if (!par.hasMore()) return; if (!first) while(true) { int next=par.indexOf(target); if (next<0) break; par.setPos(next); } par.skipChar(); String head=message.substring(0,par.getPos()); par.goToNextHeader(); String tail=message.substring(par.getPos()); message=head.concat(tail); } /** Sets the new Header (removing any previous headers of the same name) */ /*public void setHeader(Header hd) { if (hasHeader(hd.getName())) removeAllHeaders(hd.getName()); addHeader(hd,false); }*/ /** Sets the Header <i>hd</i> removing any previous headers of the same type */ public void setHeader(Header hd) { String hname=hd.getName(); if (hasHeader(hname)) { int index=(new SipParser(message)).indexOfHeader(hname); removeAllHeaders(hname); addHeaders(hd.toString(),index); } else addHeader(hd,false); } /** Removes all Headers of specified name */ public void removeAllHeaders(String hname) { String[] target={'\n'+hname, '\r'+hname}; SipParser par=new SipParser(message); par.goTo(target); while (par.hasMore()) { par.skipChar(); String head=message.substring(0,par.getPos()); String tail=message.substring(par.indexOfNextHeader()); message=head.concat(tail); par=new SipParser(message,par.getPos()-1); par.goTo(target); } } /** Sets MultipleHeader <i>mheader</i> */ /*public void setHeaders(MultipleHeader mheader) { if (hasHeader(mheader.getName())) removeAllHeaders(mheader.getName()); addHeaders(mheader,false); }*/ /** Sets MultipleHeader <i>mheader</i> */ public void setHeaders(MultipleHeader mheader) { String hname=mheader.getName(); if (hasHeader(hname)) { int index=(new SipParser(message)).indexOfHeader(hname); removeAllHeaders(hname); addHeaders(mheader.toString(),index); } else addHeaders(mheader,false); } //**************************** Specific Headers ****************************/ /** Whether Message has MaxForwardsHeader */ public boolean hasMaxForwardsHeader() { return hasHeader(SipHeaders.Max_Forwards); } /** Gets MaxForwardsHeader of Message */ public MaxForwardsHeader getMaxForwardsHeader() { Header h=getHeader(SipHeaders.Max_Forwards); if (h==null) return null; else return new MaxForwardsHeader(h); } /** Sets MaxForwardsHeader of Message */ public void setMaxForwardsHeader(MaxForwardsHeader mfh) { setHeader(mfh); } /** Removes MaxForwardsHeader from Message */ public void removeMaxForwardsHeader() { removeHeader(SipHeaders.Max_Forwards); } /** Whether Message has FromHeader */ public boolean hasFromHeader() { return hasHeader(SipHeaders.From); } /** Gets FromHeader of Message */ public FromHeader getFromHeader() { Header h=getHeader(SipHeaders.From); if (h==null) return null; else return new FromHeader(h); } /** Sets FromHeader of Message */ public void setFromHeader(FromHeader fh) { setHeader(fh); } /** Removes FromHeader from Message */ public void removeFromHeader() { removeHeader(SipHeaders.From); } /** Whether Message has ToHeader */ public boolean hasToHeader() { return hasHeader(SipHeaders.To); } /** Gets ToHeader of Message */ public ToHeader getToHeader() { Header h=getHeader(SipHeaders.To); if (h==null) return null; else return new ToHeader(h); } /** Sets ToHeader of Message */ public void setToHeader(ToHeader th) { setHeader(th); } /** Removes ToHeader from Message */ public void removeToHeader() { removeHeader(SipHeaders.To); } /** Whether Message has ContactHeader */ public boolean hasContactHeader() { return hasHeader(SipHeaders.Contact); } /** <b>Deprecated</b>. Gets ContactHeader of Message. Use getContacts instead. */ public ContactHeader getContactHeader() { //Header h=getHeader(SipHeaders.Contact); //if (h==null) return null; else return new ContactHeader(h); MultipleHeader mh=getContacts(); if (mh==null) return null; return new ContactHeader(mh.getTop()); } /** Adds ContactHeader */ public void addContactHeader(ContactHeader ch, boolean top) { addHeader(ch,top); } /** Sets ContactHeader */ public void setContactHeader(ContactHeader ch) { if (hasContactHeader()) removeContacts(); addHeader(ch,false); } /** Gets a MultipleHeader of Contacts */ public MultipleHeader getContacts() { Vector v=getHeaders(SipHeaders.Contact); if (v.size()>0) return new MultipleHeader(v); else return null; } /** Adds Contacts */ public void addContacts(MultipleHeader contacts, boolean top) { addHeaders(contacts,top); } /** Sets Contacts */ public void setContacts(MultipleHeader contacts) { if (hasContactHeader()) removeContacts(); addContacts(contacts,false); } /** Removes ContactHeaders from Message */ public void removeContacts() { removeAllHeaders(SipHeaders.Contact); } /** Whether Message has ViaHeaders */ public boolean hasViaHeader() { return hasHeader(SipHeaders.Via); } /** Adds ViaHeader at the top */ public void addViaHeader(ViaHeader vh) { addHeader(vh,true); } /** Gets the first ViaHeader */ public ViaHeader getViaHeader() { //Header h=getHeader(SipHeaders.Via); //if (h==null) return null; else return new ViaHeader(h); MultipleHeader mh=getVias(); if (mh==null) return null; return new ViaHeader(mh.getTop()); } /** Removes the top ViaHeader */ public void removeViaHeader() { //removeHeader(SipHeaders.Via); MultipleHeader mh=getVias(); mh.removeTop(); setVias(mh); } /** Gets all Vias */ public MultipleHeader getVias() { Vector v=getHeaders(SipHeaders.Via); if (v.size()>0) return new MultipleHeader(v); else return null; } /** Adds Vias */ public void addVias(MultipleHeader vias, boolean top) { addHeaders(vias,top); } /** Sets Vias */ public void setVias(MultipleHeader vias) { if (hasViaHeader()) removeVias(); addContacts(vias,true); } /** Removes ViaHeaders from Message (if any exists) */ public void removeVias() { removeAllHeaders(SipHeaders.Via); } /** Whether Message has RouteHeader */ public boolean hasRouteHeader() { return hasHeader(SipHeaders.Route); } /** Adds RouteHeader at the top */ public void addRouteHeader(RouteHeader h) { addHeaderAfter(h,SipHeaders.Via); } /** Adds multiple Route headers at the top */ public void addRoutes(MultipleHeader routes) { addHeadersAfter(routes,SipHeaders.Via); } /** Gets the top RouteHeader */ public RouteHeader getRouteHeader() { //Header h=getHeader(SipHeaders.Route); //if (h==null) return null; else return new RouteHeader(h); MultipleHeader mh=getRoutes(); if (mh==null) return null; return new RouteHeader(mh.getTop()); } /** Gets the whole route */ public MultipleHeader getRoutes() { Vector v=getHeaders(SipHeaders.Route); if (v.size()>0) return new MultipleHeader(v); else return null; } /** Removes the top RouteHeader */ public void removeRouteHeader() { //removeHeader(SipHeaders.Route); MultipleHeader mh=getRoutes(); mh.removeTop(); setRoutes(mh); } /** Removes all RouteHeaders from Message (if any exists) */ public void removeRoutes() { removeAllHeaders(SipHeaders.Route); } /** Sets the whole route */ public void setRoutes(MultipleHeader routes) { if (hasRouteHeader()) removeRoutes(); addRoutes(routes); } /** Whether Message has RecordRouteHeader */ public boolean hasRecordRouteHeader() { return hasHeader(SipHeaders.Record_Route); } /** Adds RecordRouteHeader at the top */ public void addRecordRouteHeader(RecordRouteHeader rr) { //addHeaderAfter(rr,SipHeaders.Via); addHeaderAfter(rr,SipHeaders.CSeq); } /** Adds multiple RecordRoute headers at the top */ public void addRecordRoutes(MultipleHeader routes) { //addHeadersAfter(routes,SipHeaders.Via); addHeadersAfter(routes,SipHeaders.CSeq); } /** Gets the top RecordRouteHeader */ public RecordRouteHeader getRecordRouteHeader() { //Header h=getHeader(SipHeaders.Record_Route); //if (h==null) return null; else return new RecordRouteHeader(h); MultipleHeader mh=getRecordRoutes(); if (mh==null) return null; return new RecordRouteHeader(mh.getTop()); } /** Gets the whole RecordRoute headers */ public MultipleHeader getRecordRoutes() { Vector v=getHeaders(SipHeaders.Record_Route); if (v.size()>0) return new MultipleHeader(v); else return null; } /** Removes the top RecordRouteHeader */ public void removeRecordRouteHeader() { //removeHeader(SipHeaders.Record_Route); MultipleHeader mh=getRecordRoutes(); mh.removeTop(); setRecordRoutes(mh); } /** Removes all RecordRouteHeader from Message (if any exists) */ public void removeRecordRoutes() { removeAllHeaders(SipHeaders.Record_Route); } /** Sets the whole RecordRoute headers */ public void setRecordRoutes(MultipleHeader routes) { if (hasRecordRouteHeader()) removeRecordRoutes(); addRecordRoutes(routes); } /** Whether Message has CSeqHeader */ public boolean hasCSeqHeader() { return hasHeader(SipHeaders.CSeq); } /** Gets CSeqHeader of Message */ public CSeqHeader getCSeqHeader() { Header h=getHeader(SipHeaders.CSeq); if (h==null) return null; else return new CSeqHeader(h); } /** Sets CSeqHeader of Message */ public void setCSeqHeader(CSeqHeader csh) { setHeader(csh); } /** Removes CSeqHeader from Message */ public void removeCSeqHeader() { removeHeader(SipHeaders.CSeq); } /** Whether has CallIdHeader */ public boolean hasCallIdHeader() { return hasHeader(SipHeaders.Call_ID); } /** Sets CallIdHeader of Message */ public void setCallIdHeader(CallIdHeader cih) { setHeader(cih); } /** Gets CallIdHeader of Message */ public CallIdHeader getCallIdHeader() { Header h=getHeader(SipHeaders.Call_ID); if (h==null) return null; else return new CallIdHeader(h); } /** Removes CallIdHeader from Message */ public void removeCallIdHeader() { removeHeader(SipHeaders.Call_ID); } /** Whether Message has SubjectHeader */ public boolean hasSubjectHeader() { return hasHeader(SipHeaders.Subject); } /** Sets SubjectHeader of Message */ public void setSubjectHeader(SubjectHeader sh) { setHeader(sh); } /** Gets SubjectHeader of Message */ public SubjectHeader getSubjectHeader() { Header h=getHeader(SipHeaders.Subject); if (h==null) return null; else return new SubjectHeader(h); } /** Removes SubjectHeader from Message */ public void removeSubjectHeader() { removeHeader(SipHeaders.Subject); } /** Whether Message has DateHeader */ public boolean hasDateHeader() { return hasHeader(SipHeaders.Date); } /** Gets DateHeader of Message */ public DateHeader getDateHeader() { Header h=getHeader(SipHeaders.Date); if (h==null) return null; else return new DateHeader(h); } /** Sets DateHeader of Message */ public void setDateHeader(DateHeader dh) { setHeader(dh); } /** Removes DateHeader from Message (if it exists) */ public void removeDateHeader() { removeHeader(SipHeaders.Date); } /** Whether has UserAgentHeader */ public boolean hasUserAgentHeader() { return hasHeader(SipHeaders.User_Agent); } /** Sets UserAgentHeader */ public void setUserAgentHeader(UserAgentHeader h) { setHeader(h); } /** Gets UserAgentHeader */ public UserAgentHeader getUserAgentHeader() { Header h=getHeader(SipHeaders.User_Agent); if (h==null) return null; else return new UserAgentHeader(h); } /** Removes UserAgentHeader */ public void removeUserAgentHeader() { removeHeader(SipHeaders.User_Agent); } /** Whether has ServerHeader */ public boolean hasServerHeader() { return hasHeader(SipHeaders.Server); } /** Sets ServerHeader */ public void setServerHeader(ServerHeader h) { setHeader(h); } /** Gets ServerHeader */ public ServerHeader getServerHeader() { Header h=getHeader(SipHeaders.Server); if (h==null) return null; else return new ServerHeader(h); } /** Removes ServerHeader */ public void removeServerHeader() { removeHeader(SipHeaders.Server); } /** Whether has AcceptHeader */ public boolean hasAcceptHeader() { return hasHeader(SipHeaders.Accept); } /** Sets AcceptHeader */ public void setAcceptHeader(AcceptHeader h) { setHeader(h); } /** Gets AcceptHeader */ public AcceptHeader getAcceptHeader() { Header h=getHeader(SipHeaders.Accept); if (h==null) return null; else return new AcceptHeader(h); } /** Removes AcceptHeader */ public void removeAcceptHeader() { removeHeader(SipHeaders.Accept); } /** Whether has AlertInfoHeader */ public boolean hasAlertInfoHeader() { return hasHeader(SipHeaders.Alert_Info); } /** Sets AlertInfoHeader */ public void setAlertInfoHeader(AlertInfoHeader h) { setHeader(h); } /** Gets AlertInfoHeader */ public AlertInfoHeader getAlertInfoHeader() { Header h=getHeader(SipHeaders.Alert_Info); if (h==null) return null; else return new AlertInfoHeader(h); } /** Removes AlertInfoHeader */ public void removeAlertInfoHeader() { removeHeader(SipHeaders.Alert_Info); } /** Whether has AllowHeader */ public boolean hasAllowHeader() { return hasHeader(SipHeaders.Allow); } /** Sets AllowHeader */ public void setAllowHeader(AllowHeader h) { setHeader(h); } /** Gets AllowHeader */ public AllowHeader getAllowHeader() { Header h=getHeader(SipHeaders.Allow); if (h==null) return null; else return new AllowHeader(h); } /** Removes AllowHeader */ public void removeAllowHeader() { removeHeader(SipHeaders.Allow); } /** Whether Message has ExpiresHeader */ public boolean hasExpiresHeader() { return hasHeader(SipHeaders.Expires); } /** Gets ExpiresHeader of Message */ public ExpiresHeader getExpiresHeader() { Header h=getHeader(SipHeaders.Expires); if (h==null) return null; else return new ExpiresHeader(h); } /** Sets ExpiresHeader of Message */ public void setExpiresHeader(ExpiresHeader eh) { setHeader(eh); } /** Removes ExpiresHeader from Message (if it exists) */ public void removeExpiresHeader() { removeHeader(SipHeaders.Expires); } /** Whether Message has ContentTypeHeader */ public boolean hasContentTypeHeader() { return hasHeader(SipHeaders.Content_Type); } /** Gets ContentTypeHeader of Message */ public ContentTypeHeader getContentTypeHeader() { Header h=getHeader(SipHeaders.Content_Type); if (h==null) return null; else return new ContentTypeHeader(h); } /** Sets ContentTypeHeader of Message */ protected void setContentTypeHeader(ContentTypeHeader cth) { setHeader(cth); } /** Removes ContentTypeHeader from Message (if it exists) */ protected void removeContentTypeHeader() { removeHeader(SipHeaders.Content_Type); } /** Whether Message has ContentLengthHeader */ public boolean hasContentLengthHeader() { return hasHeader(SipHeaders.Content_Length); } /** Gets ContentLengthHeader of Message */ public ContentLengthHeader getContentLengthHeader() { Header h=getHeader(SipHeaders.Content_Length); if (h==null) return null; else return new ContentLengthHeader(h); } /** Sets ContentLengthHeader of Message */ protected void setContentLengthHeader(ContentLengthHeader clh) { setHeader(clh); } /** Removes ContentLengthHeader from Message (if it exists) */ protected void removeContentLengthHeader() { removeHeader(SipHeaders.Content_Length); } /** Whether Message has Body */ public boolean hasBody() { if (hasContentLengthHeader()) return getContentLengthHeader().getContentLength()>0; else return hasContentTypeHeader(); } /** Gets body(content) type */ public String getBodyType() { return getContentTypeHeader().getContentType(); } /** Sets the message body */ public void setBody(String content_type, String body) { removeBody(); if (body!=null && body.length()>0) { setContentTypeHeader(new ContentTypeHeader(content_type)); setContentLengthHeader(new ContentLengthHeader(body.length())); message=message+"\r\n"+body; } else { setContentLengthHeader(new ContentLengthHeader(0)); message=message+"\r\n"; } } /** Sets sdp body */ public void setBody(String body) { setBody("application/sdp",body); } /** Gets message body. The end of body is evaluated * from the Content-Length header if present (SIP-RFC compliant), * or from the end of message if no Content-Length header is present (non-SIP-RFC compliant) */ public String getBody() { //if (!hasBody()) return ""; if (!hasBody()) return null; int begin=(new SipParser(message)).goToBody().getPos(); int len; // the following 'if' is for robustness with non SIP-compliant UAs; // copliant UAs must insert Content-Length header when body is present.. if (this.hasContentLengthHeader()) len=getContentLengthHeader().getContentLength(); else { //printWarning("No Content-Length header found for the Body",3); len=message.length()-begin; } int end=begin+len; if (end>message.length()) { //printWarning("Found a Message Body shorter than Content-Length",3); end=message.length(); } return message.substring(begin,end); } /** Removes the message body (if it exists) and the final empty line */ public void removeBody() { int pos=(new SipParser(message)).goToEndOfLastHeader().goToNextLine().getPos(); message=message.substring(0,pos); removeContentLengthHeader(); removeContentTypeHeader(); } //**************************** Authentication ****************************/ /** Whether has AuthenticationInfoHeader */ public boolean hasAuthenticationInfoHeader() { return hasHeader(SipHeaders.Authentication_Info); } /** Sets AuthenticationInfoHeader */ public void setAuthenticationInfoHeader(AuthenticationInfoHeader h) { setHeader(h); } /** Gets AuthenticationInfoHeader */ public AuthenticationInfoHeader getAuthenticationInfoHeader() { Header h=getHeader(SipHeaders.Authentication_Info); if (h==null) return null; else return new AuthenticationInfoHeader(h); } /** Removes AuthenticationInfoHeader */ public void removeAuthenticationInfoHeader() { removeHeader(SipHeaders.Authentication_Info); } /** Whether has AuthorizationHeader */ public boolean hasAuthorizationHeader() { return hasHeader(SipHeaders.Authorization); } /** Sets AuthorizationHeader */ public void setAuthorizationHeader(AuthorizationHeader h) { setHeader(h); } /** Gets AuthorizationHeader */ public AuthorizationHeader getAuthorizationHeader() { Header h=getHeader(SipHeaders.Authorization); if (h==null) return null; else return new AuthorizationHeader(h); } /** Removes AuthorizationHeader */ public void removeAuthorizationHeader() { removeHeader(SipHeaders.Authorization); } /** Whether has WwwAuthenticateHeader */ public boolean hasWwwAuthenticateHeader() { return hasHeader(SipHeaders.WWW_Authenticate); } /** Sets WwwAuthenticateHeader */ public void setWwwAuthenticateHeader(WwwAuthenticateHeader h) { setHeader(h); } /** Gets WwwAuthenticateHeader */ public WwwAuthenticateHeader getWwwAuthenticateHeader() { Header h=getHeader(SipHeaders.WWW_Authenticate); if (h==null) return null; else return new WwwAuthenticateHeader(h); } /** Removes WwwAuthenticateHeader */ public void removeWwwAuthenticateHeader() { removeHeader(SipHeaders.WWW_Authenticate); } /** Whether has ProxyAuthenticateHeader */ public boolean hasProxyAuthenticateHeader() { return hasHeader(SipHeaders.Proxy_Authenticate); } /** Sets ProxyAuthenticateHeader */ public void setProxyAuthenticateHeader(ProxyAuthenticateHeader h) { setHeader(h); } /** Gets ProxyAuthenticateHeader */ public ProxyAuthenticateHeader getProxyAuthenticateHeader() { Header h=getHeader(SipHeaders.Proxy_Authenticate); if (h==null) return null; else return new ProxyAuthenticateHeader(h); } /** Removes ProxyAuthenticateHeader */ public void removeProxyAuthenticateHeader() { removeHeader(SipHeaders.Proxy_Authenticate); } /** Whether has ProxyAuthorizationHeader */ public boolean hasProxyAuthorizationHeader() { return hasHeader(SipHeaders.Proxy_Authorization); } /** Sets ProxyAuthorizationHeader */ public void setProxyAuthorizationHeader(ProxyAuthorizationHeader h) { setHeader(h); } /** Gets ProxyAuthorizationHeader */ public ProxyAuthorizationHeader getProxyAuthorizationHeader() { Header h=getHeader(SipHeaders.Proxy_Authorization); if (h==null) return null; else return new ProxyAuthorizationHeader(h); } /** Removes ProxyAuthorizationHeader */ public void removeProxyAuthorizationHeader() { removeHeader(SipHeaders.Proxy_Authorization); } //**************************** RFC 2543 Legacy ****************************/ /** Checks whether the next Route is formed according to RFC2543 Strict Route * and adapts the message. */ public void rfc2543RouteAdapt() { if (hasRouteHeader()) { MultipleHeader mrh=getRoutes(); RouteHeader rh=new RouteHeader(mrh.getTop()); if (!(new RouteHeader(mrh.getTop())).getNameAddress().getAddress().hasLr()) { // re-format the message according to the RFC2543 Strict Route rule SipURL next_hop=(new RouteHeader(mrh.getTop())).getNameAddress().getAddress(); SipURL recipient=getRequestLine().getAddress(); mrh.removeTop(); mrh.addBottom(new RouteHeader(new NameAddress(recipient))); setRoutes(mrh); setRequestLine(new RequestLine(getRequestLine().getMethod(),next_hop)); } } } /** Changes form RFC2543 Strict Route to RFC3261 Lose Route. * <p> The Request-URI is replaced with the last * value from the Route header, and that value is removed from the * Route header. */ public void rfc2543toRfc3261RouteUpdate() { // the message is formed according with RFC2543 strict route // the next hop is the request-uri // the recipient of the message is the last Route value RequestLine request_line=getRequestLine(); SipURL next_hop=request_line.getAddress(); MultipleHeader mrh=getRoutes(); SipURL target=(new RouteHeader(mrh.getBottom())).getNameAddress().getAddress(); mrh.removeBottom(); next_hop.addLr(); mrh.addTop(new RouteHeader(new NameAddress(next_hop))); removeRoutes(); addRoutes(mrh); setRequestLine(new RequestLine(request_line.getMethod(),target)); } }