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: package gov.nist.siplite;
027:
028: import gov.nist.siplite.stack.*;
029: import gov.nist.siplite.message.*;
030: import gov.nist.siplite.header.*;
031: import gov.nist.siplite.address.*;
032: import gov.nist.core.*;
033: import javax.microedition.sip.SipException;
034: import java.io.IOException;
035:
036: import com.sun.midp.log.Logging;
037: import com.sun.midp.log.LogChannels;
038:
039: /**
040: * A helper class that runs a registration call flow.
041: */
042: public class RegistrationHelper implements SipListener, Runnable {
043: /** Current SIP stack context. */
044: private SipStack sipStack;
045: /** Current SIP provider. */
046: private SipProvider sipProvider;
047: /** Message factory. */
048: private MessageFactory messageFactory;
049: /** HJeader factory. */
050: private HeaderFactory headerFactory;
051: /** Current user name. */
052: private String userName;
053: /** Current user address. */
054: private String userAddress;
055: /** Current event listening filter. */
056: private ListeningPoint lp;
057: /** Local thread for asynchoronous processing. */
058: private Thread myThread;
059: /** Flag indicating successful registraion. */
060: protected boolean successfulRegistration;
061: /** Credentials listener for authentication requests. */
062: private AuthenticationListener authenticationListener;
063: /**
064: * Count of authorization requests (RFC 2617, 3.2.2).
065: */
066: private int countReoriginateRequest = 1;
067:
068: /**
069: * Constructor.
070: * @param myStack current SIP stack context
071: * @param userName current user name
072: * @param userAddress current user address
073: * @param lp listening point event filter
074: */
075: public RegistrationHelper(SipStack myStack, String userName,
076: String userAddress, ListeningPoint lp) {
077: this .sipStack = myStack;
078: this .userName = userName;
079: this .userAddress = userAddress;
080: this .messageFactory = new MessageFactory();
081: this .headerFactory = new HeaderFactory();
082: this .lp = lp;
083: myThread = new Thread(this );
084: // authenticationListener=new DigestClientAuthentication();
085: }
086:
087: /**
088: * Performs the session registration.
089: */
090: public void doRegister() {
091: myThread.start();
092: // Wait to register ourselves so we can receive messages.
093: synchronized (this ) {
094: try {
095: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
096: Logging.report(Logging.INFORMATION,
097: LogChannels.LC_JSR180, "WAIT");
098: }
099:
100: this .wait();
101:
102: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
103: Logging.report(Logging.INFORMATION,
104: LogChannels.LC_JSR180, "WAKE UP");
105: }
106: } catch (InterruptedException ex) {
107: return;
108: }
109: }
110: }
111:
112: /**
113: * Starts asynchronous processing int separate thread.
114: */
115: public void run() {
116: try {
117: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
118: Logging.report(Logging.INFORMATION,
119: LogChannels.LC_JSR180,
120: "starting registration thread");
121: }
122:
123: sipStack.stackInitialized = false;
124: Hop hop = sipStack.getRouter().getOutboundProxy();
125:
126: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
127: Logging.report(Logging.INFORMATION,
128: LogChannels.LC_JSR180, "got listening point");
129: }
130:
131: sipProvider = lp.getProvider();
132: StringBuffer requestLine = new StringBuffer("REGISTER sip:")
133: .append(sipStack.getNextHop().getHost())
134: .append(":")
135: .append(sipStack.getNextHop().getPort()).append(
136: ";transport=" + hop.getTransport()).append(
137: " SIP/2.0\r\n");
138: StringBuffer from = new StringBuffer("From: <sip:").append(
139: userName).append("@").append(userAddress).append(
140: ">;tag=1234\r\n");
141: StringBuffer to = new StringBuffer("To: <sip:").append(
142: userName).append("@").append(userAddress).append(
143: ">\r\n");
144: String via = lp.messageProcessor.getViaHeader().toString();
145: int port = lp.getPort();
146:
147: StringBuffer contact = new StringBuffer("Contact: <sip:"
148: + userName + "@" + sipStack.getIPAddress() + ":"
149: + port + ";transport=" + hop.getTransport()
150: + ">\r\n");
151:
152: CallIdHeader callId = sipProvider.getNewCallId();
153:
154: CSeqHeader cseq = new CSeqHeader();
155: cseq.setMethod(Request.REGISTER);
156: cseq.setSequenceNumber(1);
157:
158: MaxForwardsHeader maxForwards = new MaxForwardsHeader();
159: maxForwards.setMaxForwards(1);
160:
161: String registerRequest = new StringBuffer().append(
162: requestLine).append(via).append(callId.toString())
163: .append(cseq.toString()).append(
164: maxForwards.toString()).append(from)
165: .append(to).append(contact).toString();
166:
167: // System.out.println(registerRequest);
168:
169: Request request = messageFactory
170: .createRequest(registerRequest);
171: ClientTransaction ct = sipProvider
172: .getNewClientTransaction(request);
173:
174: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
175: Logging.report(Logging.INFORMATION,
176: LogChannels.LC_JSR180,
177: "Got client Transaction " + ct);
178: Logging.report(Logging.INFORMATION,
179: LogChannels.LC_JSR180,
180: "SENDING REGISTER TO THE PROXY");
181: }
182:
183: ct.sendRequest();
184: } catch (Exception ex) {
185: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
186: Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
187: "Exception: " + ex);
188: }
189:
190: synchronized (this ) {
191: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
192: Logging.report(Logging.INFORMATION,
193: LogChannels.LC_JSR180, "NOTIFY");
194: }
195: this .notify();
196: }
197: }
198: }
199:
200: /**
201: * Processes a request.
202: * (always logs a message that request is ignored)
203: * @param requestEvent the current request
204: */
205: public void processRequest(RequestEvent requestEvent) {
206: // System.out.println("Ignoring request");
207:
208: }
209:
210: /**
211: * Process a response message.
212: * @param responseEvent the transition event to be processed.
213: */
214: public void processResponse(ResponseEvent responseEvent) {
215: Response response = responseEvent.getResponse();
216: if (response.getStatusCode() == Response.OK) {
217: this .successfulRegistration = true;
218:
219: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
220: Logging.report(Logging.INFORMATION,
221: LogChannels.LC_JSR180,
222: "Registration listener : sending notify!");
223: }
224:
225: synchronized (this ) {
226: // System.out.println("NOTIFY");
227: this .notify(); // Authentication done!
228: }
229: } else {
230: // Need to call out here to the Authentication listener.
231: // check if 401 or 407
232: if (response.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED
233: || response.getStatusCode() == Response.UNAUTHORIZED) {
234: Exception ex = null;
235: try {
236: ClientTransaction clientTransac = responseEvent
237: .getClientTransaction();
238:
239: Request newRequest = authenticationListener
240: .createNewRequest(sipStack, clientTransac
241: .getRequest(), response,
242: countReoriginateRequest);
243:
244: if (newRequest == null) {
245: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
246: Logging.report(Logging.INFORMATION,
247: LogChannels.LC_JSR180,
248: "Authentication failed...");
249: }
250: return;
251: }
252: countReoriginateRequest++;
253:
254: ClientTransaction ct = sipProvider
255: .getNewClientTransaction(newRequest);
256:
257: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
258: Logging.report(Logging.INFORMATION,
259: LogChannels.LC_JSR180,
260: "Got client Transaction " + ct);
261: }
262:
263: ct.sendRequest();
264:
265: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
266: Logging.report(Logging.INFORMATION,
267: LogChannels.LC_JSR180,
268: "RegistrationHelper: request sent:\n"
269: + newRequest);
270: }
271:
272: } catch (SipException se) {
273: ex = se;
274: } catch (IOException ioe) {
275: ex = ioe;
276: }
277: if (ex != null) {
278: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
279: Logging.report(Logging.WARNING,
280: LogChannels.LC_JSR180,
281: "RegistrationHelper: processResponse(),"
282: + " exception raised: "
283: + ex.getMessage());
284: }
285: }
286: }
287: }
288: }
289:
290: /**
291: * Process a tiomeout event.
292: * @param timeoutEvent termination event based on timeout condition
293: */
294: public void processTimeout(TimeoutEvent timeoutEvent) {
295: synchronized (this ) {
296: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
297: Logging.report(Logging.INFORMATION,
298: LogChannels.LC_JSR180, "NOTIFY");
299: }
300:
301: this .notify(); // Authentication done!
302: }
303:
304: }
305:
306: }
|