001: /*
002: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
003: * Reserved. Use is subject to license terms.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025: /*
026: */
027: package gov.nist.siplite.stack;
028:
029: import gov.nist.siplite.header.*;
030: import gov.nist.siplite.address.*;
031: import gov.nist.siplite.message.*;
032: import java.util.Enumeration;
033: import java.io.IOException;
034: import gov.nist.core.*;
035:
036: /**
037: * Message channel abstraction for the SIP stack.
038: *
039: * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
040: */
041: public abstract class MessageChannel {
042: /**
043: * Message processor to whom I belong (if set).
044: */
045: protected MessageProcessor messageProcessor;
046:
047: /**
048: * Closes the message channel.
049: */
050: public abstract void close();
051:
052: /**
053: * Gets the SIPMessageStack object from this message channel.
054: * @return SIPMessageStack object of this message channel
055: */
056: public abstract SIPMessageStack getSIPStack();
057:
058: /**
059: * Gets transport string of this message channel.
060: * @return Transport string of this message channel.
061: */
062: public abstract String getTransport();
063:
064: /**
065: * Gets whether this channel is reliable or not.
066: * @return True if reliable, false if not.
067: */
068: public abstract boolean isReliable();
069:
070: /**
071: * Returns true if this is a secure channel.
072: * @return true if connection is secure
073: */
074: public abstract boolean isSecure();
075:
076: /**
077: * Sends the message (after it has been formatted)
078: * @param sipMessage Message to send.
079: */
080: public abstract void sendMessage(Message sipMessage)
081: throws IOException;
082:
083: /**
084: * Gets the peer address of the machine that sent us this message.
085: * @return a string contianing the ip address or host name of the sender
086: * of the message.
087: */
088: public abstract String getPeerAddress();
089:
090: /**
091: * Gets the name of the machine that sent us this message.
092: * @return a string contianing the ip address or host name of the sender
093: * of the message.
094: * public abstract String getPeerName();
095: */
096:
097: /**
098: * Gets the sender port (the port of the other end that sent me
099: * the message).
100: * @return the peer port
101: */
102: public abstract int getPeerPort();
103:
104: /**
105: * Generates a key which identifies the message channel.
106: * This allows us to cache the message channel.
107: * @return the key
108: */
109: public abstract String getKey();
110:
111: /**
112: * Gets the host to assign for an outgoing Request via header.
113: * @return the via host
114: */
115: public abstract String getViaHost();
116:
117: /**
118: * Gets the port to assign for the via header of an outgoing message.
119: * @return the via port
120: */
121: public abstract int getViaPort();
122:
123: /**
124: * Sends the message (after it has been formatted), to a specified
125: * address and a specified port
126: * @param message Message to send.
127: * @param receiverAddress Address of the receiver.
128: * @param receiverPort Port of the receiver.
129: */
130: protected abstract void sendMessage(byte[] message,
131: String receiverAddress, int receiverPort)
132: throws IOException;
133:
134: /**
135: * Gets the host of this message channel.
136: * @return host of this messsage channel.
137: */
138: public String getHost() {
139: return this .getSIPStack().getHostAddress();
140: }
141:
142: /**
143: * Gets port of this message channel.
144: * @return Port of this message channel.
145: */
146: public int getPort() {
147: if (this .messageProcessor != null)
148: return messageProcessor.getPort();
149: else
150: return -1;
151: }
152:
153: /**
154: * Handles an exception.
155: * @param ex the exception to process
156: */
157: public abstract void handleException(SIPServerException ex);
158:
159: /**
160: * Sends a message given SIP message.
161: * @param sipMessage is the messge to send.
162: * @param receiverAddress is the address to which we want to send
163: * @param receiverPort is the port to which we want to send
164: */
165: public void sendMessage(Message sipMessage, String receiverAddress,
166: int receiverPort) throws IOException {
167: long time = System.currentTimeMillis();
168: byte[] bytes = sipMessage.encodeAsBytes();
169: sendMessage(bytes, receiverAddress, receiverPort);
170: logMessage(sipMessage, receiverAddress, receiverPort, time);
171: }
172:
173: /**
174: * Generates a key given the inet address port and transport.
175: * @param inetAddr internet address
176: * @param port the connection end point
177: * @param transport the connection type
178: * @return the connection key
179: */
180: public static String getKey(String inetAddr, int port,
181: String transport) {
182: return transport + ":" + inetAddr + ":" + port;
183: }
184:
185: /**
186: * Gets the hostport structure of this message channel.
187: * @return the host and port
188: */
189: public HostPort getHostPort() {
190: HostPort retval = new HostPort();
191: retval.setHost(new Host(this .getHost()));
192: retval.setPort(this .getPort());
193: return retval;
194: }
195:
196: /**
197: * Gets the peer host and port.
198: *
199: * @return a HostPort structure for the peer.
200: */
201: public HostPort getPeerHostPort() {
202: HostPort retval = new HostPort();
203: retval.setHost(new Host(this .getPeerAddress()));
204: retval.setPort(this .getPeerPort());
205: return retval;
206: }
207:
208: /**
209: * Gets the Via header for this transport.
210: * Note that this does not set a branch identifier.
211: *
212: * @return a via header for outgoing messages sent from this channel.
213: */
214: public ViaHeader getViaHeader() {
215: ViaHeader channelViaHeader;
216:
217: channelViaHeader = new ViaHeader();
218:
219: channelViaHeader.setTransport(getTransport());
220:
221: channelViaHeader.setSentBy(getHostPort());
222: return channelViaHeader;
223: }
224:
225: /**
226: * Gets the via header host:port structure.
227: * This is extracted from the topmost via header of the request.
228: *
229: * @return a host:port structure
230: */
231: public HostPort getViaHostPort() {
232: HostPort retval = new HostPort();
233: retval.setHost(new Host(this .getViaHost()));
234: retval.setPort(this .getViaPort());
235: return retval;
236: }
237:
238: /**
239: * Logs a message sent to an address and port via the default interface.
240: * @param sipMessage is the message to log.
241: * @param address is the inet address to which the message is sent.
242: * @param port is the port to which the message is directed.
243: * @param time timestamp for the logged message
244: */
245: protected void logMessage(Message sipMessage, String address,
246: int port, long time) {
247: String firstLine = sipMessage.getFirstLine();
248: CSeqHeader cseq = (CSeqHeader) sipMessage.getCSeqHeader();
249: CallIdHeader callid = (CallIdHeader) sipMessage.getCallId();
250: String cseqBody = cseq.encodeBody();
251: String callidBody = callid.encodeBody();
252: // Default port.
253: if (port == -1)
254: port = 5060;
255: if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) {
256: Enumeration extList = sipMessage
257: .getHeaders("NISTExtension");
258: String status = null;
259: if (extList != null && extList.hasMoreElements()) {
260: Header exthdr = null;
261: exthdr = (Header) extList.nextElement();
262: status = exthdr.getHeaderValue();
263: }
264: ServerLog.logMessage(sipMessage.encode(), this .getHost()
265: + ":" + this .getPort(), address + ":" + port, true,
266: callidBody, firstLine, status, sipMessage
267: .getTransactionId(), time);
268: }
269: }
270:
271: /**
272: * Logs a response received at this message channel.
273: * This is used for processing incoming responses to a client transaction.
274: * @param sipResponse the response object to be logged
275: * @param receptionTime is the time at which the response was received.
276: * @param status is the processing status of the message.
277: */
278: public void logResponse(Response sipResponse, long receptionTime,
279: String status) {
280: try {
281: int peerport = getPeerPort();
282: if (peerport == 0
283: && sipResponse.getContactHeaders() != null) {
284: ContactHeader contact = (ContactHeader) sipResponse
285: .getContactHeaders().getFirst();
286: peerport = ((Address) contact.getAddress()).getPort();
287:
288: }
289: String from = getPeerAddress() + ":" + peerport;
290: String to = this .getHost() + ":" + getPort();
291: ServerLog.logMessage(sipResponse, from, to, status, false,
292: receptionTime);
293: } catch (RuntimeException ex) {
294: ex.printStackTrace();
295: }
296: }
297:
298: /**
299: * Gets the message processor.
300: * @return the message processor
301: */
302: public MessageProcessor getMessageProcessor() {
303: return this.messageProcessor;
304: }
305: }
|