/*
* Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights
* Reserved. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package gov.nist.siplite;
import gov.nist.siplite.stack.*;
import gov.nist.siplite.message.*;
import gov.nist.siplite.header.*;
import gov.nist.siplite.address.*;
import gov.nist.core.*;
import javax.microedition.sip.SipException;
import java.io.IOException;
import com.sun.j2me.log.Logging;
import com.sun.j2me.log.LogChannels;
/**
* A helper class that runs a registration call flow.
*/
public class RegistrationHelper implements SipListener, Runnable {
/** Current SIP stack context. */
private SipStack sipStack;
/** Current SIP provider. */
private SipProvider sipProvider;
/** Message factory. */
private MessageFactory messageFactory;
/** HJeader factory. */
private HeaderFactory headerFactory;
/** Current user name. */
private String userName;
/** Current user address. */
private String userAddress;
/** Current event listening filter. */
private ListeningPoint lp;
/** Local thread for asynchoronous processing. */
private Thread myThread;
/** Flag indicating successful registraion. */
protected boolean successfulRegistration;
/** Credentials listener for authentication requests. */
private AuthenticationListener authenticationListener;
/**
* Count of authorization requests (RFC 2617, 3.2.2).
*/
private int countReoriginateRequest = 1;
/**
* Constructor.
* @param myStack current SIP stack context
* @param userName current user name
* @param userAddress current user address
* @param lp listening point event filter
*/
public RegistrationHelper(SipStack myStack,
String userName, String userAddress,
ListeningPoint lp) {
this.sipStack = myStack;
this.userName = userName;
this.userAddress = userAddress;
this.messageFactory = new MessageFactory();
this.headerFactory = new HeaderFactory();
this.lp = lp;
myThread = new Thread(this);
// authenticationListener=new DigestClientAuthentication();
}
/**
* Performs the session registration.
*/
public void doRegister() {
myThread.start();
// Wait to register ourselves so we can receive messages.
synchronized (this) {
try {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"WAIT");
}
this.wait();
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"WAKE UP");
}
} catch (InterruptedException ex) {
return;
}
}
}
/**
* Starts asynchronous processing int separate thread.
*/
public void run() {
try {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"starting registration thread");
}
sipStack.stackInitialized = false;
Hop hop = sipStack.getRouter().getOutboundProxy();
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"got listening point");
}
sipProvider = lp.getProvider();
StringBuffer requestLine =
new StringBuffer("REGISTER sip:")
.append(sipStack.getNextHop().getHost())
.append(":")
.append(sipStack.getNextHop().getPort())
.append(";transport="+hop.getTransport())
.append(" SIP/2.0\r\n");
StringBuffer from =
new StringBuffer("From: <sip:")
.append(userName)
.append("@")
.append(userAddress)
.append(">;tag=1234\r\n");
StringBuffer to =
new StringBuffer("To: <sip:")
.append(userName)
.append("@")
.append(userAddress)
.append(">\r\n");
String via =
lp.messageProcessor[0].getViaHeader().toString();
int port = lp.getPort();
StringBuffer contact = new
StringBuffer(
"Contact: <sip:"
+ userName
+ "@" + sipStack.getIPAddress()
+ ":" + port
+ ";transport=" + hop.getTransport()
+ ">\r\n");
CallIdHeader callId = sipProvider.getNewCallId();
CSeqHeader cseq = new CSeqHeader();
cseq.setMethod(Request.REGISTER);
cseq.setSequenceNumber(1);
MaxForwardsHeader maxForwards = new MaxForwardsHeader();
maxForwards.setMaxForwards(1);
String registerRequest =
new StringBuffer().append(requestLine)
.append(via).append(callId.toString())
.append(cseq.toString())
.append(maxForwards.toString())
.append(from).append(to).append(contact).
toString();
// System.out.println(registerRequest);
Request request = messageFactory.createRequest
(registerRequest);
ClientTransaction ct =
sipProvider.getNewClientTransaction(request);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"Got client Transaction " + ct);
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"SENDING REGISTER TO THE PROXY");
}
ct.sendRequest();
} catch (Exception ex) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
"Exception: " + ex);
}
synchronized (this) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"NOTIFY");
}
this.notify();
}
}
}
/**
* Processes a request.
* (always logs a message that request is ignored)
* @param requestEvent the current request
*/
public void processRequest(RequestEvent requestEvent) {
// System.out.println("Ignoring request");
}
/**
* Process a response message.
* @param responseEvent the transition event to be processed.
*/
public void processResponse(ResponseEvent responseEvent) {
Response response = responseEvent.getResponse();
if (response.getStatusCode() == SIPErrorCodes.OK) {
this.successfulRegistration = true;
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"Registration listener : sending notify!");
}
synchronized (this) {
// System.out.println("NOTIFY");
this.notify(); // Authentication done!
}
} else {
// Need to call out here to the Authentication listener.
// check if 401 or 407
if (response.getStatusCode() == SIPErrorCodes.
PROXY_AUTHENTICATION_REQUIRED ||
response.getStatusCode() == SIPErrorCodes.UNAUTHORIZED) {
Exception ex = null;
try {
ClientTransaction clientTransac = responseEvent.
getClientTransaction();
Request newRequest =
authenticationListener
.createNewRequest(sipStack,
clientTransac.getRequest(),
response, countReoriginateRequest);
if (newRequest == null) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION,
LogChannels.LC_JSR180,
"Authentication failed...");
}
return;
}
countReoriginateRequest ++;
ClientTransaction ct =
sipProvider.getNewClientTransaction(newRequest);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION,
LogChannels.LC_JSR180,
"Got client Transaction " + ct);
}
ct.sendRequest();
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION,
LogChannels.LC_JSR180,
"RegistrationHelper: request sent:\n" + newRequest);
}
} catch (SipException se) {
ex = se;
} catch (IOException ioe) {
ex = ioe;
}
if (ex != null) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING, LogChannels.LC_JSR180,
"RegistrationHelper: processResponse(),"
+ " exception raised: "
+ ex.getMessage());
}
}
}
}
}
/**
* Process a tiomeout event.
* @param timeoutEvent termination event based on timeout condition
*/
public void processTimeout
(TimeoutEvent timeoutEvent) {
synchronized (this) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"NOTIFY");
}
this.notify(); // Authentication done!
}
}
}