/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2004-2011 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sipmack.sip.simple;
import java.text.ParseException;
import java.util.ArrayList;
import javax.sip.ClientTransaction;
import javax.sip.InvalidArgumentException;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.TransactionUnavailableException;
import javax.sip.address.Address;
import javax.sip.address.URI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContentLengthHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import net.java.sipmack.common.Log;
import net.java.sipmack.sip.CommunicationsException;
import net.java.sipmack.sip.SIPConfig;
import net.java.sipmack.sip.SipManager;
import net.java.sipmack.sip.security.SipSecurityException;
public class MessageProcessing {
protected SipManager sipManCallback = null;
public MessageProcessing() {
}
public MessageProcessing(SipManager sipManCallback) {
this.sipManCallback = sipManCallback;
}
public void setSipManagerCallBack(SipManager sipManCallback) {
this.sipManCallback = sipManCallback;
}
/**
* Attempts to re-generate the corresponding request with the proper
* credentials and terminates the call if it fails.
*
* @param clientTransaction the corresponding transaction
* @param response the challenge
*/
void processAuthenticationChallenge(ClientTransaction clientTransaction,
Response response) {
try {
ClientTransaction retryTran = sipManCallback.sipSecurityManager
.handleChallenge(response, clientTransaction);
retryTran.sendRequest();
}
catch (SipSecurityException exc) {
sipManCallback.fireCommunicationsError(new CommunicationsException(
"Authorization failed!", exc));
}
catch (Exception exc) {
sipManCallback.fireCommunicationsError(new CommunicationsException(
"Failed to resend a request "
+ "after a security challenge!", exc));
}
finally {
}
}
/**
* Process MESSAGE requests and send OK response.
*
* @param serverTransaction
* @param request
*/
public void processMessageRequest(ServerTransaction serverTransaction,
Request request) {
try {
// Send OK
Response ok = null;
try {
ok = sipManCallback.messageFactory.createResponse(Response.OK,
request);
// sipManCallback.attachToTag(ok,
// serverTransaction.getDialog());
}
catch (ParseException ex) {
sipManCallback
.fireCommunicationsError(new CommunicationsException(
"Failed to construct an OK response to a MESSAGE request!",
ex));
return;
}
try {
serverTransaction.sendResponse(ok);
}
catch (SipException ex) {
// This is not really a problem according to the RFC
// so just dump to stdout should someone be interested
} catch (InvalidArgumentException e) {
}
}
finally {
}
}
public void sendKeepAlive() throws CommunicationsException {
String to = "";
byte[] messageBody = "".getBytes();
try {
to = to.trim();
// Handle default domain name (i.e. transform 1234 -> 1234@sip.com
String defaultDomainName = SIPConfig.getDefaultDomain();
if (defaultDomainName != null // no sip scheme
&& !to.trim().startsWith("tel:") && to.indexOf('@') == -1) {
to = to + "@" + defaultDomainName;
}
// Let's be uri fault tolerant
if (to.toLowerCase().indexOf("sip:") == -1 // no sip scheme
&& to.indexOf('@') != -1 // most probably a sip uri
) {
to = "sip:" + to;
}
// Request URI
URI requestURI;
try {
requestURI = sipManCallback.addressFactory.createURI(to);
}
catch (ParseException ex) {
throw new CommunicationsException(to
+ " is not a legal SIP uri!", ex);
}
// Call ID
CallIdHeader callIdHeader = sipManCallback.sipProvider
.getNewCallId();
// CSeq
CSeqHeader cSeqHeader;
try {
cSeqHeader = sipManCallback.headerFactory.createCSeqHeader(1L,
Request.MESSAGE);
}
catch (Exception ex) {
// Shouldn't happen
throw new CommunicationsException(
"An unexpected erro occurred while"
+ "constructing the CSeqHeadder", ex);
}
// FromHeader
FromHeader fromHeader = sipManCallback.getFromHeader();
// ToHeader
Address toAddress = sipManCallback.addressFactory
.createAddress(requestURI);
ToHeader toHeader;
try {
toHeader = sipManCallback.headerFactory.createToHeader(
toAddress, null);
}
catch (ParseException ex) {
// Shouldn't happen
throw new CommunicationsException(
"Null is not an allowed tag for the to header!", ex);
}
ContentLengthHeader contentLengthHeader = null;
try {
contentLengthHeader = sipManCallback.headerFactory
.createContentLengthHeader(messageBody.length);
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Cseq Header must contain a integer value!", ex);
}
//ExpiresHeader expiresHeader = null;
try {
sipManCallback.headerFactory.createExpiresHeader(30);
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Expires Header must be an integer!", ex);
}
String contentType = "text/plain";
ContentTypeHeader contentTypeHeader = null;
try {
String[] contentTypeTab = contentType.split("/");
contentTypeHeader = sipManCallback.headerFactory
.createContentTypeHeader(contentTypeTab[0],
contentTypeTab[1]);
}
catch (ParseException ex) {
throw new CommunicationsException(
"ContentType Header must look like type/subtype!", ex);
}
// ViaHeaders
ArrayList<ViaHeader> viaHeaders = sipManCallback.getLocalViaHeaders();
// MaxForwards
MaxForwardsHeader maxForwards = sipManCallback
.getMaxForwardsHeader();
Request message = null;
try {
message = sipManCallback.messageFactory.createRequest(
requestURI, Request.MESSAGE, callIdHeader, cSeqHeader,
fromHeader, toHeader, viaHeaders, maxForwards);
message.setContentLength(contentLengthHeader);
message.setContent(messageBody, contentTypeHeader);
// message.addHeader(eventHeader);
}
catch (Exception e) {
Log.error("sendKeepAlive", e);
}
//ClientTransaction messageTransaction = null;
//String subscriber = sipManCallback.getFromHeader().getAddress()
// .getURI().toString();
try {
sipManCallback.sipProvider.getNewClientTransaction(message);
} catch (TransactionUnavailableException e) {
e.printStackTrace();
}
try {
// TODO : Anpassen
//((SIPClientTransaction) messageTransaction).sendRequest("\0".getBytes(), InetAddress.getByName(SIPConfig.getDefaultDomain()), SIPConfig.getRegistrarPort());
}
catch (Exception e) {
Log.error("sendKeepAlive", e);
}
}
finally {
try {
this.finalize();
}
catch (Throwable e) {
}
}
}
/**
* Sends an instant message in pager-mode using a SIMPLE/SIP MESSAGE
* request. In pager-mode, each message is independent of any other
* messages. An instant message will be the body of the MESSAGE request to
* be sent, therefore, its format must conform to the values in the
* "Content-Type" and "Content-Encoding" header fields. Refer to Message for
* details.
*
* @param to the address of receiver.
* @param messageBody the message to be sent. The messageBody will be the body of
* the MESSAGE request to be sent and its format must conform to
* the values in the parameters contentType and contentEncoding.
* Please refer to the setBody method for details.
* @param contentType the Internet media type of the messageBody. Please refer to
* the Message.setBody method for details.
* @param contentEncoding the encodings that have been applied to the messageBody in
* addition to those specified by contentType. Please refer to
* the Message.setBody method for details.
* @return the transaction ID associated with the MESSAGE request sent by
* this method.
* @throws CommunicationsException
*/
public java.lang.String sendMessage(java.lang.String to,
byte[] messageBody, java.lang.String contentType,
java.lang.String contentEncoding) throws CommunicationsException {
try {
to = to.trim();
// Handle default domain name (i.e. transform 1234 -> 1234@sip.com
String defaultDomainName = SIPConfig.getDefaultDomain();
if (defaultDomainName != null // no sip scheme
&& !to.trim().startsWith("tel:") && to.indexOf('@') == -1 // most
// probably
// a
// sip
// uri
) {
to = to + "@" + defaultDomainName;
}
// Let's be uri fault tolerant
if (to.toLowerCase().indexOf("sip:") == -1 // no sip scheme
&& to.indexOf('@') != -1 // most probably a sip uri
) {
to = "sip:" + to;
}
// Request URI
URI requestURI;
try {
requestURI = sipManCallback.addressFactory.createURI(to);
}
catch (ParseException ex) {
throw new CommunicationsException(to
+ " is not a legal SIP uri!", ex);
}
// Call ID
CallIdHeader callIdHeader = sipManCallback.sipProvider
.getNewCallId();
// CSeq
CSeqHeader cSeqHeader;
try {
cSeqHeader = sipManCallback.headerFactory.createCSeqHeader(1L,
Request.MESSAGE);
}
catch (Exception ex) {
// Shouldn't happen
throw new CommunicationsException(
"An unexpected erro occurred while"
+ "constructing the CSeqHeadder", ex);
}
// FromHeader
FromHeader fromHeader = sipManCallback.getFromHeader();
// ToHeader
Address toAddress = sipManCallback.addressFactory
.createAddress(requestURI);
ToHeader toHeader;
try {
toHeader = sipManCallback.headerFactory.createToHeader(
toAddress, null);
}
catch (ParseException ex) {
// Shouldn't happen
throw new CommunicationsException(
"Null is not an allowed tag for the to header!", ex);
}
ContentTypeHeader contentTypeHeader = null;
try {
String[] contentTypeTab = contentType.split("/");
contentTypeHeader = sipManCallback.headerFactory
.createContentTypeHeader(contentTypeTab[0],
contentTypeTab[1]);
}
catch (ParseException ex) {
throw new CommunicationsException(
"ContentType Header must look like type/subtype!", ex);
}
ContentLengthHeader contentLengthHeader = null;
try {
contentLengthHeader = sipManCallback.headerFactory
.createContentLengthHeader(messageBody.length);
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Cseq Header must contain a integer value!", ex);
}
/*
* EventHeader eventHeader = null; try { eventHeader =
* sipManCallback.headerFactory.createEventHeader("presence"); }
* catch (ParseException ex) { //Shouldn't happen console.error(
* "Unable to create event header!", ex); throw new
* CommunicationsException( "Unable to create event header!", ex); }
*/
//ExpiresHeader expiresHeader = null;
try {
sipManCallback.headerFactory.createExpiresHeader(30);
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Expires Header must be an integer!", ex);
}
// ViaHeaders
ArrayList<ViaHeader> viaHeaders = sipManCallback.getLocalViaHeaders();
// MaxForwards
MaxForwardsHeader maxForwards = sipManCallback
.getMaxForwardsHeader();
Request message = null;
try {
message = sipManCallback.messageFactory.createRequest(
requestURI, Request.MESSAGE, callIdHeader, cSeqHeader,
fromHeader, toHeader, viaHeaders, maxForwards);
message.setContent(messageBody, contentTypeHeader);
message.setContentLength(contentLengthHeader);
// message.addHeader(eventHeader);
}
catch (ParseException ex) {
throw new CommunicationsException(
"Failed to create message Request!", ex);
}
ClientTransaction messageTransaction = null;
//String subscriber = sipManCallback.getFromHeader().getAddress()
// .getURI().toString();
try {
messageTransaction = sipManCallback.sipProvider
.getNewClientTransaction(message);
//
}
catch (TransactionUnavailableException ex) {
throw new CommunicationsException(
"Failed to create messageTransaction.", ex);
}
try {
messageTransaction.sendRequest();
}
catch (SipException ex) {
throw new CommunicationsException(
"An error occurred while sending message request", ex);
}
return messageTransaction.toString();
}
finally {
}
}
}