• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package gov.nist.javax.sip.parser;
27 
28 import gov.nist.javax.sip.header.*;
29 import gov.nist.core.*;
30 import java.text.ParseException;
31 
32 /**
33  * Parser for via headers.
34  *
35  * @version 1.2 $Revision: 1.12 $ $Date: 2009/07/17 18:58:07 $
36  * @since 1.1
37  *
38  * @author Olivier Deruelle
39  * @author M. Ranganathan
40  */
41 public class ViaParser extends HeaderParser {
42 
ViaParser(String via)43     public ViaParser(String via) {
44         super(via);
45     }
46 
ViaParser(Lexer lexer)47     public ViaParser(Lexer lexer) {
48         super(lexer);
49     }
50 
51     /**
52      * a parser for the essential part of the via header.
53      */
parseVia(Via v)54     private void parseVia(Via v) throws ParseException {
55         // The protocol
56         lexer.match(TokenTypes.ID);
57         Token protocolName = lexer.getNextToken();
58 
59         this.lexer.SPorHT();
60         // consume the "/"
61         lexer.match('/');
62         this.lexer.SPorHT();
63         lexer.match(TokenTypes.ID);
64         this.lexer.SPorHT();
65         Token protocolVersion = lexer.getNextToken();
66 
67         this.lexer.SPorHT();
68 
69         // We consume the "/"
70         lexer.match('/');
71         this.lexer.SPorHT();
72         lexer.match(TokenTypes.ID);
73         this.lexer.SPorHT();
74 
75         Token transport = lexer.getNextToken();
76         this.lexer.SPorHT();
77 
78         Protocol protocol = new Protocol();
79         protocol.setProtocolName(protocolName.getTokenValue());
80         protocol.setProtocolVersion(protocolVersion.getTokenValue());
81         protocol.setTransport(transport.getTokenValue());
82         v.setSentProtocol(protocol);
83 
84         // sent-By
85         HostNameParser hnp = new HostNameParser(this.getLexer());
86         HostPort hostPort = hnp.hostPort( true );
87         v.setSentBy(hostPort);
88 
89         // Ignore blanks
90         this.lexer.SPorHT();
91 
92         // parameters
93         while (lexer.lookAhead(0) == ';') {
94             this.lexer.consume(1);
95             this.lexer.SPorHT();
96             NameValue nameValue = this.nameValue();
97             String name = nameValue.getName();
98             if (name.equals(Via.BRANCH)) {
99                 String branchId = (String) nameValue.getValueAsObject();
100                 if (branchId == null)
101                     throw new ParseException("null branch Id", lexer.getPtr());
102 
103             }
104             v.setParameter(nameValue);
105             this.lexer.SPorHT();
106         }
107 
108         //
109         // JvB Note: RFC3261 does not allow a comment in Via headers anymore
110         //
111         if (lexer.lookAhead(0) == '(') {
112             this.lexer.selectLexer("charLexer");
113             lexer.consume(1);
114             StringBuffer comment = new StringBuffer();
115             while (true) {
116                 char ch = lexer.lookAhead(0);
117                 if (ch == ')') {
118                     lexer.consume(1);
119                     break;
120                 } else if (ch == '\\') {
121                     // Escaped character
122                     Token tok = lexer.getNextToken();
123                     comment.append(tok.getTokenValue());
124                     lexer.consume(1);
125                     tok = lexer.getNextToken();
126                     comment.append(tok.getTokenValue());
127                     lexer.consume(1);
128                 } else if (ch == '\n') {
129                     break;
130                 } else {
131                     comment.append(ch);
132                     lexer.consume(1);
133                 }
134             }
135             v.setComment(comment.toString());
136         }
137 
138     }
139 
140     /**
141      * Overrides the superclass nameValue parser because we have to tolerate
142      * IPV6 addresses in the received parameter.
143      */
nameValue()144     protected NameValue nameValue() throws ParseException {
145         if (debug)
146             dbg_enter("nameValue");
147         try {
148 
149             lexer.match(LexerCore.ID);
150             Token name = lexer.getNextToken();
151             // eat white space.
152             lexer.SPorHT();
153             try {
154 
155                 boolean quoted = false;
156 
157                 char la = lexer.lookAhead(0);
158 
159                 if (la == '=') {
160                     lexer.consume(1);
161                     lexer.SPorHT();
162                     String str = null;
163                     if (name.getTokenValue().compareToIgnoreCase(Via.RECEIVED) == 0) {
164                         // Allow for IPV6 Addresses.
165                         // these could have : in them!
166                         str = lexer.byteStringNoSemicolon();
167                     } else {
168                         if (lexer.lookAhead(0) == '\"') {
169                             str = lexer.quotedString();
170                             quoted = true;
171                         } else {
172                             lexer.match(LexerCore.ID);
173                             Token value = lexer.getNextToken();
174                             str = value.getTokenValue();
175                         }
176                     }
177                     NameValue nv = new NameValue(name.getTokenValue()
178                             .toLowerCase(), str);
179                     if (quoted)
180                         nv.setQuotedValue();
181                     return nv;
182                 } else {
183                     return new NameValue(name.getTokenValue().toLowerCase(),
184                             null);
185                 }
186             } catch (ParseException ex) {
187                 return new NameValue(name.getTokenValue(), null);
188             }
189 
190         } finally {
191             if (debug)
192                 dbg_leave("nameValue");
193         }
194 
195     }
196 
parse()197     public SIPHeader parse() throws ParseException {
198         if (debug)
199             dbg_enter("parse");
200         try {
201             ViaList viaList = new ViaList();
202             // The first via header.
203             this.lexer.match(TokenTypes.VIA);
204             this.lexer.SPorHT(); // ignore blanks
205             this.lexer.match(':'); // expect a colon.
206             this.lexer.SPorHT(); // ingore blanks.
207 
208             while (true) {
209                 Via v = new Via();
210                 parseVia(v);
211                 viaList.add(v);
212                 this.lexer.SPorHT(); // eat whitespace.
213                 if (this.lexer.lookAhead(0) == ',') {
214                     this.lexer.consume(1); // Consume the comma
215                     this.lexer.SPorHT(); // Ignore space after.
216                 }
217                 if (this.lexer.lookAhead(0) == '\n')
218                     break;
219             }
220             this.lexer.match('\n');
221             return viaList;
222         } finally {
223             if (debug)
224                 dbg_leave("parse");
225         }
226 
227     }
228 
229     /**
230      *
231      * public static void main(String args[]) throws ParseException { String
232      * via[] = { "Via: SIP/2.0/UDP 135.180.130.133;branch=-12345\n", "Via:
233      * SIP/2.0/UDP 166.34.120.100;branch=0000045d-00000001"+ ",SIP/2.0/UDP
234      * 166.35.224.216:5000\n", "Via: SIP/2.0/UDP sip33.example.com,"+ "
235      * SIP/2.0/UDP sip32.example.com (oli),"+ "SIP/2.0/UDP sip31.example.com\n",
236      * "Via: SIP/2.0/UDP host.example.com;received=::133;"+ "
237      * branch=C1C3344E2710000000E299E568E7potato10potato0potato0\n", "Via:
238      * SIP/2.0/UDP host.example.com;received=135.180.130.133;"+ "
239      * branch=C1C3344E2710000000E299E568E7potato10potato0potato0\n", "Via:
240      * SIP/2.0/UDP company.com:5604 ( Hello )"+ ", SIP / 2.0 / UDP
241      * 135.180.130.133\n", "Via: SIP/2.0/UDP
242      * 129.6.55.9:7060;received=stinkbug.antd.nist.gov\n",
243      *
244      * "Via: SIP/2.0/UDP ss2.wcom.com:5060;branch=721e418c4.1"+ ", SIP/2.0/UDP
245      * ss1.wcom.com:5060;branch=2d4790.1"+ " , SIP/2.0/UDP here.com:5060( Hello
246      * the big world) \n" ,"Via: SIP/2.0/UDP
247      * ss1.wcom.com:5060;branch=2d4790.1\n", "Via: SIP/2.0/UDP
248      * first.example.com:4000;ttl=16"+ ";maddr=224.2.0.1 ;branch=a7c6a8dlze.1
249      * (Acme server)\n" };
250      *
251      * for (int i = 0; i < via.length; i++ ) { ViaParser vp = new
252      * ViaParser(via[i]); System.out.println("toParse = " + via[i]); ViaList vl =
253      * (ViaList) vp.parse(); System.out.println("encoded = " + vl.encode()); }
254      *  }
255      *
256      */
257 
258 }
259