/* * Created on Aug 26, 2005 * *Copyright Reliable Response, 2005 */ package net.reliableresponse.notification.sip; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringBufferInputStream; import java.net.UnknownHostException; import java.text.ParseException; import java.util.Vector; import javax.media.NoDataSinkException; import javax.media.NoDataSourceException; import javax.media.NoProcessorException; import javax.media.NotConfiguredError; import javax.media.NotRealizedError; import javax.media.rtp.InvalidSessionAddressException; import javax.sdp.SdpException; import javax.sdp.SdpParseException; import javax.sip.InvalidArgumentException; import javax.sip.PeerUnavailableException; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.SipException; import javax.sip.Transaction; import javax.sip.TransactionUnavailableException; import javax.sip.header.CSeqHeader; import javax.sip.header.CallIdHeader; import javax.sip.message.Message; import javax.sip.message.Request; import javax.sip.message.Response; import javax.xml.parsers.DocumentBuilderFactory; import net.reliableresponse.notification.Notification; import net.reliableresponse.notification.broker.BrokerFactory; import net.reliableresponse.notification.dialogic.DialogicAudioMessage; import net.reliableresponse.notification.dialogic.DialogicOutgoingMessage; import net.reliableresponse.notification.providers.NotificationProvider; import net.reliableresponse.notification.tts.FreeTTS; import org.w3c.dom.Document; /** * @author drig * * Copyright 2004 - David Rudder */ public class SipOutgoing extends SipOutboundCall implements PickupListener { private static SipOutgoing instance; Vector messages; String host; int port; private SipOutgoing(String host, int port) { super(host, port); BrokerFactory.getLoggingBroker().logDebug( "Initializing Sip Outgoing at " + host + ":" + port); this.host = host; this.port = port; messages = new Vector(); sipHandler.addDTMFListener(this); sipHandler.addRequestListener(this); sipHandler.addResponseListener(this); sipHandler.setUsername("reliableresponse"); addPickupListener(this); } public static SipOutgoing getInstance() { if (instance == null) { String host = BrokerFactory.getConfigurationBroker() .getStringValue("sip.gateway.host"); int port = BrokerFactory.getConfigurationBroker().getIntValue( "sip.gateway.port", 5061); instance = new SipOutgoing(host, port); } return instance; } public void addMessage(DialogicAudioMessage message) { messages.addElement(message); BrokerFactory.getLoggingBroker().logDebug("SIP Message queue has "+messages.size()+" messages"); if (messages.size() == 1) { playNextMessage(); } } private void playNextMessage() { if ((messages == null) || (messages.size() <= 0)) { BrokerFactory.getLoggingBroker().logWarn( "playNextMessage called without a message to play"); } DialogicAudioMessage message = (DialogicAudioMessage) messages .elementAt(0); try { super.makeCall("sip:" + message.getPhoneNumber() + "@" + host + ":" + port); message.setCallID(sipHandler.getCallID()); } catch (PeerUnavailableException e) { BrokerFactory.getLoggingBroker().logError(e); } catch (TransactionUnavailableException e) { BrokerFactory.getLoggingBroker().logError(e); } catch (ParseException e) { BrokerFactory.getLoggingBroker().logError(e); } catch (InvalidArgumentException e) { BrokerFactory.getLoggingBroker().logError(e); } catch (SipException e) { BrokerFactory.getLoggingBroker().logError(e); } } void startConversation(Message response, Transaction clientTransaction) throws SipException, SdpParseException, SdpException, IOException, NoDataSourceException, NoProcessorException, InterruptedException, NotConfiguredError, NotRealizedError, NoDataSinkException, InvalidSessionAddressException, UnknownHostException { super.startConversation(response, clientTransaction); DialogicAudioMessage message = (DialogicAudioMessage) messages.elementAt(0); transmitter.playSound("file:///" + message.getWaveFile()); } public void handlePickup() { DialogicAudioMessage message = (DialogicAudioMessage)messages.elementAt(0); BrokerFactory.getLoggingBroker().logDebug ("transmitter="+transmitter); BrokerFactory.getLoggingBroker().logDebug ("message = "+message); transmitter.playSound("file:///"+message.getWaveFile()); } public void handleDTMF(String digit) { DialogicOutgoingMessage message = (DialogicOutgoingMessage) messages .elementAt(0); Notification notification = message.getNotification(); String[] responses = notification.getSender().getAvailableResponses( notification); int responseNum = 0; try { responseNum = Integer.parseInt(digit); BrokerFactory.getLoggingBroker().logDebug( "num responses = " + responses.length); BrokerFactory.getLoggingBroker().logDebug( "response num = " + responseNum); notification.getSender().handleResponse(notification, null, responses[responseNum - 1], null); // TODO: Make this work with the responses String responseMessage = "<jsml>Your response has been received. Thank you</jsml>"; DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); factory.setValidating(false); Document doc = factory.newDocumentBuilder().parse( new StringBufferInputStream(responseMessage)); byte[] wav = new FreeTTS().getWav(doc); transmitter.playSound(new InputStreamDataSource( new ByteArrayInputStream(wav), "audio.x_wav")); } catch (NumberFormatException nfExc) { BrokerFactory.getLoggingBroker().logInfo( "Got a bad digit in the outgoing response: " + digit); } catch (Exception anyExc) { BrokerFactory.getLoggingBroker().logError(anyExc); } } public void handleRequest(RequestEvent requestEvent) { super.handleRequest(requestEvent); Request request = requestEvent.getRequest(); BrokerFactory.getLoggingBroker().logDebug("Got request in SipOutgoing "+request); String method = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)) .getMethod(); if (method.equals(Request.BYE)) { if (messages.size() > 0) { BrokerFactory.getLoggingBroker().logDebug( "Got BYE, removing message"); DialogicAudioMessage message = (DialogicAudioMessage) messages .elementAt(0); if (message != null) { CallIdHeader callIDHeader = (CallIdHeader) request .getHeader("Call-ID"); BrokerFactory.getLoggingBroker().logDebug( "Message's call id = " + message.getCallID()); BrokerFactory.getLoggingBroker().logDebug( "Response's call id = " + callIDHeader.getCallId()); if (message.getCallID().equals(callIDHeader.getCallId())) { messages.remove(0); } } } if (messages.size() > 0) { playNextMessage(); } } } public void handleResponse(ResponseEvent responseEvent) { super.handleResponse(responseEvent); Response response = responseEvent.getResponse(); BrokerFactory.getLoggingBroker().logDebug("Got response in SipOutgoing "+response); String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)) .getMethod(); if (method.equals(Request.BYE)) { if (messages.size() > 0) { BrokerFactory.getLoggingBroker().logDebug( "Got BYE, removing message"); DialogicAudioMessage message = (DialogicAudioMessage) messages .elementAt(0); if (message != null) { CallIdHeader callIDHeader = (CallIdHeader) response .getHeader("Call-ID"); BrokerFactory.getLoggingBroker().logDebug( "Message's call id = " + message.getCallID()); BrokerFactory.getLoggingBroker().logDebug( "Response's call id = " + callIDHeader.getCallId()); if (message.getCallID().equals(callIDHeader.getCallId())) { messages.remove(0); } } } if (messages.size() > 0) { playNextMessage(); } } else if (response.getStatusCode() >= 400) { BrokerFactory.getLoggingBroker().logDebug("Got error - hanging up"); hangup(); if (messages.size() > 0) { BrokerFactory.getLoggingBroker().logDebug( "Got BYE, removing message"); DialogicAudioMessage message = (DialogicAudioMessage) messages .elementAt(0); if (message != null) { CallIdHeader callIDHeader = (CallIdHeader) response .getHeader("Call-ID"); BrokerFactory.getLoggingBroker().logDebug( "Message's call id = " + message.getCallID()); BrokerFactory.getLoggingBroker().logDebug( "Response's call id = " + callIDHeader.getCallId()); NotificationProvider provider = message.getNotificationProvider(); provider.setStatusOfSend(message.getNotification(), "Call failed with code "+response.getStatusCode()); if (message.getCallID().equals(callIDHeader.getCallId())) { messages.remove(0); } } } if (messages.size() > 0) { playNextMessage(); } } } }