📄 vojxtacallcontrol.java
字号:
} DialogMessage msg = (DialogMessage)templateMessage.clone (); StringMessageElement commandElement = new StringMessageElement ( TAG_SESSION_COMMAND, command, null); msg.addMessageElement (TAG_SESSION_COMMAND, commandElement); if(elementMap != null) { Iterator keys = elementMap.keySet ().iterator (); while(keys.hasNext ()) { String elementName = (String)keys.next (); MessageElement element = (MessageElement)elementMap.get (elementName); msg.addMessageElement (elementName, element); LOG.info ("added element "+elementName); } } if(ackCommand != null) { this.messageAckThread = new MessageAckThread (ackCommand); this.messageAckThread.start (); } this.vojxtaDialog.dispatch (msg); } /** * Session state was meant for the UI as a messaging signaler to users */ private void setSessionState (int sessionState) { this.sessionState = sessionState; this.vojxtaView.sessionStateChanged (this.sessionState); } /** * Returns the current session state */ public int getSessionState () { return this.sessionState; } /** * This method updates the current protocol state. Also signals the UI * of a protocol state change. */ private void setProtocolState (int protocolState) { this.protocolState = protocolState; if(this.protocolState == this.SESSION_VOJXTA_INVITE_REQUEST_SENT || this.protocolState == this.SESSION_VOJXTA_INVITE_REQUEST_RECEIVED) { setSessionState (this.SESSION_VOJXTA_CONNECTING); }else if (this.protocolState == this.SESSION_VOJXTA_INVITE_ACCEPT_SENT || this.protocolState == this.SESSION_VOJXTA_INVITE_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_CONNECTED); }else if (this.protocolState == this.SESSION_VOJXTA_START_REQUEST_SENT || this.protocolState == this.SESSION_VOJXTA_START_REQUEST_RECEIVED) { setSessionState (this.SESSION_VOJXTA_STARTING); }else if (this.protocolState == this.SESSION_VOJXTA_START_ACCEPT_SENT || this.protocolState == this.SESSION_VOJXTA_START_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_STARTED); }else if (this.protocolState == this.SESSION_VOJXTA_HOLD_ACCEPT_SENT || this.protocolState == this.SESSION_VOJXTA_HOLD_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_HOLDING); }else if (this.protocolState == this.SESSION_VOJXTA_INCALL) { setSessionState (this.SESSION_VOJXTA_INCALL); }else if (this.protocolState == this.SESSION_VOJXTA_RESUME_ACCEPT_SENT || this.protocolState == this.SESSION_VOJXTA_RESUME_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_INCALL); }else if (this.protocolState == this.SESSION_VOJXTA_HANGUP_REQUEST_SENT|| this.protocolState == this.SESSION_VOJXTA_HANGUP_REQUEST_RECEIVED) { setSessionState (this.SESSION_VOJXTA_ENDING); }else if (this.protocolState == this.SESSION_VOJXTA_HANGUP_ACCEPT_SENT|| this.protocolState == this.SESSION_VOJXTA_HANGUP_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_ENDED); }else if (this.protocolState == this.SESSION_VOJXTA_DISCONNECT_REQUEST_SENT || this.protocolState == this.SESSION_VOJXTA_DISCONNECT_REQUEST_RECEIVED) { setSessionState (this.SESSION_VOJXTA_DISCONNECTING); }else if (this.protocolState == this.SESSION_VOJXTA_DISCONNECT_ACCEPT_SENT|| this.protocolState == this.SESSION_VOJXTA_DISCONNECT_ACCEPT_RECEIVED) { setSessionState (this.SESSION_VOJXTA_DISCONNECTED); } if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("ProtocolStateChanged to "+ protocolState); } this.vojxtaView.protocolStateChanged (protocolState); } /** * Returns the protocol state */ public int getProtocolState () { return this.protocolState; } /** * Returns the current time in milliseconds to wait for a message respose * before session shutdown. */ public long getMessageAckTimeout () { return (messageAckTimeout > this.MINIMUM_MESSAGE_ACK_TIMEOUT) ? messageAckTimeout : DEFAULT_MESSAGE_ACK_TIMEOUT; } public void setMessageAckTimeout (long timeInMilliseconds) { if (timeInMilliseconds > MINIMUM_MESSAGE_ACK_TIMEOUT) { this.messageAckTimeout = timeInMilliseconds; } } /** * Message ack thread has timed out and no message ack has been received. * End session. */ protected void localActionMessageGoneUnAcknowledged () { if (LOG.isEnabledFor (Level.INFO)) { LOG.info (" localActionMessageGoneUnAcknowledged "); } localActionEndSession (); /** Normally we'd just call sendcommand(END_SESSION) and wait for a * end END_SEESION_ACCEPT then go down gracefully. Since we aren't * receiving command messages we choose to just exit hard. */ /* DialogMessage msg = (DialogMessage)templateMessage.clone (); StringMessageElement commandElement = new StringMessageElement ( TAG_SESSION_COMMAND, this.COMMAND_VOJXTA_DISCONNECT_REQUEST, null); msg.addMessageElement (TAG_SESSION_COMMAND, commandElement); this.vojxtaDialog.dispatch (msg); **/ sendCommand (this.COMMAND_VOJXTA_DISCONNECT_REQUEST, null); this.setProtocolState (this.SESSION_VOJXTA_DISCONNECTED); } /** * After a message is sent this thread is instantiated, started and will * wait till it's lock is notified of an incoming message or till a timeout * is reached. The idea being each commmand message dispatched will return * an accept response. If that response is received then +1 if not this thread * will notify us and shutdown the session as gracefully as possible. A new * Thread is started for each command message sent. *TODO * Better option then creating a new thread for each command. Reuse of a single * thread maybe. */ class MessageAckThread extends Thread { private AckWaitLock ackWaitLock = null; private String commandName = null; private boolean threadEnded = false; public MessageAckThread (String commandName) { if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("MessageAckThread waiting for command "+ commandName); } ackWaitLock = new AckWaitLock (); this.commandName = commandName; this.setPriority (Thread.MIN_PRIORITY); //this.setDaemon (true); } public void run () { if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("MessageAckThread : Run "); } try { synchronized(ackWaitLock) { ackWaitLock.wait (getMessageAckTimeout ()); } }catch(InterruptedException ix) { ix.printStackTrace (); } synchronized(ackWaitLock) { if ( !ackWaitLock.isAcknowledged ()) { if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("MessageAckThread : " + this.commandName + " command NOT acknowledged"); } VoJxtaCallControl.this.localActionMessageGoneUnAcknowledged (); } } this.threadEnded = true; } /** * Avoids a race condition... needs to be reworked. */ public boolean isThreadEnded () { while(!this.threadEnded) { try{ Thread.sleep (100); }catch(InterruptedException ix) { ix.printStackTrace (); } } return this.threadEnded; } /** * A message was received and this thread is alerted. */ public void setMessageAcknowledged (String commandName) { synchronized(ackWaitLock) { if(this.commandName.equals (commandName)) { if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("MessageAckThread : Received RIGHT Ack " + commandName + " for " + this.commandName + " : Command Ack"); } ackWaitLock.setAcknowledged (true); }else{ if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("MessageAckThread : Received WRONG Ack " + commandName + " for " + this.commandName + " : Command Ack"); } } ackWaitLock.notify (); } } class AckWaitLock extends Object { private boolean acknowledged = false; public boolean isAcknowledged () { return acknowledged; } public void setAcknowledged (boolean acknowledged) { this.acknowledged = acknowledged; if (LOG.isEnabledFor (Level.INFO)) { LOG.info ("AckWaitLock : SetAcknowldge " +acknowledged); } } } } /** * Because we push the voice payload through without periodic ack's we need * a thread to count a timeout in case the other side goes down. Time out * of 40 seconds while IN CALL should be enough for any relay to catch up. *A more elegant solution is needed though i'd still like to keep it simple. *With reliable pipes SIP type acks seem too much * */ class ReceivedMessageTimeoutThread extends Thread { public static final int SLEEP_TIME = 1000; public static final long DEFAULT_PAYLOAD_MESSAGE_TIMEOUT = 1000 * 40; public static final long MINIMUM_PAYLOAD_MESSAGE_TIMEOUT = 1000 * 40; private long payloadMessageTimeout = DEFAULT_PAYLOAD_MESSAGE_TIMEOUT; private boolean run = true; public ReceivedMessageTimeoutThread () { setPriority (Thread.MIN_PRIORITY); //this.setDaemon (true); } public long getPayloadMessageTimeout () { return payloadMessageTimeout; } public void setPayloadMessageTimeout (long payloadMessageTimeout) { if(payloadMessageTimeout >= MINIMUM_PAYLOAD_MESSAGE_TIMEOUT) { this.payloadMessageTimeout = payloadMessageTimeout; } } public void stopThread () { run = false; } public void run () { while(run) { try { Thread.sleep (VoJxtaCallControl.SECOND); }catch(InterruptedException ix) { ix.printStackTrace (); } if(getProtocolState () == VoJxtaCallControl.SESSION_VOJXTA_HOLDING) { continue; } long lastMessageReceived = 0; if(speakerControl !=null) { lastMessageReceived = speakerControl.getTimeOfLastVoiceMessage (); } long currentTime = System.currentTimeMillis (); if(getProtocolState() == VoJxtaCallControl.SESSION_VOJXTA_INCALL && (currentTime - lastMessageReceived) > getPayloadMessageTimeout ()) { if(LOG.isEnabledFor (Level.INFO)) { LOG.info (" diff "+(currentTime-lastMessageReceived)+ " > "+getPayloadMessageTimeout ()); } VoJxtaCallControl.this.localActionMessageGoneUnAcknowledged (); } } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -