The Swing based GUI front-end of the Kryptofon application that implements simple VoIP phone and chat client with encrypted peer-to-peer communication. More...
Public Member Functions | |
CryptoPhoneApp (String args[]) | |
Creates a new instance of the CryptoPhoneApp . | |
void | startKryptofonServices () |
Starts audio interface and UDP peer-to-peer channel. | |
void | stopKryptofonServices () |
Stops audio interface and UDP peer-to-peer channel. | |
void | keyPressed (KeyEvent ke) |
Implements KeyListener 's key pressed event. | |
void | keyReleased (KeyEvent ke) |
Implements KeyListener 's key released event. | |
void | keyTyped (KeyEvent ke) |
Implements KeyListener 's key typed event. | |
void | actionPerformed (ActionEvent ae) |
Handles events from Swing timer and buttons. | |
void | logMessage (final String str) |
Logs message formated with limited HTML (limited because of JEditorPane) | |
void | attention (String message) |
Displays attention messages to the user from Log subsystem. | |
String | getUserId () |
Returns configured user ID (username). | |
void | setPbxStatus (String str) |
Updates status message by updating window title. | |
void | report (String cssClass, String str) |
Reports a system message to log. | |
void | reportIncomingTextMessage (String cssClass, String userId, String message) |
Reports incoming message. | |
void | onInvite (final PBXClient.ControlMessage m) |
Handles on INVITE call-back from the PBXClient. | |
void | onRing (final PBXClient.ControlMessage m) |
Handles on RING call-back from the PBXClient. | |
void | onAccept (final PBXClient.ControlMessage m) |
Handles on ACCEPT call-back from the PBXClient. | |
void | onBye (final PBXClient.ControlMessage m) |
Handles on BYE call-back from the PBXClient. | |
void | onInstantMessage (final PBXClient.ControlMessage m) |
Handles on IMSG call-back from the PBXClient. | |
void | deferredOnInvite (final PBXClient.ControlMessage m) |
On INVITE call-back is triggered when PBXClient receives inviting message (indicating that someone is calling us). | |
void | deferredOnRing (final PBXClient.ControlMessage m) |
On RING call-back is triggered when PBXClient receives ringing message (indicating that the peer is alerting end-user). | |
void | deferredOnAccept (final PBXClient.ControlMessage m) |
On ACCEPT call-back is triggered when PBXClient receives accepting message (indicating that the peer has accepted our invite). | |
void | deferredOnBye (final PBXClient.ControlMessage m) |
On BYE call-back is triggered when PBXClient receives 'bye' message (indicating that the peer is clearing i.e. | |
void | deferredOnInstantMessage (final PBXClient.ControlMessage m) |
On IMSG call-back is triggered when PBXClient receives private instant message (encrypted with session's secret key). | |
void | dumpLogArea (String fileName) |
Dumps log area into html file. | |
StringBuffer | getContentsFromResourceOrFile (String path) |
Reads contents of the text file using URL class. | |
void | clearLogArea () |
Clears log area (with the contents of the "empty" template) | |
void | displayUsage () |
Displays usage information. | |
void | displayHelp () |
Displays help. | |
Static Public Member Functions | |
static void | main (final String args[]) |
Main entry point. | |
Package Attributes | |
PublicEncryptor | remotePublicKey = null |
The last public key received from remote peer. | |
Private Member Functions | |
void | createLayout () |
Creates layout of the GUI components. | |
void | createEventListeners () |
Creates event listeners. | |
void | sendButton_Clicked () |
Parses input text entered by the user in inputMsg. | |
void | listPeersButton_Clicked () |
Performs :list command. | |
void | dialButton_Clicked () |
Performs :invite command. | |
void | secureDialButton_Clicked () |
Performs :invite+ command. | |
void | hangupButton_Clicked () |
Performs :bye command. | |
void | formWindowClosing (WindowEvent evt) |
Closes application by gracefully terminating all threads. | |
void | mainTimerEvent () |
Handles events from application's mainTimer (an instance of the Swing timer). | |
String[] | tokenizeInputMessage () |
Tokenizes inputMsg into words and returns array of strings. | |
void | parseInputMessage () |
Parses input message from inputMsg and sends it to chat server. | |
void | sendInstantMessage (String message, boolean forceUnencrypted) |
Sends chat message (encrypted if we have established secure channel with the user). | |
boolean | executeCommand (String cmd, String[] args) |
Parses commands prefixed with ':' character. | |
PublicEncryptor | tryToVerifyInvitingCall (boolean silent) |
Verifies invitor's public key (signed by invitor's private key) against the public keys from authorized keys file. | |
void | acceptIncomingCall (boolean securedIfPossible) |
Accepts incoming invite. | |
Private Attributes | |
String | serverName = "atlas.dsv.su.se" |
The host name or IP address of the remote chat server. | |
int | serverPort = 9494 |
The TCP port where to connect to on remote chat server. | |
PBXClient | pbxChannel = null |
The instance of PBX client connected to remote chat server. | |
String | pbxChannelStatus = "" |
The last status message of the PBX channel (posted by the setPbxStatus()). | |
Timer | mainTimer = null |
Main timer (elapses every 1000 ms) | |
int | reconnectTimeout = -1 |
The reconnect delay timer (for timing delay between two reconnections). | |
int | reconnectRetryCount = 0 |
Retry counter of number of failed reconnecting attempts. | |
int | localUdpPort = 47000 |
The default local UDP port. | |
DatagramChannel | udpChannel = null |
The instance of the UDP transceiver responsible for peer-to-peer communication between two Kryptofons. | |
AudioInterface | audioInterface = null |
The instance of the Audio interface used to access microphone and speaker. | |
PBXClient.ControlMessage | lastMessageFromPBX = null |
The last PBX control message sent to us (waiting to be handled) | |
String | currentInvite = null |
The remote peer (its user id) that we are currently inviting to a call. | |
int | inviteTimeout = -1 |
Timer used to detect unresolved invite (i.e. | |
boolean | monitorIfPeerIsSendingVoice = false |
Indicates whether to monitor if peer is sending voice PDUs to us. | |
JEditorPane | logArea |
The log area formatted in HTML. | |
JSecState | securityState |
JImageButton | sendButton |
JImageButton | listPeersButton |
JImageButton | dialButton |
JImageButton | secureDialButton |
JImageButton | hangupButton |
JLabel | imsgLabel |
JTextField | inputMsg |
JLabel | idLabel |
JTextField | userId |
JCheckBox | autoAnswer |
Static Private Attributes | |
static final long | serialVersionUID = -1830703904673318918L |
Implements java.io.Serializable interface. | |
static final String | appTitle = "IP1-10: Kryptofon" |
The common application title prefix. | |
static final String | defaultInputMsg = "<type in message, command or command arguments here>" |
The initial message content of the input text message field. | |
static final String | defaultLogAreaDumpFilename = "mykf-log-area-" |
The default file name where to dump log area contents with :dump command. |
The Swing based GUI front-end of the Kryptofon application that implements simple VoIP phone and chat client with encrypted peer-to-peer communication.
Definition at line 66 of file CryptoPhoneApp.java.
CryptoPhoneApp.CryptoPhoneApp | ( | String | args[] ) |
Creates a new instance of the CryptoPhoneApp
.
args | the command line arguments passed to main |
Definition at line 195 of file CryptoPhoneApp.java.
References appTitle, autoAnswer, clearLogArea(), createEventListeners(), createLayout(), defaultInputMsg, dialButton, displayUsage(), getUserId(), hangupButton, idLabel, imsgLabel, crypto.CipherEngine.initialize(), inputMsg, listPeersButton, ui.JImageButton.loadIcon(), logArea, mainTimer, pbxChannel, secureDialButton, securityState, sendButton, serverName, serverPort, pbx.PBXClient.start(), startKryptofonServices(), and userId.
Referenced by main().
{ super( appTitle ); setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ); //////////////////////////////////////////////////////// Create GUI elements ///// /* Fonts and colors */ Font textFont = new Font( Font.SANS_SERIF, Font.PLAIN, 14 ); UIManager.put( "ToolTip.background", new ColorUIResource( 0xFF, 0xFF, 0xC7 ) ); /* Application icons */ List<Image> icons = new LinkedList<Image> (); icons.add( JImageButton.loadIcon( this, "favicon48.png" ).getImage () ); icons.add( JImageButton.loadIcon( this, "favicon24.png" ).getImage () ); icons.add( JImageButton.loadIcon( this, "favicon16.png" ).getImage () ); setIconImages( icons ); /* Components */ inputMsg = new JTextField( defaultInputMsg, 30 ); inputMsg.setFont( textFont ); inputMsg.selectAll (); inputMsg.setToolTipText( "<html><head></head><body><p>" + "Enter a text message or command here, then press <tt>Enter</tt><br/>" + "If you are going to use command buttons or command mnemonics,<br/>" + "then put command arguments here (or leave this field empty)." + "</p></body></html>" ); imsgLabel = new JLabel (); // without the text; holds only mnemonic for the field imsgLabel.setFont( textFont ); imsgLabel.setDisplayedMnemonic( KeyEvent.VK_I ); imsgLabel.setLabelFor( inputMsg ); securityState = new JSecState( this ); sendButton = new JImageButton( this, "Send message", "chat.png", "chat2.png" ); sendButton.setMnemonic( KeyEvent.VK_ENTER ); listPeersButton = new JImageButton( this, "List kryptofon users (Alt + L)", "listPeers.png", "listPeers2.png" ); listPeersButton.setMnemonic( KeyEvent.VK_L ); dialButton = new JImageButton( this, "Make a call (Alt+C)", "dial.png", "dial2.png" ); dialButton.setMnemonic( KeyEvent.VK_C ); secureDialButton = new JImageButton( this, "Make a secure call (Alt+S)", "secureDial.png", "secureDial2.png" ); secureDialButton.setMnemonic( KeyEvent.VK_S ); hangupButton = new JImageButton( this, "Clear or reject the call (Alt+H)", "hangup.png", "hangup2.png" ); hangupButton.setMnemonic( KeyEvent.VK_H ); userId = new JTextField (); userId.setFont( textFont ); userId.setText( getUserId () ); // set default user id userId.setToolTipText( "<html><head></head><body><p>" + "Enter name, which will be used to identify you to other kryptofon peers.<br/>" + "The name should be unique and possibly without whitespaces." + "</p></body></html>" ); idLabel = new JLabel( "My Name:" ); idLabel.setFont( textFont ); idLabel.setDisplayedMnemonic( KeyEvent.VK_N ); idLabel.setLabelFor( userId ); autoAnswer = new JCheckBox( "Autoanswer" ); autoAnswer.setMnemonic( KeyEvent.VK_A ); autoAnswer.setToolTipText( "Toggle auto-answer mode (Alt+A)" ); logArea = new JEditorPane (); logArea.setFont( textFont ); logArea.setEditable( false ); logArea.setToolTipText( "<html><head></head><body><p>" + "<strong>Log Area</strong><br/>" + "Use <tt>:dump</tt> command to save contents into a file" + "</p></body></html>" ); clearLogArea (); //////////////////////////////////////////////////////// GUI Layout ////////////// createLayout (); /* Set inputMsg field ready for user to type in something... */ inputMsg.requestFocus (); //////////////////////////////////////////////////////// Event listeners ///////// createEventListeners (); //////////////////////////////////////////////////////// Window Size ///////////// /* Adjust window dimensions not to exceed screen dimensions ... */ Dimension win = new Dimension( 1024, 600 ); Dimension scsz = Toolkit.getDefaultToolkit().getScreenSize(); win.width = Math.min( win.width, scsz.width ); win.height = Math.min( win.height, scsz.height - 40 ); setSize( win ); setMinimumSize( new Dimension( 600, 400 ) ); /* ... then center window on the screen. */ setLocation( ( scsz.width - win.width )/2, ( scsz.height - 40 - win.height )/2 ); //////////////////////////////////////////////////////// Enable Logging ////////// /* Enable Log */ Log.setEnabled( Log.ALL , false ); Log.setEnabled( Log.VERB , false ); Log.setEnabled( Log.PDU , false ); Log.setEnabled( Log.AUDIO , false ); Log.setEnabled( Log.DEBUG , false ); Log.setEnabled( Log.ATTN , true ); Log.setEnabled( Log.TRACE , true ); Log.setEnabled( Log.INFO , true ); Log.setEnabled( Log.WARN , true ); Log.setEnabled( Log.ERROR , true ); Log.attn = this; // catch messages in 'attention' channel /* Display initial contents in the log area */ displayUsage (); //////////////////////////////////////////////////////// Start services ////////// /* Parse arguments: [ <host> [ <port> ] ] */ if ( args.length >= 1 ) { serverName = args[ 0 ]; if( args.length >= 2 ) try { serverPort = Integer.parseInt( args[ 1 ] ); } catch ( NumberFormatException e ) { Log.warn( "Using the default destination TCP port: " + serverPort ); } } /* Load authorized public keys and initializes asymmetric and symmetric * ciphering engines */ CipherEngine.initialize (); /* Start UDP listener and audio interface... */ startKryptofonServices (); /* Open communication link to server... */ pbxChannel = new PBXClient( serverName, serverPort, this ); pbxChannel.start (); /* Instantiate connection monitor timer (for reconnect supervision) */ mainTimer = new Timer( 1000, this ); mainTimer.start (); Log.trace( "Created instance of the " + this.getClass().toString () ); }
void CryptoPhoneApp.acceptIncomingCall | ( | boolean | securedIfPossible ) | [private] |
Accepts incoming invite.
Procedure is called either automatically from deferredOnInvite() when the auto-answer is turned on, or manually by the user from :accept command).
It first verifies invitor's public key (signed by invitor's private key) against the public keys from authorized keys file.
It then signs local secret key with the local private key, then encrypts signed secret key with our with verified invitor's public key and serializes it as Base64 string.
It sends ACCEPTING message to the peer with the information how to rich us (local IP address and UDP port as well serialized encrypted secret key) and signed/encrypted/encoded secret key.
At the end it creates instance for the call (CallContext class) and the remote peer (RemotePeer class), and binds them to specific CODEC of the audio interface and UDP channel.
The call is finally established at this point.
Definition at line 1857 of file CryptoPhoneApp.java.
References protocol.VoicePDU.ALAW, appTitle, audioInterface, crypto.PublicEncryptor.encryptAndSerialize(), audio.AudioInterface.getByFormat(), crypto.CipherEngine.getCipher(), pbx.PBXClient.getLocalAddress(), protocol.DatagramChannel.getLocalPort(), crypto.CipherEngine.getSignedSecretKey(), protocol.DatagramChannel.hasRemotePeer(), crypto.PublicEncryptor.isActive(), crypto.PublicEncryptor.isVerified(), lastMessageFromPBX, monitorIfPeerIsSendingVoice, pbxChannel, remotePublicKey, report(), securityState, pbx.PBXClient.sendAccept(), protocol.CallContext.setCallEstablished(), ui.JSecState.setState(), tryToVerifyInvitingCall(), udpChannel, and protocol.DatagramChannel.useSymmetricCipher().
Referenced by deferredOnInvite(), dialButton_Clicked(), executeCommand(), and secureDialButton_Clicked().
{ if ( this.lastMessageFromPBX == null ) { // There is no INVITE to accept return; } PBXClient.ControlMessage m = this.lastMessageFromPBX; String verboseRemote = m.getVerboseRemote (); /* Can accept only if there is no call in progress. */ if ( udpChannel.hasRemotePeer () ) { return; } /* Resolve peers IP address */ InetAddress peerAddr = null; try { peerAddr = InetAddress.getByName( m.peerAddr ); } catch( UnknownHostException e ) { Log.exception( Log.ERROR, e ); this.lastMessageFromPBX = null; report( "logError", "Unknown remote host '" + m.peerAddr + "'; clearing the call..." ); return; } /* Deserialize remote public key and encrypt our secret key with it. * Deserialization also verifies the public key against authorized keys. * \see constructor of the PublicEncryptor */ String mySecret = null; remotePublicKey = null; udpChannel.useSymmetricCipher( null ); if ( securedIfPossible ) { remotePublicKey = tryToVerifyInvitingCall( /*silent*/ true ); if ( remotePublicKey != null && remotePublicKey.isActive () ) { mySecret = remotePublicKey.encryptAndSerialize( CipherEngine.getSignedSecretKey() ); udpChannel.useSymmetricCipher( CipherEngine.getCipher () ); } } /* Send accepting message to remote peer */ pbxChannel.sendAccept( m.peerUserId, pbxChannel.getLocalAddress (), udpChannel.getLocalPort (), mySecret ); /* Create necessary objects needed to establish the call: * instances of the RemotePeer and CallContext. */ RemotePeer remotePeer = new RemotePeer( this.udpChannel, m.peerUserId, peerAddr, m.peerPort ); AudioInterface codec = this.audioInterface.getByFormat( VoicePDU.ALAW ); CallContext call = new CallContext( remotePeer, codec ); call.setCallEstablished( true ); monitorIfPeerIsSendingVoice = true; /* Report what we've done. */ if ( remotePublicKey != null && remotePublicKey.isActive () ) { if ( ! remotePublicKey.isVerified () ) { securityState.setState( JSecState.State.UNVERIFIED ); } else { securityState.setState( JSecState.State.VERIFIED ); } report( "logOk", "***** Encrypted call established *****" ); setTitle( appTitle + "; Established ENCRYPTED call with " + verboseRemote ); } else { securityState.setState( JSecState.State.UNSECURED ); report( "logError", "***** Un-encrypted call established *****" ); setTitle( appTitle + "; Established PLAIN call with " + verboseRemote ); } this.lastMessageFromPBX = null; }
void CryptoPhoneApp.actionPerformed | ( | ActionEvent | ae ) |
Handles events from Swing timer and buttons.
Definition at line 703 of file CryptoPhoneApp.java.
References dialButton, dialButton_Clicked(), hangupButton, hangupButton_Clicked(), listPeersButton, listPeersButton_Clicked(), mainTimer, mainTimerEvent(), secureDialButton, secureDialButton_Clicked(), sendButton, and sendButton_Clicked().
{ if ( ae.getSource () == mainTimer ) { mainTimerEvent (); } else if ( ae.getSource () == sendButton ) { sendButton_Clicked (); } else if ( ae.getSource () == listPeersButton ) { listPeersButton_Clicked (); } else if ( ae.getSource () == dialButton ) { dialButton_Clicked (); } else if ( ae.getSource () == secureDialButton ) { secureDialButton_Clicked (); } else if ( ae.getSource () == hangupButton ) { hangupButton_Clicked (); } }
void CryptoPhoneApp.attention | ( | String | message ) |
Displays attention messages to the user from Log subsystem.
Definition at line 857 of file CryptoPhoneApp.java.
References report().
void CryptoPhoneApp.clearLogArea | ( | ) |
Clears log area (with the contents of the "empty" template)
Definition at line 2031 of file CryptoPhoneApp.java.
References getContentsFromResourceOrFile(), and logArea.
Referenced by CryptoPhoneApp(), and executeCommand().
{ logArea.setContentType( "text/html" ); StringBuffer sb = getContentsFromResourceOrFile( "resources/empty.html" ); if ( sb != null ) { logArea.setText( sb.toString () ); } else { logArea.setText( "<html><head></head><body></body></html>" ); } }
void CryptoPhoneApp.createEventListeners | ( | ) | [private] |
Creates event listeners.
Definition at line 478 of file CryptoPhoneApp.java.
References autoAnswer, dialButton, formWindowClosing(), getUserId(), hangupButton, inputMsg, listPeersButton, logArea, secureDialButton, sendButton, and userId.
Referenced by CryptoPhoneApp().
{ addWindowListener( new java.awt.event.WindowAdapter () { public void windowClosing( java.awt.event.WindowEvent evt ) { formWindowClosing( evt ); } } ); inputMsg.addKeyListener( this ); userId.addKeyListener( this ); autoAnswer.addKeyListener( this ); logArea.addKeyListener( this ); sendButton.addKeyListener( this ); listPeersButton.addKeyListener( this ); dialButton.addKeyListener( this ); secureDialButton.addKeyListener( this ); hangupButton.addKeyListener( this ); sendButton.addActionListener( this ); listPeersButton.addActionListener( this ); dialButton.addActionListener( this ); secureDialButton.addActionListener( this ); hangupButton.addActionListener( this ); inputMsg.addFocusListener( new FocusListener () { public void focusGained( FocusEvent evt ) { inputMsg.selectAll (); } public void focusLost( FocusEvent evt ) { } } ); userId.addFocusListener( new FocusListener () { public void focusGained( FocusEvent evt ) { userId.selectAll (); } public void focusLost( FocusEvent evt ) { synchronized( userId ) { userId.setText( getUserId () ); } } } ); }
void CryptoPhoneApp.createLayout | ( | ) | [private] |
Creates layout of the GUI components.
Definition at line 376 of file CryptoPhoneApp.java.
References dialButton, hangupButton, idLabel, imsgLabel, inputMsg, listPeersButton, logArea, secureDialButton, securityState, sendButton, and userId.
Referenced by CryptoPhoneApp().
{ /* Upper: status, inputMsg | buttons | idLabel, userId * Lower: scrolled logArea */ GroupLayout layout = new GroupLayout( getContentPane () ); getContentPane().setLayout( layout ); layout.setAutoCreateContainerGaps( true ); layout.setAutoCreateGaps( true ); JScrollPane logPane = new JScrollPane (); logPane.setViewportView( logArea ); JSeparator vertS1 = new JSeparator( JSeparator.VERTICAL ); JSeparator vertS2 = new JSeparator( JSeparator.VERTICAL ); int textH = 26; // fixed text field height int iconH = 32; // fixed icon height int iconW = 32; // fixed icon width layout.setHorizontalGroup ( layout .createParallelGroup( GroupLayout.Alignment.LEADING ) .addGroup ( layout .createSequentialGroup () .addGroup ( layout .createParallelGroup( GroupLayout.Alignment.LEADING ) .addGroup ( GroupLayout.Alignment.TRAILING, layout .createSequentialGroup () .addComponent( securityState ) .addGap( 5 ) .addComponent( imsgLabel ) .addGap( 0 ) .addComponent( inputMsg ) .addComponent( sendButton, iconW, iconW, iconW ) .addGap( 15 ) .addComponent( vertS1, 4, 4, 4 ) .addGap( 10 ) .addComponent( listPeersButton, iconW, iconW, iconW ) .addComponent( dialButton, iconW, iconW, iconW ) .addComponent( secureDialButton, iconW, iconW, iconW ) .addComponent( hangupButton, iconW, iconW, iconW ) .addGap( 15 ) // .addComponent( autoAnswer ) // .addGap( 10 ) .addComponent( vertS2, 4, 4, 4 ) .addGap( 10 ) .addComponent( idLabel ) .addGap( 5 ) .addComponent( userId ) ) .addComponent( logPane ) ) ) ); layout.setVerticalGroup ( layout .createParallelGroup( GroupLayout.Alignment.LEADING ) .addGroup ( layout .createSequentialGroup () .addGroup ( layout .createParallelGroup( GroupLayout.Alignment.CENTER ) .addComponent( securityState ) .addComponent( imsgLabel ) .addComponent( inputMsg, textH, textH, textH ) .addComponent( sendButton, iconH, iconH, iconH ) .addComponent( vertS1, iconH, iconH, iconH ) .addComponent( listPeersButton, iconH, iconH, iconH ) .addComponent( dialButton, iconH, iconH, iconH ) .addComponent( secureDialButton, iconH, iconH, iconH ) .addComponent( hangupButton, iconH, iconH, iconH ) .addComponent( vertS2, iconH, iconH, iconH ) .addComponent( idLabel ) .addComponent( userId, textH, textH, textH ) //.addComponent( autoAnswer ) ) .addComponent( logPane ) ) ); pack(); }
void CryptoPhoneApp.deferredOnAccept | ( | final PBXClient.ControlMessage | m ) |
On ACCEPT call-back is triggered when PBXClient receives accepting message (indicating that the peer has accepted our invite).
It deserializes encrypted secret key used for peer-to-peer communication (if any) and creates instance for the call (CallContext class) as well the remote peer (RemotePeer class), and binds them to specific CODEC (of the audio interface) and the UDP channel (for voice transmission).
The call is finally established at this point.
Definition at line 1624 of file CryptoPhoneApp.java.
References protocol.VoicePDU.ALAW, appTitle, audioInterface, currentInvite, crypto.CipherEngine.deserializeEncryptedSecretKey(), audio.AudioInterface.getByFormat(), crypto.SymmetricCipher.getVerificatorName(), protocol.DatagramChannel.hasRemotePeer(), inviteTimeout, crypto.SymmetricCipher.isActive(), crypto.SymmetricCipher.isVerified(), lastMessageFromPBX, monitorIfPeerIsSendingVoice, report(), securityState, protocol.CallContext.setCallEstablished(), ui.JSecState.setState(), udpChannel, and protocol.DatagramChannel.useSymmetricCipher().
Referenced by onAccept().
{ if ( m.peerPort < 1 || m.peerPort > 65535 ) { return; } String verboseRemote = m.getVerboseRemote (); /* Ignore message if we already have the call in progress. */ if ( udpChannel.hasRemotePeer () ) { return; } inviteTimeout = -1; currentInvite = null; /* Resolve peers IP address */ InetAddress peerAddr = null; try { peerAddr = InetAddress.getByName( m.peerAddr ); } catch( UnknownHostException e ) { Log.exception( Log.ERROR, e ); this.lastMessageFromPBX = null; report( "logError", "Unknown remote host '" + m.peerAddr + "'; clearing the call..." ); return; } report( "logInfo", "User " + verboseRemote + " has accepted our invite" ); /* Deserialize encrypted remote secret key and decrypt it with our private key */ SymmetricCipher cipher = null; udpChannel.useSymmetricCipher( null ); if ( m.secret != null ) { cipher = CipherEngine.deserializeEncryptedSecretKey( m.secret ); if ( cipher.isActive () ) { udpChannel.useSymmetricCipher( cipher ); } else { cipher = null; } } /* Create necessary objects needed to establish the call */ RemotePeer remotePeer = new RemotePeer( this.udpChannel, m.peerUserId, peerAddr, m.peerPort ); AudioInterface codec = this.audioInterface.getByFormat( VoicePDU.ALAW ); CallContext call = new CallContext( remotePeer, codec ); call.setCallEstablished( true ); monitorIfPeerIsSendingVoice = true; if ( cipher != null && cipher.isActive () ) { if ( ! cipher.isVerified () ) { securityState.setState( JSecState.State.UNVERIFIED ); report( "logError", "Secret key from " + verboseRemote + " could not be authenticated." ); } else { securityState.setState( JSecState.State.VERIFIED ); report( "logOk", "Secret key from " + verboseRemote + " authenticated with public key '" + cipher.getVerificatorName () + "'" ); } report( "logOk", "***** Encrypted call established *****" ); setTitle( appTitle + "; Established ENCRYPTED call with " + verboseRemote ); } else { securityState.setState( JSecState.State.UNSECURED ); report( "logError", "***** Un-encrypted call established *****" ); setTitle( appTitle + "; Established PLAIN call with " + verboseRemote ); } }
void CryptoPhoneApp.deferredOnBye | ( | final PBXClient.ControlMessage | m ) |
On BYE call-back is triggered when PBXClient receives 'bye' message (indicating that the peer is clearing i.e.
hanging-up the call).
Definition at line 1714 of file CryptoPhoneApp.java.
References audioInterface, currentInvite, protocol.DatagramChannel.hasRemotePeer(), inviteTimeout, lastMessageFromPBX, logMessage(), pbxChannelStatus, remotePublicKey, protocol.DatagramChannel.removePeer(), report(), securityState, ui.JSecState.setState(), audio.AudioInterface.stopRinging(), udpChannel, and userId.
Referenced by onBye().
{ String verboseRemote = m.getVerboseRemote (); /* If we do not have a call, than remote has rejected our earlier invite */ if ( ! udpChannel.hasRemotePeer () && currentInvite != null ) { report( "logInfo", "User " + verboseRemote + " rejected our invite" ); } else /* otheresie, it is a hang-up of the existing call */ { report( "logInfo", "User " + verboseRemote + " is clearing the call" ); udpChannel.removePeer (); } audioInterface.stopRinging (); userId.setEnabled( true ); // enable back changing user ID lastMessageFromPBX = null; remotePublicKey = null; report( "logInfo", "***** Call Ended *****" ); logMessage( "<hr/>" ); securityState.setState( JSecState.State.UNSECURED ); setTitle( pbxChannelStatus ); inviteTimeout = -1; currentInvite = null; }
void CryptoPhoneApp.deferredOnInstantMessage | ( | final PBXClient.ControlMessage | m ) |
On IMSG call-back is triggered when PBXClient receives private instant message (encrypted with session's secret key).
Definition at line 1750 of file CryptoPhoneApp.java.
References crypto.SymmetricCipher.decrypt(), protocol.DatagramChannel.getUsedSymmetricCipher(), reportIncomingTextMessage(), and udpChannel.
Referenced by onInstantMessage().
{ /* Get symmetric ciphering engine for PDUs and messages (if any). */ SymmetricCipher cipher = udpChannel.getUsedSymmetricCipher (); if ( cipher == null ) { return; } /* Decrypt instant message and display highlighted contents to the user */ String clearText = cipher.decrypt( m.secret ); if ( clearText != null ) { /* */ reportIncomingTextMessage( "secureMessage", m.peerUserId + " [encrypted]", clearText ); } }
void CryptoPhoneApp.deferredOnInvite | ( | final PBXClient.ControlMessage | m ) |
On INVITE call-back is triggered when PBXClient receives inviting message (indicating that someone is calling us).
It starts ringing and if the application is in auto-answer mode, it accepts incoming call immediately. Otherwise it presents alerting message to the user with information about who's calling.
Definition at line 1501 of file CryptoPhoneApp.java.
References acceptIncomingCall(), appTitle, audioInterface, autoAnswer, pbx.PBXClient.getLocalAddress(), protocol.DatagramChannel.getLocalPort(), crypto.CipherEngine.getSignedPublicKey(), protocol.DatagramChannel.hasRemotePeer(), lastMessageFromPBX, logMessage(), pbxChannel, report(), pbx.PBXClient.sendBye(), pbx.PBXClient.sendRing(), audio.AudioInterface.startRinging(), tryToVerifyInvitingCall(), udpChannel, and userId.
Referenced by onInvite().
{ if ( m.peerPort < 1 || m.peerPort > 65535 ) { return; } String verboseRemote = m.getVerboseRemote (); /* Reject new calls if we already have the call in progress */ if ( udpChannel.hasRemotePeer () ) { /* Send 'bye' message to remote peer who is inviting us */ pbxChannel.sendBye( m.peerUserId, "0.0.0.0", 0 ); return; } this.lastMessageFromPBX = m; logMessage( "<hr/>" ); report( "logInfo", "User " + verboseRemote + " is inviting us..." ); if ( m.secret == null ) { setTitle( appTitle + "; Incoming PLAIN call from " + verboseRemote ); } else { setTitle( appTitle + "; Incoming ENCRYPTED call from " + verboseRemote ); } this.audioInterface.startRinging (); userId.setEnabled( false ); // disable changing user ID if ( autoAnswer.isSelected () ) { report( "logInfo", "Auto-answering the call..." ); acceptIncomingCall( /*secured*/ true ); } else { tryToVerifyInvitingCall( /*silent*/ false ); report( "logInfo", "Respond with :accept to answer the call!" ); /* Send 'ringing' message to remote peer with our public key */ pbxChannel.sendRing( m.peerUserId, pbxChannel.getLocalAddress (), udpChannel.getLocalPort (), CipherEngine.getSignedPublicKey () ); } }
void CryptoPhoneApp.deferredOnRing | ( | final PBXClient.ControlMessage | m ) |
On RING call-back is triggered when PBXClient receives ringing message (indicating that the peer is alerting end-user).
Definition at line 1554 of file CryptoPhoneApp.java.
References audioInterface, currentInvite, crypto.PublicEncryptor.getVerificatorName(), protocol.DatagramChannel.hasRemotePeer(), inviteTimeout, crypto.PublicEncryptor.isActive(), crypto.PublicEncryptor.isVerified(), remotePublicKey, report(), audio.AudioInterface.startRinging(), udpChannel, and userId.
Referenced by onRing().
{ if ( m.peerPort < 1 || m.peerPort > 65535 ) { return; } String verboseRemote = m.getVerboseRemote (); /* Ignore the message if we already have the call in progress. */ if ( udpChannel.hasRemotePeer () ) { return; } /* Ignore the message if the remote peer is not that we are inviting to a call */ if ( currentInvite == null || ! currentInvite.equalsIgnoreCase( m.peerUserId ) ) { return; } /* Deserialize remote public key. * Deserialization also verifies the public key against authorized keys. * \see constructor of the PublicEncryptor */ remotePublicKey = null; if ( m.secret != null ) { remotePublicKey = new PublicEncryptor( m.secret, m.peerUserId ); if ( ! remotePublicKey.isActive () ) { remotePublicKey = null; } } /* Cancel inviteTimeout timer and give information and ringing tone to our user */ report( "logInfo", "User " + verboseRemote + " is alerted..." ); if ( remotePublicKey != null && remotePublicKey.isActive () ) { if ( ! remotePublicKey.isVerified () ) { report( "logError", "Reply from " + verboseRemote + " could not be authenticated." ); } else { report( "logOk", "Reply from " + verboseRemote + " authenticated with public key '" + remotePublicKey.getVerificatorName () + "'" ); } } inviteTimeout = -1; // Reset only invite timeout (do not reset currentInvite) this.audioInterface.startRinging (); userId.setEnabled( false ); // disable changing user ID }
void CryptoPhoneApp.dialButton_Clicked | ( | ) | [private] |
Performs :invite command.
Definition at line 609 of file CryptoPhoneApp.java.
References acceptIncomingCall(), executeCommand(), lastMessageFromPBX, and tokenizeInputMessage().
Referenced by actionPerformed().
{ /* If there is outstanding INVITE waiting to be accepted, * do accept incoming call instead of making new outgoing call. */ if ( this.lastMessageFromPBX == null ) { executeCommand( ":invite", tokenizeInputMessage () ); } else { acceptIncomingCall( /*secured*/ false ); } }
void CryptoPhoneApp.displayHelp | ( | ) |
Displays help.
Definition at line 2057 of file CryptoPhoneApp.java.
References getContentsFromResourceOrFile(), and logMessage().
Referenced by executeCommand().
{ StringBuffer sb = getContentsFromResourceOrFile( "resources/help.html" ); if ( sb != null && sb.length () > 0 ) { logMessage( sb.toString () ); } }
void CryptoPhoneApp.displayUsage | ( | ) |
Displays usage information.
Definition at line 2045 of file CryptoPhoneApp.java.
References getContentsFromResourceOrFile(), and logMessage().
Referenced by CryptoPhoneApp(), and executeCommand().
{ StringBuffer sb = getContentsFromResourceOrFile( "resources/usage.html" ); if ( sb != null && sb.length () > 0 ) { logMessage( sb.toString () ); } }
void CryptoPhoneApp.dumpLogArea | ( | String | fileName ) |
Dumps log area into html file.
Definition at line 1950 of file CryptoPhoneApp.java.
References defaultLogAreaDumpFilename, logArea, and report().
Referenced by executeCommand().
{ if ( fileName == null || fileName.isEmpty () ) { Calendar cal = Calendar.getInstance (); SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd-HHmmssSSS" ); fileName = defaultLogAreaDumpFilename + sdf.format( cal.getTime () ) + ".html"; } try { BufferedWriter out = new BufferedWriter( new FileWriter( fileName ) ); synchronized( logArea ) { out.write( logArea.getText () ); } out.close (); report( "logInfo", "Dumped log area into '" + fileName + "'" ); } catch( IOException e ) { report( "logError", "Failed to dump log area: " + e.getMessage () ); } }
boolean CryptoPhoneApp.executeCommand | ( | String | cmd, |
String[] | args | ||
) | [private] |
Parses commands prefixed with ':' character.
Recognized commands are:
VoIP Calls:
:inv[ite] username aliases: :ca[ll] :inv[ite]+ username aliases: :ca[ll]+ :acc[ept] aliases: :ans[wer] :by[e] aliases: :ha[ngup] :shk[ey]
VoIP Peers:
:li[st] [ username-regex ]
Chat Messages:
:br[oadcast] message
Connection to Chat Server:
:clo[se] :op[en] [ host [ port ] ]
Application: :cl[ear]s[creen] :reauth :newsecret [ algorithm [ keysize ] ] :du[mp] :ex[it] aliases: :qu[it] :he[lp]
cmd | command name; must begin with ":" |
args | command arguments; may be null or empty array |
Definition at line 1188 of file CryptoPhoneApp.java.
References acceptIncomingCall(), audioInterface, clearLogArea(), pbx.PBXClient.close(), currentInvite, displayHelp(), displayUsage(), dumpLogArea(), crypto.CipherEngine.generateNewSecret(), pbx.PBXClient.getLocalAddress(), protocol.DatagramChannel.getLocalPort(), crypto.CipherEngine.getNamedPublicKey(), protocol.DatagramChannel.getRemotePeer(), protocol.RemotePeer.getRemoteUserId(), crypto.CipherEngine.getSignedPublicKey(), protocol.DatagramChannel.hasRemotePeer(), inviteTimeout, lastMessageFromPBX, logMessage(), pbxChannel, pbxChannelStatus, reconnectRetryCount, crypto.CipherEngine.reloadAuthorizedPublicKeys(), remotePublicKey, protocol.DatagramChannel.removePeer(), report(), securityState, pbx.PBXClient.send(), pbx.PBXClient.sendBye(), sendInstantMessage(), pbx.PBXClient.sendInvite(), pbx.PBXClient.sendListPeers(), serverName, serverPort, ui.JSecState.setState(), pbx.PBXClient.start(), stopKryptofonServices(), audio.AudioInterface.stopRinging(), udpChannel, and userId.
Referenced by dialButton_Clicked(), hangupButton_Clicked(), keyPressed(), listPeersButton_Clicked(), parseInputMessage(), secureDialButton_Clicked(), and stopKryptofonServices().
{ cmd = cmd.trim().toLowerCase(); boolean executed = false; if ( args == null ) { args = new String[0]; } /* Note bellow that we use both equals() and matches() to resolve command. * We need equals() to speed-up lookup for those commands that are executed * internally by directly calling executeCommand() with hard-coded argument * (contrary to when executeCommand() is called with commnands entered by * the user). */ /*------------------------------------------------------------------------------*/ if ( cmd.equals( ":list" ) || cmd.matches( "^:li(st?)?$" ) ) { pbxChannel.sendListPeers( args.length >= 1 ? args[0] : null ); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":who" ) ) { pbxChannel.send( "wwhhoo" ); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":bye" ) || cmd.matches( "^:by(e)?$" ) || cmd.matches( "^:ha(n(g(up?)?)?)?$" ) ) { RemotePeer remotePeer = udpChannel.getRemotePeer (); if ( remotePeer != null ) { report( "logInfo", "***** Call Ended *****" ); logMessage( "<hr/>" ); /* Send 'bye' message to remote peer */ pbxChannel.sendBye( remotePeer.getRemoteUserId (), pbxChannel.getLocalAddress (), udpChannel.getLocalPort () ); } else if ( currentInvite != null ) { report( "logInfo", "Invite cancelled." ); logMessage( "<hr/>" ); /* Send 'bye' message to remote peer */ pbxChannel.sendBye( currentInvite, pbxChannel.getLocalAddress (), udpChannel.getLocalPort () ); } else if ( this.lastMessageFromPBX != null ) // call waiting to be accepted { PBXClient.ControlMessage m = this.lastMessageFromPBX; String verboseRemote = m.getVerboseRemote (); report( "logInfo", "Rejecting invite from " + verboseRemote ); logMessage( "<hr/>" ); /* Send 'bye' message to remote peer */ pbxChannel.sendBye( m.peerUserId, pbxChannel.getLocalAddress (), udpChannel.getLocalPort () ); this.lastMessageFromPBX = null; } udpChannel.removePeer (); audioInterface.stopRinging (); userId.setEnabled( true ); // enable back changing user ID lastMessageFromPBX = null; remotePublicKey = null; securityState.setState( JSecState.State.UNSECURED ); setTitle( pbxChannelStatus ); inviteTimeout = -1; currentInvite = null; executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":invite+" ) || cmd.matches( "^:inv(i(te?)?)?\\+$" ) || cmd.matches( "^:ca(ll?)?\\+$" ) ) { /* Calls another user WITH encryption enabled */ if ( udpChannel.hasRemotePeer () || currentInvite != null ) { report( "logError", "Call in progress. Hang up first!" ); executed = true; } else if ( args.length >= 1 && pbxChannel.isAlive () ) { logMessage( "<hr/>" ); report( "logInfo", "Inviting '" + args[0] + "' to encrypted voice call..." ); currentInvite = args[0]; inviteTimeout = 3; userId.setEnabled( false ); // disable changing user ID pbxChannel.sendInvite( currentInvite, pbxChannel.getLocalAddress (), udpChannel.getLocalPort (), CipherEngine.getSignedPublicKey () ); executed = true; } } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":invite" ) || cmd.matches( "^:inv(i(te?)?)?$" ) || cmd.matches( "^:ca(ll?)?$" ) ) { /* Calls another user WITHOUT encryption enabled */ if ( udpChannel.hasRemotePeer () || currentInvite != null ) { report( "logError", "Call in progress. Hang up first!" ); executed = true; } else if ( args.length >= 1 && pbxChannel.isAlive () ) { logMessage( "<hr/>" ); report( "logInfo", "Inviting '" + args[0] + "' to un-encrypted voice call..." ); currentInvite = args[0]; inviteTimeout = 3; userId.setEnabled( false ); // disable changing user ID pbxChannel.sendInvite( args[0], pbxChannel.getLocalAddress (), udpChannel.getLocalPort (), null ); executed = true; } } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":accept" ) || cmd.matches( "^:acc(e(pt?)?)?$" ) || cmd.matches( "^:ans(w(er?)?)?$" ) ) { acceptIncomingCall( /*secured*/ true ); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":broadcast" ) || cmd.matches( "^:br(o(a(d(c(a(st?)?)?)?)?)?)?$" ) ) { if ( args.length >= 1 ) { StringBuffer msg = new StringBuffer (); for ( String s : args ) { if ( msg.length () > 0 ) { msg.append( " " ); } msg.append( s ); } sendInstantMessage( msg.toString () , /*forceUnencrypted*/ true ); executed = true; } } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":mykey" ) || cmd.matches( "^:my(k(ey?)?)?$" ) ) { sendInstantMessage( "\f========= BEGIN PUBLIC KEY =========\f\f" + CipherEngine.getNamedPublicKey () + "\f\f========= END PUBLIC KEY ===========" , /*forceUnencrypted*/ false ); } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":close" ) || cmd.matches( "^:clo(se?)?$" ) ) { logMessage( "<hr/>" ); reconnectRetryCount = Integer.MAX_VALUE; // suppresses reconnection pbxChannel.close (); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":open" ) || cmd.matches( "^:op(en?)?$" ) ) { /* Opens new connection to chat server */ if ( args.length >= 1 ) { /* Parse arguments first: host name and port */ serverName = args[0]; serverPort = 2000; // the default port if( args.length >= 2 ) try { serverPort = Integer.parseInt( args[1] ); } catch ( NumberFormatException e ) { report( "logError", "The port must be integer." ); return false; } } logMessage( "<hr/>" ); reconnectRetryCount = Integer.MAX_VALUE; // suppresses reconnection pbxChannel.close (); pbxChannel = new PBXClient( serverName, serverPort , this ); pbxChannel.start (); reconnectRetryCount = 0; executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":exit" ) || cmd.matches( "^:ex(it?)?$" ) || cmd.matches( "^:qu(it?)?$" ) ) { stopKryptofonServices (); pbxChannel.close (); System.exit( 0 ); } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":reauth" ) ) { CipherEngine.reloadAuthorizedPublicKeys (); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":newsecret" ) ) { String algorithm = "Blowfish"; int keySize = 32; if ( args.length >= 1 ) { algorithm = args[0]; } if ( args.length >= 2 ) { try { keySize = Integer.parseInt( args[1] ); } catch ( NumberFormatException e ) { report( "logError", "The key size must be integer." ); return false; } } if ( ! CipherEngine.generateNewSecret( algorithm, keySize, /*verbose*/true ) ) { /* fail back to blowfish (not to leave user without symmetric cipher) */ CipherEngine.generateNewSecret( "Blowfish", 32, /*verbose*/false ); return false; } executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":cls" ) || cmd.matches( "^:cl(ear)?s(c(r(e(en?)?)?)?)?$" ) ) { clearLogArea (); // clears screen displayUsage (); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":help" ) || cmd.matches( "^:he(lp?)?$" ) ) { displayHelp (); executed = true; } /*------------------------------------------------------------------------------*/ else if ( cmd.equals( ":dump" ) || cmd.matches( "^:du(mp?)?$" ) ) { dumpLogArea( args.length >= 1 ? args[0] : null ); executed = true; } /*------------------------------------------------------------------------------*/ return executed; }
void CryptoPhoneApp.formWindowClosing | ( | WindowEvent | evt ) | [private] |
Closes application by gracefully terminating all threads.
Definition at line 647 of file CryptoPhoneApp.java.
References pbx.PBXClient.close(), pbxChannel, and stopKryptofonServices().
Referenced by createEventListeners(), and parseInputMessage().
{ stopKryptofonServices (); if ( pbxChannel != null ) { pbxChannel.close (); } System.exit( 0 ); }
StringBuffer CryptoPhoneApp.getContentsFromResourceOrFile | ( | String | path ) |
Reads contents of the text file using URL class.
Definition at line 1982 of file CryptoPhoneApp.java.
Referenced by clearLogArea(), displayHelp(), and displayUsage().
{ StringBuffer sb = new StringBuffer (); try { /* First, try to read resource from JAR */ URL url = getClass().getResource( path ); /* Then fail to local file */ if ( url == null ) { url = new URL( "file:" + path ); } /* Append contents of the file to string buffer */ if ( url != null ) { InputStream in = url.openStream (); BufferedReader dis = new BufferedReader( new InputStreamReader( in ) ); String line; while ( ( line = dis.readLine () ) != null ) { sb.append( line + "\n" ); } in.close (); } } catch( MalformedURLException e ) { Log.exception( Log.TRACE, e ); sb = null; } catch( IOException e ) { Log.exception( Log.TRACE, e ); sb = null; } return sb; }
String CryptoPhoneApp.getUserId | ( | ) |
Returns configured user ID (username).
Definition at line 872 of file CryptoPhoneApp.java.
References userId.
Referenced by createEventListeners(), CryptoPhoneApp(), parseInputMessage(), sendInstantMessage(), and startKryptofonServices().
{ String newId = null; synchronized( userId ) { String oldId = userId.getText ().trim(); /* Default user id, if not specified */ if ( oldId.isEmpty () ) { oldId = System.getProperty( "user.name" ); } /* Ouch. Again empty. Then we are really an anonymous */ if ( oldId.isEmpty () ) { oldId = "[Anonymous]"; } /* Discard spaces from the local userId */ newId = oldId.replaceAll( "\\s{1,}", "-" ); } return newId; }
void CryptoPhoneApp.hangupButton_Clicked | ( | ) | [private] |
Performs :bye command.
Definition at line 639 of file CryptoPhoneApp.java.
References executeCommand(), and tokenizeInputMessage().
Referenced by actionPerformed().
{ executeCommand( ":bye", tokenizeInputMessage () ); }
void CryptoPhoneApp.keyPressed | ( | KeyEvent | ke ) |
Implements KeyListener
's key pressed event.
Parses input message on ENTER (the same action as it was sendButton_Clicked).
Definition at line 662 of file CryptoPhoneApp.java.
References defaultInputMsg, executeCommand(), inputMsg, parseInputMessage(), and userId.
{ int keyCode = ke.getKeyCode (); if( ke.getSource () == inputMsg && keyCode == KeyEvent.VK_ENTER ) { if ( defaultInputMsg.equalsIgnoreCase( inputMsg.getText () ) ) { return; // ignore default input message } parseInputMessage (); } else if( ke.getSource () == userId && keyCode == KeyEvent.VK_ENTER ) { inputMsg.requestFocus (); } else if( keyCode == KeyEvent.VK_F1 ) { executeCommand( ":help", null ); } }
void CryptoPhoneApp.keyReleased | ( | KeyEvent | ke ) |
Implements KeyListener
's key released event.
Definition at line 687 of file CryptoPhoneApp.java.
{
/* unused */
}
void CryptoPhoneApp.keyTyped | ( | KeyEvent | ke ) |
Implements KeyListener
's key typed event.
Definition at line 695 of file CryptoPhoneApp.java.
{
/* unused */
}
void CryptoPhoneApp.listPeersButton_Clicked | ( | ) | [private] |
Performs :list command.
Definition at line 601 of file CryptoPhoneApp.java.
References executeCommand().
Referenced by actionPerformed().
{ executeCommand( ":list", null ); }
void CryptoPhoneApp.logMessage | ( | final String | str ) |
Logs message formated with limited HTML (limited because of JEditorPane)
Definition at line 833 of file CryptoPhoneApp.java.
References logArea.
Referenced by deferredOnBye(), deferredOnInvite(), displayHelp(), displayUsage(), executeCommand(), mainTimerEvent(), report(), and reportIncomingTextMessage().
static void CryptoPhoneApp.main | ( | final String | args[] ) | [static] |
Main entry point.
Creates GUI instance of the CryptoPhoneApp application.
args | the command line arguments |
Definition at line 2072 of file CryptoPhoneApp.java.
References CryptoPhoneApp().
{ // System.getProperties().list( System.out ); java.awt.EventQueue.invokeLater( new Runnable() { public void run() { new CryptoPhoneApp( args ).setVisible( true ); } } ); }
void CryptoPhoneApp.mainTimerEvent | ( | ) | [private] |
Handles events from application's mainTimer (an instance of the Swing timer).
It monitors status of:
If PBXClient connection is detected to be down, the procedure will try to reconnect to chat server after some period of time. If reconnection retry count exceeded maximum, timer will stop retrying.
In case of dead remote peer (not sending UDP packets to us), udpChannel.isPearDead() timer will clear down the call.
In case of unacknowledged invite message, inviteTimeout timer will cancel current inviting.
Definition at line 738 of file CryptoPhoneApp.java.
References currentInvite, protocol.DatagramChannel.getRemotePeer(), protocol.RemotePeer.getRemoteUserId(), inviteTimeout, protocol.DatagramChannel.isPearDead(), logMessage(), monitorIfPeerIsSendingVoice, pbxChannel, reconnectRetryCount, reconnectTimeout, report(), serverName, serverPort, setPbxStatus(), pbx.PBXClient.start(), and udpChannel.
Referenced by actionPerformed().
{ ////////////////////////////////////////////////////////////////////////////////// /* Monitor remote peer's status */ RemotePeer peer = udpChannel.getRemotePeer(); if ( monitorIfPeerIsSendingVoice && peer != null && udpChannel.isPearDead( /*timeout-millis*/ 2500 ) ) { monitorIfPeerIsSendingVoice = false; report( "logWarn", "Warning: Not receiving voice from '" + peer.getRemoteUserId () + "'; Maybe it's dead?" ); } ////////////////////////////////////////////////////////////////////////////////// /* Monitor the last issued invite */ if ( inviteTimeout >= 0 ) // invite timeout is active { if ( --inviteTimeout < 0 ) // invite timeout reached { report( "logError", "It seems that kryptofon user '" + currentInvite + "' is not connected." ); report( "logInfo", "Use :list to query available users..." ); logMessage( "<hr/>" ); inviteTimeout = -1; currentInvite = null; } } ////////////////////////////////////////////////////////////////////////////////// /* Monitor current connection. */ final int maxRetryCount = 3; final int reconnectDelay = 2; if ( pbxChannel != null && pbxChannel.isAlive () ) { reconnectTimeout = -1; // disables timer return; } if ( reconnectRetryCount >= maxRetryCount ) { if ( reconnectRetryCount == maxRetryCount ) { ++reconnectRetryCount; logMessage( "<hr/><div class='logDiv'>" + "<span class='logError'>Press ENTER to quit or type<br/><br/>" + " :open [ <hostname> [ <port> ] ]<br/><br/>" + "to open new connection...</span><br/><br/></div>" ); setPbxStatus( "Dead" ); /* Reset defaults */ serverName = "atlas.dsv.su.se"; serverPort = 9494; } return; // Leave to the user to quit by pressing ENTER } if ( reconnectTimeout < 0 ) { setPbxStatus( "Disconnected" ); logMessage( "<hr/><div class='logDiv'>Reconnecting in " + reconnectDelay + " seconds...</div>" ); reconnectTimeout = reconnectDelay; // start timer return; } if ( --reconnectTimeout > 0 ) { return; } logMessage( "<div class='logDiv'>Retry #" + ( ++reconnectRetryCount ) + " of max " + maxRetryCount + ":<br/></div>" ); reconnectTimeout = -1; // disables timer and restarts new connection pbxChannel = new PBXClient( serverName, serverPort , this ); pbxChannel.start (); }
void CryptoPhoneApp.onAccept | ( | final PBXClient.ControlMessage | m ) |
Handles on ACCEPT call-back from the PBXClient.
Definition at line 983 of file CryptoPhoneApp.java.
References deferredOnAccept().
{ java.awt.EventQueue.invokeLater( new Runnable() { public void run() { deferredOnAccept( m ); } } ); }
void CryptoPhoneApp.onBye | ( | final PBXClient.ControlMessage | m ) |
Handles on BYE call-back from the PBXClient.
Definition at line 998 of file CryptoPhoneApp.java.
References deferredOnBye().
{ java.awt.EventQueue.invokeLater( new Runnable() { public void run() { deferredOnBye( m ); } } ); }
void CryptoPhoneApp.onInstantMessage | ( | final PBXClient.ControlMessage | m ) |
Handles on IMSG call-back from the PBXClient.
Definition at line 1013 of file CryptoPhoneApp.java.
References deferredOnInstantMessage().
{ java.awt.EventQueue.invokeLater( new Runnable() { public void run() { deferredOnInstantMessage( m ); } } ); }
void CryptoPhoneApp.onInvite | ( | final PBXClient.ControlMessage | m ) |
Handles on INVITE call-back from the PBXClient.
Definition at line 953 of file CryptoPhoneApp.java.
References deferredOnInvite().
{ java.awt.EventQueue.invokeLater( new Runnable() { public void run() { deferredOnInvite( m ); } } ); }
void CryptoPhoneApp.onRing | ( | final PBXClient.ControlMessage | m ) |
Handles on RING call-back from the PBXClient.
Definition at line 968 of file CryptoPhoneApp.java.
References deferredOnRing().
{ java.awt.EventQueue.invokeLater( new Runnable() { public void run() { deferredOnRing( m ); } } ); }
void CryptoPhoneApp.parseInputMessage | ( | ) | [private] |
Parses input message from inputMsg and sends it to chat server.
If it is a command (the first word is prefixed with ':' character) it spawns executeCommand() for further parsing.
Definition at line 1054 of file CryptoPhoneApp.java.
References defaultInputMsg, executeCommand(), formWindowClosing(), getUserId(), inputMsg, pbxChannel, pbx.PBXClient.send(), sendInstantMessage(), and tokenizeInputMessage().
Referenced by keyPressed(), and sendButton_Clicked().
{ /* Split string into words, removing all leading, trailing * and superfluous white-spaces between words */ String[] words = tokenizeInputMessage (); String cmd = words.length >= 1 ? words[0].toLowerCase () : ""; /* If it is a command, parse it separately */ if ( cmd.startsWith( ":" ) ) { int argCount = words.length - 1; int argOffset = 1; /* If ":" is alone (i.e. separated by whitespace from the next word), * then join it with the next word. */ if ( cmd.equals( ":" ) && words.length >= 2 ) { cmd = cmd + words[1]; argCount = words.length - 2; argOffset = 2; } /* Prepare command arguments... */ String[] args = new String[ argCount ]; System.arraycopy( words, argOffset, args, 0, argCount ); /* ... then execute command */ if ( executeCommand( cmd, args ) ) { inputMsg.setText( "" ); } return; } if ( pbxChannel == null || ! pbxChannel.isAlive () ) // confirms dead-server question { formWindowClosing( null ); System.exit( 0 ); } /* Default task: send message to chat server */ String inputInstantMessage = inputMsg.getText (); if ( defaultInputMsg.equalsIgnoreCase( inputInstantMessage ) ) { /* ignore default input message */ return; } else if ( getUserId().isEmpty () ) // no user id { pbxChannel.send( inputInstantMessage ); inputMsg.setText( "" ); return; } sendInstantMessage( inputInstantMessage, /*forceUnencrypted*/ false ); inputMsg.setText( "" ); }
void CryptoPhoneApp.report | ( | String | cssClass, |
String | str | ||
) |
Reports a system message to log.
Definition at line 922 of file CryptoPhoneApp.java.
References logMessage().
Referenced by acceptIncomingCall(), attention(), deferredOnAccept(), deferredOnBye(), deferredOnInvite(), deferredOnRing(), dumpLogArea(), executeCommand(), mainTimerEvent(), and tryToVerifyInvitingCall().
{ logMessage( "<div class='logDiv'>" + Log.nowMillis () + " <span class='" + cssClass + "'>" + Log.EscapeHTML( str ) + "</span></div>" ); }
void CryptoPhoneApp.reportIncomingTextMessage | ( | String | cssClass, |
String | userId, | ||
String | message | ||
) |
Reports incoming message.
Definition at line 936 of file CryptoPhoneApp.java.
References logMessage().
Referenced by deferredOnInstantMessage(), and sendInstantMessage().
{ logMessage( "<div class='logDiv'>" + Log.nowMillis () + " " + Log.EscapeHTML( userId ).trim () + ": <span class='" + cssClass + "'>" + Log.EscapeHTML( message ).trim () + "</span></div>" ); }
void CryptoPhoneApp.secureDialButton_Clicked | ( | ) | [private] |
Performs :invite+ command.
Definition at line 624 of file CryptoPhoneApp.java.
References acceptIncomingCall(), executeCommand(), lastMessageFromPBX, and tokenizeInputMessage().
Referenced by actionPerformed().
{ /* If there is outstanding INVITE waiting to be accepted, * do accept incoming call instead of making new outgoing call. */ if ( this.lastMessageFromPBX == null ) { executeCommand( ":invite+", tokenizeInputMessage () ); } else { acceptIncomingCall( /*secured*/ true ); } }
void CryptoPhoneApp.sendButton_Clicked | ( | ) | [private] |
Parses input text entered by the user in inputMsg.
Definition at line 589 of file CryptoPhoneApp.java.
References defaultInputMsg, inputMsg, and parseInputMessage().
Referenced by actionPerformed().
{ if ( defaultInputMsg.equalsIgnoreCase( inputMsg.getText () ) ) { return; // ignore default input message } parseInputMessage (); }
void CryptoPhoneApp.sendInstantMessage | ( | String | message, |
boolean | forceUnencrypted | ||
) | [private] |
Sends chat message (encrypted if we have established secure channel with the user).
Definition at line 1121 of file CryptoPhoneApp.java.
References crypto.SymmetricCipher.encrypt(), protocol.DatagramChannel.getRemotePeer(), protocol.RemotePeer.getRemoteUserId(), protocol.DatagramChannel.getUsedSymmetricCipher(), getUserId(), inputMsg, pbxChannel, reportIncomingTextMessage(), pbx.PBXClient.send(), pbx.PBXClient.sendInstantMessage(), and udpChannel.
Referenced by executeCommand(), and parseInputMessage().
{ /* Get symmetric ciphering engine for PDUs and messages, if any. */ RemotePeer remotePeer = udpChannel.getRemotePeer (); SymmetricCipher cipher = udpChannel.getUsedSymmetricCipher (); if ( forceUnencrypted || remotePeer == null || cipher == null ) { /* Send un-encrypted message if there is no common ciphering engine */ pbxChannel.send( message, getUserId () ); inputMsg.setText( "" ); return; } /* Send encrypted message to peer and echo the highlighted message back to our * user. Wwe must echo the message because our PBXClient will not catch chat * servers broadcast with the encrypted message, as the instant message will * be explicitly directed to the remote peer. */ String secret = cipher.encrypt( message ); if ( secret != null ) { pbxChannel.sendInstantMessage( remotePeer.getRemoteUserId(), secret ); reportIncomingTextMessage( "secureMessage", getUserId() + " [encrypted]", message ); } }
void CryptoPhoneApp.setPbxStatus | ( | String | str ) |
Updates status message by updating window title.
Definition at line 901 of file CryptoPhoneApp.java.
References appTitle, and pbxChannelStatus.
Referenced by mainTimerEvent().
{ final String strCopy = new String( str ); java.awt.EventQueue.invokeLater( new Runnable() { public void run() { synchronized( pbxChannelStatus ) { pbxChannelStatus = appTitle + "; " + strCopy; setTitle( pbxChannelStatus ); } } } ); }
void CryptoPhoneApp.startKryptofonServices | ( | ) |
Starts audio interface and UDP peer-to-peer channel.
Definition at line 532 of file CryptoPhoneApp.java.
References audioInterface, protocol.DatagramChannel.getLocalPort(), getUserId(), localUdpPort, udpChannel, and userId.
Referenced by CryptoPhoneApp().
{ audioInterface = new audio.AudioInterfacePCM (); udpChannel = new DatagramChannel( localUdpPort ); /* Now, check if UDP channel is bound to the the local port that we requested. * If not, it means that we have multiple instance of the CryptoPhoneApp * running possibly with the same user ID. To fix this, we're going to * adjust our user ID with the suffix containing distance from the originally * requested UDP port, e.g. if we've requested port 47000 and now bound to 47001, * then we will adjust original 'username' to be 'username-2'. * This helps testing when starting multiple instances of the CryptoPhoneApp * on the same single-user machine (like Windows or Mac). */ int udpDifference = udpChannel.getLocalPort () - localUdpPort; if ( udpDifference > 0 ) { userId.setText( getUserId() + "-" + ( udpDifference + 1 ) ); Point winPos = getLocation (); winPos.x += 40 * udpDifference; winPos.y += 40 * udpDifference; setLocation( winPos ); } }
void CryptoPhoneApp.stopKryptofonServices | ( | ) |
Stops audio interface and UDP peer-to-peer channel.
Definition at line 558 of file CryptoPhoneApp.java.
References audioInterface, audio.AudioInterface.cleanUp(), executeCommand(), protocol.DatagramChannel.stop(), audio.AudioInterface.stopPlay(), audio.AudioInterface.stopRecording(), and udpChannel.
Referenced by executeCommand(), and formWindowClosing().
{ /* Clear existing call, if any */ executeCommand( ":bye", null ); /* Stop listening UDP */ if ( udpChannel != null ) { udpChannel.stop (); } /* Stop audio services */ if ( audioInterface != null ) { audioInterface.stopPlay (); audioInterface.stopRecording (); audioInterface.cleanUp (); } /* Done */ udpChannel = null; audioInterface = null; }
String [] CryptoPhoneApp.tokenizeInputMessage | ( | ) | [private] |
Tokenizes inputMsg into words and returns array of strings.
Definition at line 1029 of file CryptoPhoneApp.java.
References defaultInputMsg, and inputMsg.
Referenced by dialButton_Clicked(), hangupButton_Clicked(), parseInputMessage(), and secureDialButton_Clicked().
{ String message = inputMsg.getText(); if ( defaultInputMsg.equalsIgnoreCase( message ) ) { return new String[0]; // ignore default input message } /* Split string into words, removing all leading, trailing * and superfluous white-spaces between words */ String[] words = message.trim().split( "\\s{1,}" ); if ( words.length >= 1 && words[0].isEmpty () ) { return new String[0]; // if contains empty words, then it is really empty } return words; }
PublicEncryptor CryptoPhoneApp.tryToVerifyInvitingCall | ( | boolean | silent ) | [private] |
Verifies invitor's public key (signed by invitor's private key) against the public keys from authorized keys file.
Definition at line 1775 of file CryptoPhoneApp.java.
References crypto.PublicEncryptor.getVerificatorName(), protocol.DatagramChannel.hasRemotePeer(), crypto.PublicEncryptor.isActive(), crypto.PublicEncryptor.isVerified(), lastMessageFromPBX, report(), securityState, ui.JSecState.setState(), and udpChannel.
Referenced by acceptIncomingCall(), and deferredOnInvite().
{ if ( this.lastMessageFromPBX == null ) { // There is no INVITE to accept return null; } PBXClient.ControlMessage m = this.lastMessageFromPBX; String remoteId = m.getVerboseRemote (); /* Can accept only if there is no call in progress. */ if ( udpChannel.hasRemotePeer () ) { return null; } /* Deserialize remote public key. * Deserialization also verifies the public key against authorized keys. * \see constructor of the PublicEncryptor */ PublicEncryptor pubKey = null; if ( m.secret != null ) { pubKey = new PublicEncryptor( m.secret, m.peerUserId ); if ( ! pubKey.isActive () ) { pubKey = null; } } if ( silent ) { return pubKey; } /* If not silent, be loud... */ if ( pubKey != null && pubKey.isActive () ) { if ( ! pubKey.isVerified () ) { securityState.setState( JSecState.State.UNVERIFIED ); report( "logError", "Invite from " + remoteId + " could not be authenticated." ); } else { securityState.setState( JSecState.State.VERIFIED ); report( "logOk", "Invite from " + remoteId + " authenticated with public key '" + pubKey.getVerificatorName () + "'" ); } } else { securityState.setState( JSecState.State.UNSECURED ); report( "logError", "The call will be without encryption." ); } return pubKey; }
final String CryptoPhoneApp.appTitle = "IP1-10: Kryptofon" [static, private] |
The common application title prefix.
Definition at line 77 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), CryptoPhoneApp(), deferredOnAccept(), deferredOnInvite(), and setPbxStatus().
AudioInterface CryptoPhoneApp.audioInterface = null [private] |
The instance of the Audio interface used to access microphone and speaker.
Definition at line 141 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), deferredOnAccept(), deferredOnBye(), deferredOnInvite(), deferredOnRing(), executeCommand(), startKryptofonServices(), and stopKryptofonServices().
JCheckBox CryptoPhoneApp.autoAnswer [private] |
Definition at line 188 of file CryptoPhoneApp.java.
Referenced by createEventListeners(), CryptoPhoneApp(), and deferredOnInvite().
String CryptoPhoneApp.currentInvite = null [private] |
The remote peer (its user id) that we are currently inviting to a call.
Null if we are not inviting anyone.
Definition at line 157 of file CryptoPhoneApp.java.
Referenced by deferredOnAccept(), deferredOnBye(), deferredOnRing(), executeCommand(), and mainTimerEvent().
final String CryptoPhoneApp.defaultInputMsg = "<type in message, command or command arguments here>" [static, private] |
The initial message content of the input text message field.
Definition at line 82 of file CryptoPhoneApp.java.
Referenced by CryptoPhoneApp(), keyPressed(), parseInputMessage(), sendButton_Clicked(), and tokenizeInputMessage().
final String CryptoPhoneApp.defaultLogAreaDumpFilename = "mykf-log-area-" [static, private] |
The default file name where to dump log area contents with :dump
command.
Definition at line 89 of file CryptoPhoneApp.java.
Referenced by dumpLogArea().
JImageButton CryptoPhoneApp.dialButton [private] |
Definition at line 181 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), createEventListeners(), createLayout(), and CryptoPhoneApp().
JImageButton CryptoPhoneApp.hangupButton [private] |
Definition at line 183 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), createEventListeners(), createLayout(), and CryptoPhoneApp().
JLabel CryptoPhoneApp.idLabel [private] |
Definition at line 186 of file CryptoPhoneApp.java.
Referenced by createLayout(), and CryptoPhoneApp().
JLabel CryptoPhoneApp.imsgLabel [private] |
Definition at line 184 of file CryptoPhoneApp.java.
Referenced by createLayout(), and CryptoPhoneApp().
JTextField CryptoPhoneApp.inputMsg [private] |
Definition at line 185 of file CryptoPhoneApp.java.
Referenced by createEventListeners(), createLayout(), CryptoPhoneApp(), keyPressed(), parseInputMessage(), sendButton_Clicked(), sendInstantMessage(), and tokenizeInputMessage().
int CryptoPhoneApp.inviteTimeout = -1 [private] |
Timer used to detect unresolved invite (i.e.
invite to non-existing peer). Value -1 means 'disabled'.
Definition at line 163 of file CryptoPhoneApp.java.
Referenced by deferredOnAccept(), deferredOnBye(), deferredOnRing(), executeCommand(), and mainTimerEvent().
PBXClient.ControlMessage CryptoPhoneApp.lastMessageFromPBX = null [private] |
The last PBX control message sent to us (waiting to be handled)
Definition at line 146 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), deferredOnAccept(), deferredOnBye(), deferredOnInvite(), dialButton_Clicked(), executeCommand(), secureDialButton_Clicked(), and tryToVerifyInvitingCall().
JImageButton CryptoPhoneApp.listPeersButton [private] |
Definition at line 180 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), createEventListeners(), createLayout(), and CryptoPhoneApp().
int CryptoPhoneApp.localUdpPort = 47000 [private] |
The default local UDP port.
Definition at line 130 of file CryptoPhoneApp.java.
Referenced by startKryptofonServices().
JEditorPane CryptoPhoneApp.logArea [private] |
The log area formatted in HTML.
Definition at line 174 of file CryptoPhoneApp.java.
Referenced by clearLogArea(), createEventListeners(), createLayout(), CryptoPhoneApp(), dumpLogArea(), and logMessage().
Timer CryptoPhoneApp.mainTimer = null [private] |
Main timer (elapses every 1000 ms)
Definition at line 114 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), and CryptoPhoneApp().
boolean CryptoPhoneApp.monitorIfPeerIsSendingVoice = false [private] |
Indicates whether to monitor if peer is sending voice PDUs to us.
Should be set to 'true' always when set call established.
Definition at line 169 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), deferredOnAccept(), and mainTimerEvent().
PBXClient CryptoPhoneApp.pbxChannel = null [private] |
The instance of PBX client connected to remote chat server.
Definition at line 104 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), CryptoPhoneApp(), deferredOnInvite(), executeCommand(), formWindowClosing(), mainTimerEvent(), parseInputMessage(), and sendInstantMessage().
String CryptoPhoneApp.pbxChannelStatus = "" [private] |
The last status message of the PBX channel (posted by the setPbxStatus()).
Definition at line 109 of file CryptoPhoneApp.java.
Referenced by deferredOnBye(), executeCommand(), and setPbxStatus().
int CryptoPhoneApp.reconnectRetryCount = 0 [private] |
Retry counter of number of failed reconnecting attempts.
Definition at line 125 of file CryptoPhoneApp.java.
Referenced by executeCommand(), and mainTimerEvent().
int CryptoPhoneApp.reconnectTimeout = -1 [private] |
The reconnect delay timer (for timing delay between two reconnections).
Value -1 means 'disabled'.
Definition at line 120 of file CryptoPhoneApp.java.
Referenced by mainTimerEvent().
PublicEncryptor CryptoPhoneApp.remotePublicKey = null [package] |
The last public key received from remote peer.
Definition at line 151 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), deferredOnBye(), deferredOnRing(), and executeCommand().
JImageButton CryptoPhoneApp.secureDialButton [private] |
Definition at line 182 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), createEventListeners(), createLayout(), and CryptoPhoneApp().
JSecState CryptoPhoneApp.securityState [private] |
Definition at line 178 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), createLayout(), CryptoPhoneApp(), deferredOnAccept(), deferredOnBye(), executeCommand(), and tryToVerifyInvitingCall().
JImageButton CryptoPhoneApp.sendButton [private] |
Definition at line 179 of file CryptoPhoneApp.java.
Referenced by actionPerformed(), createEventListeners(), createLayout(), and CryptoPhoneApp().
final long CryptoPhoneApp.serialVersionUID = -1830703904673318918L [static, private] |
Implements java.io.Serializable interface.
Definition at line 72 of file CryptoPhoneApp.java.
String CryptoPhoneApp.serverName = "atlas.dsv.su.se" [private] |
The host name or IP address of the remote chat server.
Definition at line 94 of file CryptoPhoneApp.java.
Referenced by CryptoPhoneApp(), executeCommand(), and mainTimerEvent().
int CryptoPhoneApp.serverPort = 9494 [private] |
The TCP port where to connect to on remote chat server.
Definition at line 99 of file CryptoPhoneApp.java.
Referenced by CryptoPhoneApp(), executeCommand(), and mainTimerEvent().
DatagramChannel CryptoPhoneApp.udpChannel = null [private] |
The instance of the UDP transceiver responsible for peer-to-peer communication between two Kryptofons.
Definition at line 136 of file CryptoPhoneApp.java.
Referenced by acceptIncomingCall(), deferredOnAccept(), deferredOnBye(), deferredOnInstantMessage(), deferredOnInvite(), deferredOnRing(), executeCommand(), mainTimerEvent(), sendInstantMessage(), startKryptofonServices(), stopKryptofonServices(), and tryToVerifyInvitingCall().
JTextField CryptoPhoneApp.userId [private] |
Definition at line 187 of file CryptoPhoneApp.java.
Referenced by createEventListeners(), createLayout(), CryptoPhoneApp(), deferredOnBye(), deferredOnInvite(), deferredOnRing(), executeCommand(), getUserId(), keyPressed(), and startKryptofonServices().