1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/****************************************************************************** 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.stack; 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.Host; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.HostPort; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.ServerLogger; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.AddressImpl; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ContentLength; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ContentType; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Via; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.MessageFactoryImpl; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPMessage; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.InetAddress; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Hop; 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CSeqHeader; 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CallIdHeader; 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContactHeader; 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentLengthHeader; 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentTypeHeader; 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.FromHeader; 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ServerHeader; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ToHeader; 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ViaHeader; 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Message channel abstraction for the SIP stack. 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> Contains additions for support of symmetric NAT contributed by 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Hagai. 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.28 $ $Date: 2009/11/14 20:06:18 $ 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic abstract class MessageChannel { 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Incremented whenever a transaction gets assigned 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to the message channel and decremented when 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // a transaction gets freed from the message channel. 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected int useCount; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Hook method, overridden by subclasses 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void uncache() {} 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Message processor to whom I belong (if set). 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected transient MessageProcessor messageProcessor; 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Close the message channel. 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract void close(); 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the SIPStack object from this message channel. 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return SIPStack object of this message channel 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract SIPTransactionStack getSIPStack(); 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get transport string of this message channel. 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Transport string of this message channel. 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getTransport(); 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get whether this channel is reliable or not. 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return True if reliable, false if not. 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract boolean isReliable(); 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Return true if this is a secure channel. 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract boolean isSecure(); 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send the message (after it has been formatted) 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage Message to send. 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract void sendMessage(SIPMessage sipMessage) throws IOException; 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the peer address of the machine that sent us this message. 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a string contianing the ip address or host name of the sender of the message. 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getPeerAddress(); 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected abstract InetAddress getPeerInetAddress(); 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected abstract String getPeerProtocol(); 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the sender port ( the port of the other end that sent me the message). 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract int getPeerPort(); 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract int getPeerPacketSourcePort(); 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract InetAddress getPeerPacketSourceAddress(); 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Generate a key which identifies the message channel. This allows us to cache the message 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * channel. 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getKey(); 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the host to assign for an outgoing Request via header. 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract String getViaHost(); 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the port to assign for the via header of an outgoing message. 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public abstract int getViaPort(); 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send the message (after it has been formatted), to a specified address and a specified port 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param message Message to send. 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverAddress Address of the receiver. 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverPort Port of the receiver. 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected abstract void sendMessage(byte[] message, InetAddress receiverAddress, 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int receiverPort, boolean reconnectFlag) throws IOException; 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the host of this message channel. 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return host of this messsage channel. 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getHost() { 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.getMessageProcessor().getIpAddress().getHostAddress(); 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get port of this message channel. 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return Port of this message channel. 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getPort() { 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.messageProcessor != null) 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return messageProcessor.getPort(); 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return -1; 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a formatted message to the specified target. 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage Message to send. 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param hop hop to send it to. 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws IOException If there is an error sending the message 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void sendMessage(SIPMessage sipMessage, Hop hop) throws IOException { 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long time = System.currentTimeMillis(); 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InetAddress hopAddr = InetAddress.getByName(hop.getHost()); 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (MessageProcessor messageProcessor : getSIPStack().getMessageProcessors()) { 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageProcessor.getIpAddress().equals(hopAddr) 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && messageProcessor.getPort() == hop.getPort() 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && messageProcessor.getTransport().equals(hop.getTransport())) { 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MessageChannel messageChannel = messageProcessor.createMessageChannel( 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hopAddr, hop.getPort()); 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (messageChannel instanceof RawMessageChannel) { 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((RawMessageChannel) messageChannel).processMessage(sipMessage); 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (getSIPStack().isLoggingEnabled()) 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang getSIPStack().getStackLogger().logDebug("Self routing message"); 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] msg = sipMessage.encodeAsBytes(this.getTransport()); 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendMessage(msg, hopAddr, hop.getPort(), sipMessage instanceof SIPRequest); 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ioe) { 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw ioe; 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_ERROR)) { 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.getSIPStack().getStackLogger().logError("Error self routing message cause by: ", ex); 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // TODO: When moving to Java 6, use the IOExcpetion(message, exception) constructor 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new IOException("Error self routing message"); 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang logMessage(sipMessage, hopAddr, hop.getPort(), time); 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a message given SIP message. 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage is the messge to send. 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverAddress is the address to which we want to send 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receiverPort is the port to which we want to send 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void sendMessage(SIPMessage sipMessage, InetAddress receiverAddress, int receiverPort) 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throws IOException { 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long time = System.currentTimeMillis(); 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang byte[] bytes = sipMessage.encodeAsBytes(this.getTransport()); 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sendMessage(bytes, receiverAddress, receiverPort, sipMessage instanceof SIPRequest); 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang logMessage(sipMessage, receiverAddress, receiverPort, time); 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Convenience function to get the raw IP source address of a SIP message as a String. 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getRawIpSourceAddress() { 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String sourceAddress = getPeerAddress(); 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String rawIpSourceAddress = null; 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InetAddress sourceInetAddress = InetAddress.getByName(sourceAddress); 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang rawIpSourceAddress = sourceInetAddress.getHostAddress(); 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return rawIpSourceAddress; 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * generate a key given the inet address port and transport. 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static String getKey(InetAddress inetAddr, int port, String transport) { 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (transport + ":" + inetAddr.getHostAddress() + ":" + port).toLowerCase(); 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Generate a key given host and port. 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static String getKey(HostPort hostPort, String transport) { 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return (transport + ":" + hostPort.getHost().getHostname() + ":" + hostPort.getPort()) 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .toLowerCase(); 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the hostport structure of this message channel. 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostPort getHostPort() { 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostPort retval = new HostPort(); 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setHost(new Host(this.getHost())); 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setPort(this.getPort()); 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the peer host and port. 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a HostPort structure for the peer. 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostPort getPeerHostPort() { 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostPort retval = new HostPort(); 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setHost(new Host(this.getPeerAddress())); 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setPort(this.getPeerPort()); 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the Via header for this transport. Note that this does not set a branch identifier. 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a via header for outgoing messages sent from this channel. 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Via getViaHeader() { 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Via channelViaHeader; 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang channelViaHeader = new Via(); 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang channelViaHeader.setTransport(getTransport()); 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang channelViaHeader.setSentBy(getHostPort()); 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return channelViaHeader; 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the via header host:port structure. This is extracted from the topmost via header of 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the request. 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return a host:port structure 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostPort getViaHostPort() { 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostPort retval = new HostPort(); 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setHost(new Host(this.getViaHost())); 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.setPort(this.getViaPort()); 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Log a message sent to an address and port via the default interface. 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipMessage is the message to log. 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param address is the inet address to which the message is sent. 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param port is the port to which the message is directed. 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void logMessage(SIPMessage sipMessage, InetAddress address, int port, long time) { 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!getSIPStack().getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Default port. 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (port == -1) 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = 5060; 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang getSIPStack().serverLogger.logMessage(sipMessage, this.getHost() + ":" + this.getPort(), 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang address.getHostAddress().toString() + ":" + port, true, time); 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Log a response received at this message channel. This is used for processing incoming 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * responses to a client transaction. 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param receptionTime is the time at which the response was received. 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param status is the processing status of the message. 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void logResponse(SIPResponse sipResponse, long receptionTime, String status) { 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int peerport = getPeerPort(); 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (peerport == 0 && sipResponse.getContactHeaders() != null) { 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContactHeader contact = (ContactHeader) sipResponse.getContactHeaders().getFirst(); 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang peerport = ((AddressImpl) contact.getAddress()).getPort(); 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String from = getPeerAddress().toString() + ":" + peerport; 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String to = this.getHost() + ":" + getPort(); 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.getSIPStack().serverLogger.logMessage(sipResponse, from, to, status, false, 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang receptionTime); 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a response to a bad request (ie one that causes a ParseException) 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param badReq 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return message bytes, null if unable to formulate response 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected final String createBadReqRes(String badReq, ParseException pe) { 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer buf = new StringBuffer(512); 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("SIP/2.0 400 Bad Request (" + pe.getLocalizedMessage() + ')'); 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We need the following headers: all Vias, CSeq, Call-ID, From, To 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!copyViaHeaders(badReq, buf)) 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!copyHeader(CSeqHeader.NAME, badReq, buf)) 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!copyHeader(CallIdHeader.NAME, badReq, buf)) 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!copyHeader(FromHeader.NAME, badReq, buf)) 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!copyHeader(ToHeader.NAME, badReq, buf)) 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Should add a to-tag if not already present... 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int toStart = buf.indexOf(ToHeader.NAME); 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (toStart != -1 && buf.indexOf("tag", toStart) == -1) { 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append(";tag=badreq"); 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Let's add a Server header too.. 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader s = MessageFactoryImpl.getDefaultServerHeader(); 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( s != null ) { 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("\r\n" + s.toString()); 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int clength = badReq.length(); 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (! (this instanceof UDPMessageChannel) || 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang clength + buf.length() + ContentTypeHeader.NAME.length() 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ": message/sipfrag\r\n".length() + 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLengthHeader.NAME.length() < 1300) { 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Check to see we are within one UDP packet. 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentTypeHeader cth = new ContentType("message", "sipfrag"); 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("\r\n" + cth.toString()); 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLength clengthHeader = new ContentLength(clength); 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("\r\n" + clengthHeader.toString()); 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("\r\n\r\n" + badReq); 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentLength clengthHeader = new ContentLength(0); 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append("\r\n" + clengthHeader.toString()); 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return buf.toString(); 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Copies a header from a request 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param name 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param fromReq 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param buf 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Note: some limitations here: does not work for short forms of headers, or continuations; 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * problems when header names appear in other parts of the request 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final boolean copyHeader(String name, String fromReq, StringBuffer buf) { 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int start = fromReq.indexOf(name); 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (start != -1) { 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int end = fromReq.indexOf("\r\n", start); 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (end != -1) { 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // XX Assumes no continuation here... 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append(fromReq.subSequence(start - 2, end)); // incl CRLF 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // in front 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Copies all via headers from a request 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param fromReq 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param buf 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Note: some limitations here: does not work for short forms of headers, or continuations 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final boolean copyViaHeaders(String fromReq, StringBuffer buf) { 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int start = fromReq.indexOf(ViaHeader.NAME); 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean found = false; 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (start != -1) { 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int end = fromReq.indexOf("\r\n", start); 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (end != -1) { 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // XX Assumes no continuation here... 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang buf.append(fromReq.subSequence(start - 2, end)); // incl CRLF 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // in front 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang found = true; 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang start = fromReq.indexOf(ViaHeader.NAME, end); 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return found; 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Get the message processor. 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public MessageProcessor getMessageProcessor() { 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.messageProcessor; 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 490