use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SipProviderImpl method getNewClientTransaction.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request)
*/
public ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException {
if (request == null)
throw new NullPointerException("null request");
if (!sipStack.isAlive())
throw new TransactionUnavailableException("Stack is stopped");
SIPRequest sipRequest = (SIPRequest) request;
if (sipRequest.getTransaction() != null)
throw new TransactionUnavailableException("Transaction already assigned to request");
if (sipRequest.getMethod().equals(Request.ACK)) {
throw new TransactionUnavailableException("Cannot create client transaction for " + Request.ACK);
}
// sloppy
if (sipRequest.getTopmostVia() == null) {
ListeningPointImpl lp = (ListeningPointImpl) this.getListeningPoint("udp");
Via via = lp.getViaHeader();
request.setHeader(via);
}
// Give the request a quick check to see if all headers are assigned.
try {
sipRequest.checkHeaders();
} catch (ParseException ex) {
throw new TransactionUnavailableException(ex.getMessage(), ex);
}
/*
* User decided to give us his own via header branch. Lets see if it
* results in a clash. If so reject the request.
*/
if (sipRequest.getTopmostVia().getBranch() != null && sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) && sipStack.findTransaction((SIPRequest) request, false) != null) {
throw new TransactionUnavailableException("Transaction already exists!");
}
if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) {
SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction((SIPRequest) request, false);
if (ct != null) {
ClientTransaction retval = sipStack.createClientTransaction((SIPRequest) request, ct.getMessageChannel());
((SIPTransaction) retval).addEventListener(this);
sipStack.addTransaction((SIPClientTransaction) retval);
if (ct.getDialog() != null) {
((SIPClientTransaction) retval).setDialog((SIPDialog) ct.getDialog(), sipRequest.getDialogId(false));
}
return retval;
}
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("could not find existing transaction for " + ((SIPRequest) request).getFirstLine() + " creating a new one ");
// Could not find a dialog or the route is not set in dialog.
Hop hop = null;
try {
hop = sipStack.getNextHop((SIPRequest) request);
if (hop == null)
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable");
} catch (SipException ex) {
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable", ex);
}
String transport = hop.getTransport();
ListeningPointImpl listeningPoint = (ListeningPointImpl) this.getListeningPoint(transport);
String dialogId = sipRequest.getDialogId(false);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null && dialog.getState() == DialogState.TERMINATED) {
// throw new TransactionUnavailableException
// ("Found a terminated dialog -- possible re-use of old tag
// parameters");
sipStack.removeDialog(dialog);
}
try {
// Set the brannch id before you ask for a tx.
// If the user has set his own branch Id and the
// branch id starts with a valid prefix, then take it.
// otherwise, generate one. If branch ID checking has
// been requested, set the branch ID.
String branchId = null;
if (sipRequest.getTopmostVia().getBranch() == null || !sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) || sipStack.checkBranchId()) {
branchId = Utils.getInstance().generateBranchId();
sipRequest.getTopmostVia().setBranch(branchId);
}
Via topmostVia = sipRequest.getTopmostVia();
//set port and transport if user hasn't already done this.
if (topmostVia.getTransport() == null)
topmostVia.setTransport(transport);
if (topmostVia.getPort() == -1)
topmostVia.setPort(listeningPoint.getPort());
branchId = sipRequest.getTopmostVia().getBranch();
SIPClientTransaction ct = (SIPClientTransaction) sipStack.createMessageChannel(sipRequest, listeningPoint.getMessageProcessor(), hop);
if (ct == null)
throw new TransactionUnavailableException("Cound not create tx");
ct.setNextHop(hop);
ct.setOriginalRequest(sipRequest);
ct.setBranch(branchId);
// if the stack supports dialogs then
if (sipStack.isDialogCreated(request.getMethod())) {
// (but noticed by Brad Templeton)
if (dialog != null)
ct.setDialog(dialog, sipRequest.getDialogId(false));
else if (this.isAutomaticDialogSupportEnabled()) {
SIPDialog sipDialog = sipStack.createDialog(ct);
ct.setDialog(sipDialog, sipRequest.getDialogId(false));
}
} else {
if (dialog != null) {
ct.setDialog(dialog, sipRequest.getDialogId(false));
}
}
// The provider is the event listener for all transactions.
ct.addEventListener(this);
return (ClientTransaction) ct;
} catch (IOException ex) {
throw new TransactionUnavailableException("Could not resolve next hop or listening point unavailable! ", ex);
} catch (java.text.ParseException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
} catch (InvalidArgumentException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
}
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SipProviderImpl method sendResponse.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#sendResponse(javax.sip.message.Response)
*/
public void sendResponse(Response response) throws SipException {
if (!sipStack.isAlive())
throw new SipException("Stack is stopped");
SIPResponse sipResponse = (SIPResponse) response;
Via via = sipResponse.getTopmostVia();
if (via == null)
throw new SipException("No via header in response!");
SIPServerTransaction st = (SIPServerTransaction) sipStack.findTransaction((SIPMessage) response, true);
if (st != null && st.getState() != TransactionState.TERMINATED && this.isAutomaticDialogSupportEnabled()) {
throw new SipException("Transaction exists -- cannot send response statelessly");
}
String transport = via.getTransport();
// check to see if Via has "received paramaeter". If so
// set the host to the via parameter. Else set it to the
// Via host.
String host = via.getReceived();
if (host == null)
host = via.getHost();
// Symmetric nat support
int port = via.getRPort();
if (port == -1) {
port = via.getPort();
if (port == -1) {
if (transport.equalsIgnoreCase("TLS"))
port = 5061;
else
port = 5060;
}
}
// for correct management of IPv6 addresses.
if (host.indexOf(":") > 0)
if (host.indexOf("[") < 0)
host = "[" + host + "]";
Hop hop = sipStack.getAddressResolver().resolveAddress(new HopImpl(host, port, transport));
try {
ListeningPointImpl listeningPoint = (ListeningPointImpl) this.getListeningPoint(transport);
if (listeningPoint == null)
throw new SipException("whoopsa daisy! no listening point found for transport " + transport);
MessageChannel messageChannel = sipStack.createRawMessageChannel(this.getListeningPoint(hop.getTransport()).getIPAddress(), listeningPoint.port, hop);
messageChannel.sendMessage(sipResponse);
} catch (IOException ex) {
throw new SipException(ex.getMessage());
}
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class UDPMessageChannel method processIncomingDataPacket.
/**
* Process an incoming datagram
*
* @param packet
* is the incoming datagram packet.
*/
private void processIncomingDataPacket(DatagramPacket packet) throws Exception {
this.peerAddress = packet.getAddress();
int packetLength = packet.getLength();
// Read bytes and put it in a eueue.
byte[] bytes = packet.getData();
byte[] msgBytes = new byte[packetLength];
System.arraycopy(bytes, 0, msgBytes, 0, packetLength);
// Do debug logging.
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("UDPMessageChannel: processIncomingDataPacket : peerAddress = " + peerAddress.getHostAddress() + "/" + packet.getPort() + " Length = " + packetLength);
}
SIPMessage sipMessage = null;
try {
this.receptionTime = System.currentTimeMillis();
sipMessage = myParser.parseSIPMessage(msgBytes);
myParser = null;
} catch (ParseException ex) {
// let go of the parser reference.
myParser = null;
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("Rejecting message ! " + new String(msgBytes));
this.sipStack.getStackLogger().logDebug("error message " + ex.getMessage());
this.sipStack.getStackLogger().logException(ex);
}
// JvB: send a 400 response for requests (except ACK)
// Currently only UDP, @todo also other transports
String msgString = new String(msgBytes, 0, packetLength);
if (!msgString.startsWith("SIP/") && !msgString.startsWith("ACK ")) {
String badReqRes = createBadReqRes(msgString, ex);
if (badReqRes != null) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Sending automatic 400 Bad Request:");
sipStack.getStackLogger().logDebug(badReqRes);
}
try {
this.sendMessage(badReqRes.getBytes(), peerAddress, packet.getPort(), "UDP", false);
} catch (IOException e) {
this.sipStack.getStackLogger().logException(e);
}
} else {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Could not formulate automatic 400 Bad Request");
}
}
}
return;
}
if (sipMessage == null) {
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("Rejecting message ! + Null message parsed.");
}
if (pingBackRecord.get(packet.getAddress().getHostAddress() + ":" + packet.getPort()) == null) {
byte[] retval = "\r\n\r\n".getBytes();
DatagramPacket keepalive = new DatagramPacket(retval, 0, retval.length, packet.getAddress(), packet.getPort());
((UDPMessageProcessor) this.messageProcessor).sock.send(keepalive);
this.sipStack.getTimer().schedule(new PingBackTimerTask(packet.getAddress().getHostAddress(), packet.getPort()), 1000);
}
return;
}
ViaList viaList = sipMessage.getViaHeaders();
// Check for the required headers.
if (sipMessage.getFrom() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) {
String badmsg = new String(msgBytes);
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logError("bad message " + badmsg);
this.sipStack.getStackLogger().logError(">>> Dropped Bad Msg " + "From = " + sipMessage.getFrom() + "To = " + sipMessage.getTo() + "CallId = " + sipMessage.getCallId() + "CSeq = " + sipMessage.getCSeq() + "Via = " + sipMessage.getViaHeaders());
}
return;
}
// For response, just get the port from the packet.
if (sipMessage instanceof SIPRequest) {
Via v = (Via) viaList.getFirst();
Hop hop = sipStack.addressResolver.resolveAddress(v.getHop());
this.peerPort = hop.getPort();
this.peerProtocol = v.getTransport();
this.peerPacketSourceAddress = packet.getAddress();
this.peerPacketSourcePort = packet.getPort();
try {
this.peerAddress = packet.getAddress();
// Check to see if the received parameter matches
// the peer address and tag it appropriately.
boolean hasRPort = v.hasParameter(Via.RPORT);
if (hasRPort || !hop.getHost().equals(this.peerAddress.getHostAddress())) {
v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress());
}
if (hasRPort) {
v.setParameter(Via.RPORT, Integer.toString(this.peerPacketSourcePort));
}
} catch (java.text.ParseException ex1) {
InternalErrorHandler.handleException(ex1);
}
} else {
this.peerPacketSourceAddress = packet.getAddress();
this.peerPacketSourcePort = packet.getPort();
this.peerAddress = packet.getAddress();
this.peerPort = packet.getPort();
this.peerProtocol = ((Via) viaList.getFirst()).getTransport();
}
this.processMessage(sipMessage);
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class TCPMessageChannel method processMessage.
/**
* Gets invoked by the parser as a callback on successful message parsing (i.e. no parser
* errors).
*
* @param sipMessage Mesage to process (this calls the application for processing the
* message).
*/
public void processMessage(SIPMessage sipMessage) throws Exception {
try {
if (sipMessage.getFrom() == null || // == null ||
sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) {
String badmsg = sipMessage.encode();
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug(">>> Dropped Bad Msg");
sipStack.getStackLogger().logDebug(badmsg);
}
return;
}
ViaList viaList = sipMessage.getViaHeaders();
// message.
if (sipMessage instanceof SIPRequest) {
Via v = (Via) viaList.getFirst();
Hop hop = sipStack.addressResolver.resolveAddress(v.getHop());
this.peerProtocol = v.getTransport();
try {
this.peerAddress = mySock.getInetAddress();
// JvB: if sender added 'rport', must always set received
if (v.hasParameter(Via.RPORT) || !hop.getHost().equals(this.peerAddress.getHostAddress())) {
v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress());
}
// @@@ hagai
// JvB: technically, may only do this when Via already
// contains
// rport
v.setParameter(Via.RPORT, Integer.toString(this.peerPort));
} catch (java.text.ParseException ex) {
InternalErrorHandler.handleException(ex, sipStack.getStackLogger());
}
// Use this for outgoing messages as well.
if (!this.isCached) {
((TCPMessageProcessor) this.messageProcessor).cacheMessageChannel(this);
this.isCached = true;
int remotePort = ((java.net.InetSocketAddress) mySock.getRemoteSocketAddress()).getPort();
String key = IOHandler.makeKey(mySock.getInetAddress(), remotePort);
sipStack.ioHandler.putSocket(key, mySock);
}
}
// Foreach part of the request header, fetch it and process it
long receptionTime = System.currentTimeMillis();
if (sipMessage instanceof SIPRequest) {
// This is a request - process the request.
SIPRequest sipRequest = (SIPRequest) sipMessage;
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("----Processing Message---");
}
// if it is too long.
if (this.sipStack.getStackLogger().isLoggingEnabled(ServerLogger.TRACE_MESSAGES)) {
sipStack.serverLogger.logMessage(sipMessage, this.getPeerHostPort().toString(), this.getMessageProcessor().getIpAddress().getHostAddress() + ":" + this.getMessageProcessor().getPort(), false, receptionTime);
}
if (sipStack.getMaxMessageSize() > 0 && sipRequest.getSize() + (sipRequest.getContentLength() == null ? 0 : sipRequest.getContentLength().getContentLength()) > sipStack.getMaxMessageSize()) {
SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.MESSAGE_TOO_LARGE);
byte[] resp = sipResponse.encodeAsBytes(this.getTransport());
this.sendMessage(resp, false);
throw new Exception("Message size exceeded");
}
ServerRequestInterface sipServerRequest = sipStack.newSIPServerRequest(sipRequest, this);
if (sipServerRequest != null) {
try {
sipServerRequest.processRequest(sipRequest, this);
} finally {
if (sipServerRequest instanceof SIPTransaction) {
SIPServerTransaction sipServerTx = (SIPServerTransaction) sipServerRequest;
if (!sipServerTx.passToListener())
((SIPTransaction) sipServerRequest).releaseSem();
}
}
} else {
if (sipStack.isLoggingEnabled())
this.sipStack.getStackLogger().logWarning("Dropping request -- could not acquire semaphore in 10 sec");
}
} else {
SIPResponse sipResponse = (SIPResponse) sipMessage;
// sipResponse.getTo().removeParameter("tag");
try {
sipResponse.checkHeaders();
} catch (ParseException ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logError("Dropping Badly formatted response message >>> " + sipResponse);
return;
}
// If it is too large dump it silently.
if (sipStack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse.getContentLength().getContentLength()) > sipStack.getMaxMessageSize()) {
if (sipStack.isLoggingEnabled())
this.sipStack.getStackLogger().logDebug("Message size exceeded");
return;
}
ServerResponseInterface sipServerResponse = sipStack.newSIPServerResponse(sipResponse, this);
if (sipServerResponse != null) {
try {
if (sipServerResponse instanceof SIPClientTransaction && !((SIPClientTransaction) sipServerResponse).checkFromTag(sipResponse)) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logError("Dropping response message with invalid tag >>> " + sipResponse);
return;
}
sipServerResponse.processResponse(sipResponse, this);
} finally {
if (sipServerResponse instanceof SIPTransaction && !((SIPTransaction) sipServerResponse).passToListener())
((SIPTransaction) sipServerResponse).releaseSem();
}
} else {
sipStack.getStackLogger().logWarning("Application is blocked -- could not acquire semaphore -- dropping response");
}
}
} finally {
}
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SIPDialog method sendAck.
/**
* Sends ACK Request to the remote party of this Dialogue.
*
*
* @param request the new ACK Request message to send.
* @param throwIOExceptionAsSipException - throws SipException if IOEx encountered. Otherwise,
* no exception is propagated.
* @param releaseAckSem - release ack semaphore.
* @throws SipException if implementation cannot send the ACK Request for any other reason
*
*/
private void sendAck(Request request, boolean throwIOExceptionAsSipException) throws SipException {
SIPRequest ackRequest = (SIPRequest) request;
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("sendAck" + this);
if (!ackRequest.getMethod().equals(Request.ACK))
throw new SipException("Bad request method -- should be ACK");
if (this.getState() == null || this.getState().getValue() == EARLY_STATE) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("Bad Dialog State for " + this + " dialogID = " + this.getDialogId());
}
throw new SipException("Bad dialog state " + this.getState());
}
if (!this.getCallId().getCallId().equals(((SIPRequest) request).getCallId().getCallId())) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("CallID " + this.getCallId());
sipStack.getStackLogger().logError("RequestCallID = " + ackRequest.getCallId().getCallId());
sipStack.getStackLogger().logError("dialog = " + this);
}
throw new SipException("Bad call ID in request");
}
try {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("setting from tag For outgoing ACK= " + this.getLocalTag());
sipStack.getStackLogger().logDebug("setting To tag for outgoing ACK = " + this.getRemoteTag());
sipStack.getStackLogger().logDebug("ack = " + ackRequest);
}
if (this.getLocalTag() != null)
ackRequest.getFrom().setTag(this.getLocalTag());
if (this.getRemoteTag() != null)
ackRequest.getTo().setTag(this.getRemoteTag());
} catch (ParseException ex) {
throw new SipException(ex.getMessage());
}
Hop hop = sipStack.getNextHop(ackRequest);
// Hop hop = defaultRouter.getNextHop(ackRequest);
if (hop == null)
throw new SipException("No route!");
try {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("hop = " + hop);
ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider.getListeningPoint(hop.getTransport());
if (lp == null)
throw new SipException("No listening point for this provider registered at " + hop);
InetAddress inetAddress = InetAddress.getByName(hop.getHost());
MessageChannel messageChannel = lp.getMessageProcessor().createMessageChannel(inetAddress, hop.getPort());
boolean releaseAckSem = false;
long cseqNo = ((SIPRequest) request).getCSeq().getSeqNumber();
if (!this.isAckSent(cseqNo)) {
releaseAckSem = true;
}
this.setLastAckSent(ackRequest);
messageChannel.sendMessage(ackRequest);
// Sent atleast one ACK.
this.isAcknowledged = true;
this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged, ((SIPRequest) ackRequest).getCSeq().getSeqNumber());
if (releaseAckSem && this.isBackToBackUserAgent) {
this.releaseAckSem();
} else {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Not releasing ack sem for " + this + " isAckSent " + releaseAckSem);
}
}
} catch (IOException ex) {
if (throwIOExceptionAsSipException)
throw new SipException("Could not send ack", ex);
this.raiseIOException(hop.getHost(), hop.getPort(), hop.getTransport());
} catch (SipException ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
throw ex;
} catch (Exception ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
throw new SipException("Could not create message channel", ex);
}
if (this.dialogDeleteTask != null) {
this.dialogDeleteTask.cancel();
this.dialogDeleteTask = null;
}
this.ackSeen = true;
}
Aggregations