1 /*
2 * Conditions Of Use
3 *
4 * This software was developed by employees of the National Institute of
5 * Standards and Technology (NIST), an agency of the Federal Government.
6 * Pursuant to title 15 Untied States Code Section 105, works of NIST
7 * employees are not subject to copyright protection in the United States
8 * and are considered to be in the public domain.  As a result, a formal
9 * license is not needed to use the software.
10 *
11 * This software is provided by NIST as a service and is expressly
12 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15 * AND DATA ACCURACY.  NIST does not warrant or make any representations
16 * regarding the use of the software or the results thereof, including but
17 * not limited to the correctness, accuracy, reliability or usefulness of
18 * the software.
19 *
20 * Permission to use this software is contingent upon your acceptance
21 * of the terms of this agreement
22 *
23 * .
24 *
25 */
26 /*******************************************************************************
27 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).        *
28 *******************************************************************************/
29 package gov.nist.javax.sip.header;
30 
31 import gov.nist.core.Host;
32 import gov.nist.core.HostPort;
33 import gov.nist.core.NameValue;
34 import gov.nist.core.NameValueList;
35 import gov.nist.javax.sip.stack.HopImpl;
36 
37 import javax.sip.InvalidArgumentException;
38 import javax.sip.address.Hop;
39 import javax.sip.header.ViaHeader;
40 import java.text.ParseException;
41 
42 /**
43  * Via SIPHeader (these are strung together in a ViaList).
44  *
45  * @see ViaList
46  *
47  * @version 1.2 $Revision: 1.17 $ $Date: 2009/10/18 13:46:33 $
48  *
49  * @author M. Ranganathan   <br/>
50  *
51  *
52  *
53  */
54 public class Via
55     extends ParametersHeader
56     implements javax.sip.header.ViaHeader, ViaHeaderExt {
57 
58     /**
59      * Comment for <code>serialVersionUID</code>
60      */
61     private static final long serialVersionUID = 5281728373401351378L;
62 
63     /** The branch parameter is included by every forking proxy.
64     */
65     public static final String BRANCH = ParameterNames.BRANCH;
66 
67     /** The "received" parameter is added only for receiver-added Via Fields.
68      */
69     public static final String RECEIVED = ParameterNames.RECEIVED;
70 
71     /** The "maddr" paramter is designating the multicast address.
72      */
73     public static final String MADDR = ParameterNames.MADDR;
74 
75     /** The "TTL" parameter is designating the time-to-live value.
76      */
77     public static final String TTL = ParameterNames.TTL;
78 
79     /** The RPORT parameter.
80     */
81     public static final String RPORT = ParameterNames.RPORT;
82 
83     /** sentProtocol field.
84      */
85     protected Protocol sentProtocol;
86 
87     /** sentBy field.
88      */
89     protected HostPort sentBy;
90 
91     /**
92      * comment field
93      *
94      * JvB note: RFC3261 does not allow a comment to appear in Via headers, and this
95      * is not accessible through the API. Suggest removal
96      */
97     protected String comment;
98 
99     private boolean rPortFlag = false;
100 
101     /** Default constructor
102     */
Via()103     public Via() {
104         super(NAME);
105         sentProtocol = new Protocol();
106     }
107 
equals(Object other)108     public boolean equals(Object other) {
109 
110         if (other==this) return true;
111 
112         if (other instanceof ViaHeader) {
113             final ViaHeader o = (ViaHeader) other;
114             return getProtocol().equalsIgnoreCase( o.getProtocol() )
115                 && getTransport().equalsIgnoreCase( o.getTransport() )
116                 && getHost().equalsIgnoreCase( o.getHost() )
117                 && getPort() == o.getPort()
118                 && equalParameters( o );
119         }
120         return false;
121     }
122 
123 
124     /** get the Protocol Version
125      * @return String
126      */
getProtocolVersion()127     public String getProtocolVersion() {
128         if (sentProtocol == null)
129             return null;
130         else
131             return sentProtocol.getProtocolVersion();
132     }
133 
134     /**
135      * Accessor for the sentProtocol field.
136      * @return Protocol field
137      */
getSentProtocol()138     public Protocol getSentProtocol() {
139 
140         return sentProtocol;
141     }
142 
143     /**
144      * Accessor for the sentBy field
145      *@return SentBy field
146      */
getSentBy()147     public HostPort getSentBy() {
148         return sentBy;
149     }
150 
151     /**
152      * Get the host, port and transport as a Hop. This is
153      * useful for the stack to avoid duplication of code.
154      *
155      */
getHop()156     public Hop getHop() {
157         HopImpl hop = new HopImpl(sentBy.getHost().getHostname(),
158                 sentBy.getPort(),sentProtocol.getTransport());
159         return hop;
160     }
161 
162     /**
163      * Accessor for the parameters field
164      * @return parameters field
165      */
getViaParms()166     public NameValueList getViaParms() {
167         return parameters;
168     }
169 
170     /**
171      * Accessor for the comment field.
172      * @return comment field.
173      * @deprecated RFC 2543 support feature.
174      */
getComment()175     public String getComment() {
176         return comment;
177     }
178 
179 
180 
181     /** port of the Via Header.
182      * @return true if Port exists.
183      */
hasPort()184     public boolean hasPort() {
185         return (getSentBy()).hasPort();
186     }
187 
188     /** comment of the Via Header.
189      *
190      * @return false if comment does not exist and true otherwise.
191      */
hasComment()192     public boolean hasComment() {
193         return comment != null;
194     }
195 
196     /** remove the port.
197      */
removePort()198     public void removePort() {
199         sentBy.removePort();
200     }
201 
202     /** remove the comment field.
203      */
removeComment()204     public void removeComment() {
205         comment = null;
206     }
207 
208     /** set the Protocol Version
209      * @param protocolVersion String to set
210      */
setProtocolVersion(String protocolVersion)211     public void setProtocolVersion(String protocolVersion) {
212         if (sentProtocol == null)
213             sentProtocol = new Protocol();
214         sentProtocol.setProtocolVersion(protocolVersion);
215     }
216 
217     /** set the Host of the Via Header
218          * @param host String to set
219          */
setHost(Host host)220     public void setHost(Host host) {
221         if (sentBy == null) {
222             sentBy = new HostPort();
223         }
224         sentBy.setHost(host);
225     }
226 
227     /**
228      * Set the sentProtocol member
229      * @param s Protocol to set.
230      */
setSentProtocol(Protocol s)231     public void setSentProtocol(Protocol s) {
232         sentProtocol = s;
233     }
234 
235     /**
236      * Set the sentBy member
237      * @param s HostPort to set.
238      */
setSentBy(HostPort s)239     public void setSentBy(HostPort s) {
240         sentBy = s;
241     }
242 
243     /**
244      * Set the comment member
245      * @param c String to set.
246      * @deprecated This is an RFC 2543 feature.
247      */
setComment(String c)248     public void setComment(String c) {
249         comment = c;
250     }
251 
252     /** Encode the body of this header (the stuff that follows headerName).
253      * A.K.A headerValue.
254      */
encodeBody()255     protected String encodeBody() {
256         return encodeBody(new StringBuffer()).toString();
257     }
258 
encodeBody(StringBuffer buffer)259     protected StringBuffer encodeBody(StringBuffer buffer) {
260         sentProtocol.encode(buffer);
261         buffer.append(SP);
262         sentBy.encode(buffer);
263         if (!parameters.isEmpty()) {
264             buffer.append(SEMICOLON);
265             parameters.encode(buffer);
266         }
267         if (comment != null) {
268             buffer.append(SP).append(LPAREN).append(comment).append(RPAREN);
269         }
270         if (rPortFlag) buffer.append(";rport");
271         return buffer;
272     }
273 
274     /**
275      * Set the host part of this ViaHeader to the newly supplied <code>host</code>
276      * parameter.
277      *
278      * @throws ParseException which signals that an error has been reached
279      * unexpectedly while parsing the host value.
280      */
setHost(String host)281     public void setHost(String host) throws ParseException {
282         if (sentBy == null)
283             sentBy = new HostPort();
284         try {
285             Host h = new Host(host);
286             sentBy.setHost(h);
287         } catch (Exception e) {
288             throw new NullPointerException(" host parameter is null");
289         }
290     }
291 
292     /**
293     * Returns the host part of this ViaHeader.
294     *
295     * @return  the string value of the host
296     */
getHost()297     public String getHost() {
298         if (sentBy == null)
299             return null;
300         else {
301             Host host = sentBy.getHost();
302             if (host == null)
303                 return null;
304             else
305                 return host.getHostname();
306         }
307     }
308 
309     /**
310      * Set the port part of this ViaHeader to the newly supplied <code>port</code>
311      * parameter.
312      *
313      * @param port - the Integer.valueOf value of the port of this ViaHeader
314      */
setPort(int port)315     public void setPort(int port) throws InvalidArgumentException {
316 
317         if ( port!=-1 && (port<1 || port>65535)) {
318             throw new InvalidArgumentException( "Port value out of range -1, [1..65535]" );
319         }
320 
321         if (sentBy == null)
322             sentBy = new HostPort();
323         sentBy.setPort(port);
324     }
325 
326     /**
327      * Set the RPort flag parameter
328      */
setRPort()329     public void setRPort(){
330         rPortFlag = true;
331     }
332 
333     /**
334      * Returns the port part of this ViaHeader.
335      *
336      * @return the integer value of the port
337      */
getPort()338     public int getPort() {
339         if (sentBy == null)
340             return -1;
341         return sentBy.getPort();
342     }
343 
344 
345     /**
346     * Return the rport parameter.
347     *
348     *@return the rport parameter or -1.
349     */
getRPort()350        public int getRPort() {
351          String strRport = getParameter(ParameterNames.RPORT);
352          if (strRport != null && ! strRport.equals(""))
353             return Integer.valueOf(strRport).intValue();
354          else
355             return -1;
356          }
357 
358 
359     /**
360      * Returns the value of the transport parameter.
361      *
362      * @return the string value of the transport paramter of the ViaHeader
363      */
getTransport()364     public String getTransport() {
365         if (sentProtocol == null)
366             return null;
367         return sentProtocol.getTransport();
368     }
369 
370     /**
371      * Sets the value of the transport. This parameter specifies
372      * which transport protocol to use for sending requests and responses to
373      * this entity. The following values are defined: "udp", "tcp", "sctp",
374      * "tls", but other values may be used also.
375      *
376      * @param transport - new value for the transport parameter
377      * @throws ParseException which signals that an error has been reached
378      * unexpectedly while parsing the transport value.
379      */
setTransport(String transport)380     public void setTransport(String transport) throws ParseException {
381         if (transport == null)
382             throw new NullPointerException(
383                 "JAIN-SIP Exception, "
384                     + "Via, setTransport(), the transport parameter is null.");
385         if (sentProtocol == null)
386             sentProtocol = new Protocol();
387         sentProtocol.setTransport(transport);
388     }
389 
390     /**
391      * Returns the value of the protocol used.
392      *
393      * @return the string value of the protocol paramter of the ViaHeader
394      */
getProtocol()395     public String getProtocol() {
396         if (sentProtocol == null)
397             return null;
398         return sentProtocol.getProtocol();// JvB: Return name ~and~ version
399     }
400 
401     /**
402      * Sets the value of the protocol parameter. This parameter specifies
403      * which protocol is used, for example "SIP/2.0".
404      *
405      * @param protocol - new value for the protocol parameter
406      * @throws ParseException which signals that an error has been reached
407      * unexpectedly while parsing the protocol value.
408      */
setProtocol(String protocol)409     public void setProtocol(String protocol) throws ParseException {
410         if (protocol == null)
411             throw new NullPointerException(
412                 "JAIN-SIP Exception, "
413                     + "Via, setProtocol(), the protocol parameter is null.");
414 
415         if (sentProtocol == null)
416             sentProtocol = new Protocol();
417 
418         sentProtocol.setProtocol(protocol);
419     }
420 
421     /**
422      * Returns the value of the ttl parameter, or -1 if this is not set.
423      *
424      * @return the integer value of the <code>ttl</code> parameter
425      */
getTTL()426     public int getTTL() {
427         int ttl = getParameterAsInt(ParameterNames.TTL);
428         return ttl;
429     }
430 
431     /**
432      * Sets the value of the ttl parameter. The ttl parameter specifies the
433      * time-to-live value when packets are sent using UDP multicast.
434      *
435      * @param ttl - new value of the ttl parameter
436      * @throws InvalidArgumentException if supplied value is less than zero or
437      * greater than 255, excluding -1 the default not set value.
438      */
setTTL(int ttl)439     public void setTTL(int ttl) throws InvalidArgumentException {
440         if (ttl < 0 && ttl != -1)
441             throw new InvalidArgumentException(
442                 "JAIN-SIP Exception"
443                     + ", Via, setTTL(), the ttl parameter is < 0");
444         setParameter(new NameValue(ParameterNames.TTL, Integer.valueOf(ttl)));
445     }
446 
447     /**
448      * Returns the value of the <code>maddr</code> parameter, or null if this
449      * is not set.
450      *
451      * @return the string value of the maddr parameter
452      */
getMAddr()453     public String getMAddr() {
454         return getParameter(ParameterNames.MADDR);
455     }
456 
457     /**
458      * Sets the value of the <code>maddr</code> parameter of this ViaHeader. The
459      * maddr parameter indicates the server address to be contacted for this
460      * user, overriding any address derived from the host field.
461      *
462      * @param  mAddr new value of the <code>maddr</code> parameter
463      * @throws ParseException which signals that an error has been reached
464      * unexpectedly while parsing the mAddr value.
465      */
setMAddr(String mAddr)466     public void setMAddr(String mAddr) throws ParseException {
467         if (mAddr == null)
468             throw new NullPointerException(
469                 "JAIN-SIP Exception, "
470                     + "Via, setMAddr(), the mAddr parameter is null.");
471 
472         Host host = new Host();
473         host.setAddress(mAddr);
474         NameValue nameValue = new NameValue(ParameterNames.MADDR, host);
475         setParameter(nameValue);
476 
477     }
478 
479     /**
480      * Gets the received paramater of the ViaHeader. Returns null if received
481      * does not exist.
482      *
483      * @return the string received value of ViaHeader
484      */
getReceived()485     public String getReceived() {
486         return getParameter(ParameterNames.RECEIVED);
487     }
488 
489     /**
490      * Sets the received parameter of ViaHeader.
491      *
492      * @param received - the newly supplied received parameter.
493      * @throws ParseException which signals that an error has been reached
494      * unexpectedly while parsing the received value.
495      */
setReceived(String received)496     public void setReceived(String received) throws ParseException {
497         if (received == null)
498             throw new NullPointerException(
499                 "JAIN-SIP Exception, "
500                     + "Via, setReceived(), the received parameter is null.");
501 
502         setParameter(ParameterNames.RECEIVED, received);
503 
504     }
505 
506     /**
507      * Gets the branch paramater of the ViaHeader. Returns null if branch
508      * does not exist.
509      *
510      * @return the string branch value of ViaHeader
511      */
getBranch()512     public String getBranch() {
513         return getParameter(ParameterNames.BRANCH);
514     }
515 
516     /**
517      * Sets the branch parameter of the ViaHeader to the newly supplied
518      * branch value.
519      *
520      * @param branch - the new string branch parmameter of the ViaHeader.
521      * @throws ParseException which signals that an error has been reached
522      * unexpectedly while parsing the branch value.
523      */
setBranch(String branch)524     public void setBranch(String branch) throws ParseException {
525         if (branch == null || branch.length()==0)
526             throw new NullPointerException(
527                 "JAIN-SIP Exception, "
528                     + "Via, setBranch(), the branch parameter is null or length 0.");
529 
530         setParameter(ParameterNames.BRANCH, branch);
531     }
532 
clone()533     public Object clone() {
534         Via retval = (Via) super.clone();
535         if (this.sentProtocol != null)
536             retval.sentProtocol = (Protocol) this.sentProtocol.clone();
537         if (this.sentBy != null)
538             retval.sentBy = (HostPort) this.sentBy.clone();
539         if ( this.getRPort() != -1)
540             retval.setParameter(RPORT,this.getRPort());
541         return retval;
542     }
543 
544     /*
545      * (non-Javadoc)
546      * @see gov.nist.javax.sip.header.ViaHeaderExt#getSentByField()
547      */
getSentByField()548     public String getSentByField() {
549         if(sentBy != null)
550             return sentBy.encode();
551         return null;
552     }
553     /*
554      * (non-Javadoc)
555      * @see gov.nist.javax.sip.header.ViaHeaderExt#getSentProtocolField()
556      */
getSentProtocolField()557     public String getSentProtocolField() {
558         if(sentProtocol != null)
559             return sentProtocol.encode();
560         return null;
561     }
562 
563 }
564