/* * TeleStax, Open Source Cloud Communications * Copyright 2011-2015, Telestax Inc and individual contributors * by the @authors tag. * * This program is free software: you can redistribute it and/or modify * under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * * For questions related to commercial use licensing, please contact sales@telestax.com. * */ package org.restcomm.android.sdk.SignalingClient; import android.os.Handler; import android.os.Looper; import android.os.Message; import org.restcomm.android.sdk.RCClient; import org.restcomm.android.sdk.RCDeviceListener; import org.restcomm.android.sdk.SignalingClient.JainSipClient.JainSipCall; import org.restcomm.android.sdk.SignalingClient.JainSipClient.JainSipClient; import org.restcomm.android.sdk.util.RCLogger; import java.util.HashMap; /** * SignalingHandler takes care of all the messaging from UI thread -> JainSipClient and the opposite */ class SignalingHandler extends Handler implements JainSipClient.JainSipClientListener, JainSipCall.JainSipCallListener { JainSipClient jainSipClient; Handler uiHandler; private static final String TAG = "SignalingHandler"; public SignalingHandler(Looper looper, Handler uiHandler) { // instantiate parent Handler, and pass non UI looper remember by default associates this handler with the Looper for the current thread, hence signaling thread super(looper); this.uiHandler = uiHandler; jainSipClient = null; } @Override public void handleMessage(Message inputMessage) { // Gets the image task from the incoming Message object. SignalingMessage message = (SignalingMessage) inputMessage.obj; RCLogger.i(TAG, "handleMessage: type: " + message.type + ", jobId: " + message.jobId); // all requests apart from OPEN_REQUEST require an initialized jainSipClient if (message.type != SignalingMessage.MessageType.OPEN_REQUEST && jainSipClient == null) { // wrong usage of API throw new RuntimeException("JainSipClient has not been initialized"); } if (message.type == SignalingMessage.MessageType.OPEN_REQUEST) { if (jainSipClient != null) { onClientOpenedReply(message.jobId, RCDeviceListener.RCConnectivityStatus.RCConnectivityStatusNone, RCClient.ErrorCodes.ERROR_DEVICE_ALREADY_OPEN, RCClient.errorText(RCClient.ErrorCodes.ERROR_DEVICE_ALREADY_OPEN)); return; } jainSipClient = new JainSipClient(this); jainSipClient.open(message.jobId, message.androidContext, message.parameters, this); } else if (message.type == SignalingMessage.MessageType.CLOSE_REQUEST) { jainSipClient.close(message.jobId); } if (message.type == SignalingMessage.MessageType.RECONFIGURE_REQUEST) { jainSipClient.reconfigure(message.jobId, message.parameters, this); } else if (message.type == SignalingMessage.MessageType.CALL_REQUEST) { jainSipClient.call(message.jobId, message.parameters, this); } else if (message.type == SignalingMessage.MessageType.CALL_DISCONNECT_REQUEST) { jainSipClient.disconnect(message.jobId, message.reason, this); } else if (message.type == SignalingMessage.MessageType.CALL_ACCEPT_REQUEST) { jainSipClient.accept(message.jobId, message.parameters, this); } else if (message.type == SignalingMessage.MessageType.MESSAGE_REQUEST) { jainSipClient.sendMessage(message.jobId, message.parameters); } else if (message.type == SignalingMessage.MessageType.CALL_SEND_DIGITS_REQUEST) { jainSipClient.sendDigits(message.jobId, message.dtmfDigits); } } // -- JainSipClientListener events public void onClientOpenedReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onClientOpenedReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.OPEN_REPLY); signalingMessage.status = status; //RCClient.ErrorCodes.SUCCESS; signalingMessage.text = text; //"Success"; signalingMessage.connectivityStatus = connectivityStatus; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientErrorReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onClientErrorReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.ERROR_EVENT); signalingMessage.status = status; signalingMessage.text = text; signalingMessage.connectivityStatus = connectivityStatus; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientClosedEvent(String jobId, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onClientClosedEvent: jobId: " + jobId + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CLOSE_REPLY); signalingMessage.status = status; //RCClient.ErrorCodes.SUCCESS; signalingMessage.text = text; //"Success"; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); // remove reference so that it can be GC'd this.jainSipClient = null; } public void onClientReconfigureReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onClientReconfigureReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.RECONFIGURE_REPLY); signalingMessage.status = status; //RCClient.ErrorCodes.SUCCESS; signalingMessage.text = text; //"Success"; signalingMessage.connectivityStatus = connectivityStatus; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientConnectivityEvent(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus) { RCLogger.v(TAG, "onClientConnectivityEvent: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CONNECTIVITY_EVENT); signalingMessage.connectivityStatus = connectivityStatus; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientMessageArrivedEvent(String jobId, String peer, String messageText) { RCLogger.v(TAG, "onClientMessageArrivedEvent: jobId: " + jobId + ", peer: " + peer + ", messageText: " + messageText); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.MESSAGE_INCOMING_EVENT); signalingMessage.messageText = messageText; signalingMessage.peer = peer; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientMessageReply(String jobId, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onClientMessageReply: jobId: " + jobId + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.MESSAGE_REPLY); signalingMessage.status = status; signalingMessage.text = text; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onClientRegisteringEvent(String jobId) { RCLogger.v(TAG, "onClientRegisteringEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.REGISTERING_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } // -- JainSipCallListener events public void onCallArrivedEvent(String jobId, String peer, String sdpOffer, HashMap<String, String> customHeaders) { RCLogger.v(TAG, "onCallArrivedEvent: jobId: " + jobId + ", peer: " + peer + ", sdpOffer: " + sdpOffer); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_INCOMING_EVENT); signalingMessage.sdp = sdpOffer; signalingMessage.customHeaders = customHeaders; signalingMessage.peer = peer; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallOutgoingConnectedEvent(String jobId, String sdpAnswer, HashMap<String, String> customHeaders) { RCLogger.v(TAG, "onCallOutgoingConnectedEvent: jobId: " + jobId + ", sdpAnswer: " + sdpAnswer); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_OUTGOING_CONNECTED_EVENT); signalingMessage.sdp = sdpAnswer; signalingMessage.customHeaders = customHeaders; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallIncomingConnectedEvent(String jobId) { RCLogger.v(TAG, "onCallIncomingConnectedEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_INCOMING_CONNECTED_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallPeerDisconnectedEvent(String jobId) { RCLogger.v(TAG, "onCallPeerDisconnectedEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_PEER_DISCONNECT_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallLocalDisconnectedEvent(String jobId) { RCLogger.v(TAG, "onCallLocalDisconnectedEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_LOCAL_DISCONNECT_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallOutgoingPeerRingingEvent(String jobId) { RCLogger.v(TAG, "onCallOutgoingPeerRingingEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_OUTGOING_PEER_RINGING_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallIncomingCanceledEvent(String jobId) { RCLogger.v(TAG, "onCallIncomingCanceledEvent: jobId: " + jobId); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_INCOMING_CANCELED_EVENT); Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallIgnoredEvent(String jobId) { RCLogger.v(TAG, "onCallIgnoredEvent: jobId: " + jobId); } public void onCallErrorEvent(String jobId, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onCallErrorEvent: jobId: " + jobId + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_ERROR_EVENT); signalingMessage.status = status; signalingMessage.text = text; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } public void onCallDigitsEvent(String jobId, RCClient.ErrorCodes status, String text) { RCLogger.v(TAG, "onCallDigitsEvent: jobId: " + jobId + ", status: " + status + ", text: " + text); SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_SEND_DIGITS_EVENT); signalingMessage.status = status; signalingMessage.text = text; Message message = uiHandler.obtainMessage(1, signalingMessage); message.sendToTarget(); } }