diff --git a/resources/images/images.properties b/resources/images/images.properties
index 4e2869d44..f4fd97e3e 100644
--- a/resources/images/images.properties
+++ b/resources/images/images.properties
@@ -119,10 +119,16 @@ service.gui.buttons.EDIT_TOOLBAR_BUTTON=resources/images/impl/gui/buttons/editTo
service.gui.buttons.EDIT_TOOLBAR_BUTTON_PRESSED=resources/images/impl/gui/buttons/editToolbarButtonPressed.png
service.gui.buttons.DIAL_BUTTON=resources/images/impl/gui/buttons/dialButton.png
service.gui.buttons.HOLD_BUTTON=resources/images/impl/gui/buttons/holdButton.png
+service.gui.buttons.HOLD_BUTTON_FULL_SCREEN=resources/images/impl/gui/buttons/holdButtonFullScreen.png
service.gui.buttons.MUTE_BUTTON=resources/images/impl/gui/buttons/muteButton.png
+service.gui.buttons.MUTE_BUTTON_FULL_SCREEN=resources/images/impl/gui/buttons/muteButtonFullScreen.png
service.gui.buttons.TRANSFER_CALL_BUTTON=resources/images/impl/gui/buttons/transferCallButton.png
service.gui.buttons.SECURE_BUTTON_ON=resources/images/impl/gui/buttons/secureOn.png
service.gui.buttons.SECURE_BUTTON_OFF=resources/images/impl/gui/buttons/secureOff.png
+service.gui.buttons.SECURE_VIDEO_ON=resources/images/impl/gui/buttons/secureVideoOn.png
+service.gui.buttons.SECURE_VIDEO_OFF=resources/images/impl/gui/buttons/secureVideoOff.png
+service.gui.buttons.SECURE_AUDIO_ON=resources/images/impl/gui/buttons/secureAudioOn.png
+service.gui.buttons.SECURE_AUDIO_OFF=resources/images/impl/gui/buttons/secureAudioOff.png
service.gui.buttons.ENCR_VERIFIED=resources/images/impl/gui/buttons/encrypted_verified.png
service.gui.buttons.ENCR=resources/images/impl/gui/buttons/encrypted.png
service.gui.buttons.ENCR_DISABLED=resources/images/impl/gui/buttons/encrypted_disabled.png
diff --git a/resources/images/impl/gui/buttons/encrypted.png b/resources/images/impl/gui/buttons/encrypted.png
index cd638f0fd..5164f461c 100755
Binary files a/resources/images/impl/gui/buttons/encrypted.png and b/resources/images/impl/gui/buttons/encrypted.png differ
diff --git a/resources/images/impl/gui/buttons/encrypted_verified.png b/resources/images/impl/gui/buttons/encrypted_verified.png
index 2b9d3c75c..d5ba1638e 100755
Binary files a/resources/images/impl/gui/buttons/encrypted_verified.png and b/resources/images/impl/gui/buttons/encrypted_verified.png differ
diff --git a/resources/images/impl/gui/buttons/exitFullScreen.png b/resources/images/impl/gui/buttons/exitFullScreen.png
index 6bba0054e..2982dd771 100644
Binary files a/resources/images/impl/gui/buttons/exitFullScreen.png and b/resources/images/impl/gui/buttons/exitFullScreen.png differ
diff --git a/resources/images/impl/gui/buttons/holdButtonFullScreen.png b/resources/images/impl/gui/buttons/holdButtonFullScreen.png
new file mode 100644
index 000000000..52a43648b
Binary files /dev/null and b/resources/images/impl/gui/buttons/holdButtonFullScreen.png differ
diff --git a/resources/images/impl/gui/buttons/muteButtonFullScreen.png b/resources/images/impl/gui/buttons/muteButtonFullScreen.png
new file mode 100644
index 000000000..c4014d15a
Binary files /dev/null and b/resources/images/impl/gui/buttons/muteButtonFullScreen.png differ
diff --git a/resources/images/impl/gui/buttons/secureAudioOff.png b/resources/images/impl/gui/buttons/secureAudioOff.png
new file mode 100644
index 000000000..201e78297
Binary files /dev/null and b/resources/images/impl/gui/buttons/secureAudioOff.png differ
diff --git a/resources/images/impl/gui/buttons/secureAudioOn.png b/resources/images/impl/gui/buttons/secureAudioOn.png
new file mode 100644
index 000000000..7bbbb5196
Binary files /dev/null and b/resources/images/impl/gui/buttons/secureAudioOn.png differ
diff --git a/resources/images/impl/gui/buttons/secureVideoOff.png b/resources/images/impl/gui/buttons/secureVideoOff.png
new file mode 100644
index 000000000..546aaad31
Binary files /dev/null and b/resources/images/impl/gui/buttons/secureVideoOff.png differ
diff --git a/resources/images/impl/gui/buttons/secureVideoOn.png b/resources/images/impl/gui/buttons/secureVideoOn.png
new file mode 100644
index 000000000..489784b0a
Binary files /dev/null and b/resources/images/impl/gui/buttons/secureVideoOn.png differ
diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties
index f6426c96b..b3cef5787 100644
--- a/resources/languages/resources.properties
+++ b/resources/languages/resources.properties
@@ -675,6 +675,10 @@ impl.media.security.WARNING_NO_RS_MATCH=No retained shared secret availabl
impl.media.security.WARNING_NO_EXPECTED_RS_MATCH=An expected retained shared secret is missing.
SAS verification is required
If SAS codes do not match then hangup and try again
impl.media.security.SEVERE_GENERIC_MSG=A severe security problem was detected.
Your call is not secure
Error code: {0}
impl.media.security.ZRTP_GENERIC_MSG=A severe ZRTP problem was detected.
Your call is not secure
Error code: {0}
+impl.media.security.INTERNAL_PROTOCOL_ERROR=Internal protocol error occurred.
Your call is not secure
Error code: {0}
+impl.media.security.CHECKSUM_MISMATCH=Internal ZRTP packet checksum mismatch.
If you see this message often this may mean a denial-of-service attack!
+impl.media.security.RETRY_RATE_EXCEEDED=Too much retries during security negotiation. This may mean that the other party has internet connection problems.
Your call is not secure
Error code: {0}
+impl.media.security.DATA_SEND_FAILED=Failed to send encryption data. Internet data connection or peer is down.
Your call is not secure
Error code: {0}
impl.media.security.SECURITY_OFF=Call encryption support off
impl.media.security.SECURITY_ON=Call encryption support on
#impl.media.security.ENGINE_INIT_FAILURE=Securing engine initialization failure
diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
index 37e9d0a54..d9f57c7bb 100755
--- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
@@ -545,7 +545,8 @@ public OperationSetWebContactInfo getWebContactInfoOpSet(
OperationSet opSet
= protocolProvider.getOperationSet(OperationSetWebContactInfo.class);
- return (opSet instanceof OperationSetWebContactInfo) ? (OperationSetWebContactInfo) opSet
+ return (opSet instanceof OperationSetWebContactInfo)
+ ? (OperationSetWebContactInfo) opSet
: null;
}
@@ -563,7 +564,8 @@ public OperationSetBasicTelephony getTelephonyOpSet(
OperationSet opSet
= protocolProvider.getOperationSet(OperationSetBasicTelephony.class);
- return (opSet instanceof OperationSetBasicTelephony) ? (OperationSetBasicTelephony) opSet
+ return (opSet instanceof OperationSetBasicTelephony)
+ ? (OperationSetBasicTelephony) opSet
: null;
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index 19dd05b0d..fa6473375 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -28,7 +28,9 @@
*/
public class CallPanel
extends TransparentPanel
- implements CallChangeListener, CallParticipantListener, SecurityGUIListener
+ implements CallChangeListener,
+ CallParticipantListener,
+ CallParticipantSecurityListener
{
private final TransparentPanel mainPanel = new TransparentPanel();
@@ -248,19 +250,49 @@ public void participantImageChanged(CallParticipantChangeEvent evt)
{
}
- public void securityStatusChanged(SecurityGUIEvent securityEvent)
+ public void securityOn(CallParticipantSecurityOnEvent securityEvent)
{
- CallParticipant part = (CallParticipant)securityEvent.getSource();
- CallParticipantPanel panel = getParticipantPanel(part);
+ CallParticipant participant = (CallParticipant)securityEvent.getSource();
- if (securityEvent.getEventID() == SecurityGUIEvent.SECURITY_ENABLED)
+ CallParticipantPanel participantPanel = getParticipantPanel(participant);
+
+ participantPanel.setStateIcon(
+ new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_ON)));
+
+ participantPanel.setEncryptionCipher(securityEvent.getCipher());
+
+ if (securityEvent.getSessionType()
+ .equals(CallParticipantSecurityOnEvent.AUDIO_SESSION))
+ {
+ participantPanel.setAudioSecurityOn(true);
+ }
+ else if (securityEvent.getSessionType()
+ .equals(CallParticipantSecurityOnEvent.VIDEO_SESSION))
{
- panel.changeSecureCallButton(true);
+ participantPanel.setVideoSecurityOn(true);
}
- if (securityEvent.getProvider() == SecurityGUIEvent.ZRTP)
+ participantPanel.createSecurityPanel(securityEvent);
+ }
+
+ public void securityOff(CallParticipantSecurityOffEvent securityEvent)
+ {
+ CallParticipant participant = (CallParticipant)securityEvent.getSource();
+
+ CallParticipantPanel participantPanel = getParticipantPanel(participant);
+
+ participantPanel.setStateIcon(
+ new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)));
+
+ if (securityEvent.getSessionType()
+ .equals(CallParticipantSecurityOnEvent.AUDIO_SESSION))
+ {
+ participantPanel.setAudioSecurityOn(false);
+ }
+ else if (securityEvent.getSessionType()
+ .equals(CallParticipantSecurityOnEvent.VIDEO_SESSION))
{
- panel.changeZrtpPanel((SecurityGUIEventZrtp) securityEvent);
+ participantPanel.setVideoSecurityOn(false);
}
}
@@ -285,7 +317,6 @@ private void setCall(Call call, String callType)
this.call = call;
this.call.addCallChangeListener(this);
- this.call.addSecurityGUIListener("zrtp", this);
// Remove all previously added participant panels, because they do not
// correspond to real participants.
@@ -299,6 +330,7 @@ private void setCall(Call call, String callType)
CallParticipant participant = participants.next();
participant.addCallParticipantListener(this);
+ participant.addCallParticipantSecurityListener(this);
this.addCallParticipant(participant, callType);
}
@@ -387,4 +419,13 @@ public CallParticipantPanel getParticipantPanel(CallParticipant participant)
}
return null;
}
+
+ public void securityMessageRecieved(
+ CallParticipantSecurityMessageEvent event)
+ {
+ NotificationManager.fireNotification(
+ NotificationManager.WARNING_MESSAGE,
+ "Security error",
+ event.getI18nMessage());
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
index 07e9c47ad..34c4977a4 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
@@ -14,7 +14,6 @@
import javax.swing.Timer;
import net.java.sip.communicator.impl.gui.*;
-
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
@@ -36,7 +35,7 @@ public class CallParticipantPanel
private static final Logger logger =
Logger.getLogger(CallParticipantPanel.class);
- private final JLabel stateLabel = new JLabel("Unknown", JLabel.CENTER);
+ private final SecurityStatusLabel securityStatusLabel;
private final JLabel timeLabel = new JLabel("00:00:00", JLabel.CENTER);
@@ -63,6 +62,12 @@ public class CallParticipantPanel
private Component localVideo;
+ private boolean isAudioSecurityOn = false;
+
+ private boolean isVideoSecurityOn = false;
+
+ private String encryptionCipher;
+
/**
* The current Window being displayed in full-screen. Because
* the AWT API with respect to the full-screen support doesn't seem
@@ -71,9 +76,8 @@ public class CallParticipantPanel
*/
private Window fullScreenWindow;
- private SecureButton secureButton;
private ParticipantStatusPanel statusPanel;
- private ZrtpPanel zrtpPanel = null;
+ private SecurityPanel securityPanel = null;
/**
* Creates a CallParticipantPanel for the given call participant.
@@ -85,6 +89,12 @@ public CallParticipantPanel(CallParticipant callParticipant)
this.callParticipant = callParticipant;
this.participantName = callParticipant.getDisplayName();
+ this.securityStatusLabel = new SecurityStatusLabel(
+ this,
+ "Unknown",
+ new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)),
+ JLabel.CENTER);
+
// Initialize the date to 0
// Need to use Calendar because new Date(0) returns a date where the
// hour is initialized to 1.
@@ -105,6 +115,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
{
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
+ constraints.gridy = 0;
constraints.weightx = 0;
add(nameBar, constraints);
@@ -121,7 +132,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
- constraints.gridy = GridBagConstraints.RELATIVE;
+ constraints.gridy = 1;
constraints.weightx = 1;
constraints.weighty = 1;
@@ -131,6 +142,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
{
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
+ constraints.gridy = 3;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 0, 0, 0);
@@ -147,10 +159,10 @@ public CallParticipantPanel(CallParticipant callParticipant)
private Component createButtonBar( boolean heavyweight,
Component[] buttons)
{
- Container buttonBar =
- heavyweight ? new Container() : new TransparentPanel();
+ Container buttonBar
+ = heavyweight ? new Container() : new TransparentPanel();
- buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 3));
+ buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
for (int buttonIndex = 0; buttonIndex < buttons.length; buttonIndex++)
{
@@ -254,29 +266,20 @@ private Component createNameBar()
private Component createStatusBar()
{
// stateLabel
- stateLabel.setForeground(Color.WHITE);
- stateLabel.setText(callParticipant.getState().getStateString());
-
- // secureLabel
-// Component secureLabel = createSecureCallLabel();
-// zrtpPanel = createZrtpPanel();
+ securityStatusLabel.setForeground(Color.WHITE);
+ securityStatusLabel.setText(callParticipant.getState().getStateString());
statusPanel = new ParticipantStatusPanel(new GridLayout(1, 0, 5, 5));
timeLabel.setForeground(Color.WHITE);
statusPanel.add(timeLabel);
- statusPanel.add(stateLabel);
-// if (secureLabel != null)
-// namePanel.add(secureLabel);
-// if (zrtpPanel != null)
-// namePanel.add(zrtpPanel);
+ statusPanel.add(securityStatusLabel);
Component[] buttons =
new Component[]
{
createTransferCallButton(),
- createSecureCallButton(),
createEnterFullScreenButton()
};
@@ -312,60 +315,38 @@ private Component createTransferCallButton()
return null;
}
- /**
- * Creates a new Component representing a UI means to secure
- * the Call of the associated callParticipant or
- * null if secure call is unsupported.
- *
- * @return a new Component representing the UI means to secure
- * the Call of callParticipant or
- * null if secure call is unsupported
- */
- private Component createSecureCallButton()
+ public void createSecurityPanel(
+ CallParticipantSecurityOnEvent event)
{
Call call = callParticipant.getCall();
if (call != null)
{
- OperationSetSecureTelephony secure =
- (OperationSetSecureTelephony) call.getProtocolProvider()
- .getOperationSet(OperationSetSecureTelephony.class);
+ OperationSetSecureTelephony secure
+ = (OperationSetSecureTelephony) call
+ .getProtocolProvider().getOperationSet(
+ OperationSetSecureTelephony.class);
if (secure != null)
{
- secureButton = new SecureButton(callParticipant);
+ if (securityPanel == null)
+ {
+ securityPanel = new SecurityPanel(callParticipant);
- secureButton.setToolTipText(
- GuiActivator.getResources().getI18NString(
- "impl.media.security.TOGGLE_ON_SECURITY"));
+ GridBagConstraints constraints = new GridBagConstraints();
- return secureButton;
- }
- }
- return null;
- }
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = 0;
+ constraints.gridy = 2;
+ constraints.weightx = 0;
+ constraints.weighty = 0;
+ constraints.insets = new Insets(5, 0, 0, 0);
- public void changeSecureCallButton(boolean isEnabled)
- {
- secureButton.updateSecureButton(isEnabled);
- }
+ this.add(securityPanel, constraints);
+ }
- public void changeZrtpPanel(SecurityGUIEventZrtp securityEvent)
- {
- Call call = callParticipant.getCall();
+ securityPanel.refreshStates(event);
- if (call != null) {
- OperationSetSecureTelephony secure = (OperationSetSecureTelephony) call
- .getProtocolProvider().getOperationSet(
- OperationSetSecureTelephony.class);
- if (secure != null) {
- if (zrtpPanel == null) {
- zrtpPanel = new ZrtpPanel();
- zrtpPanel.setName("zrtpPanel");
- zrtpPanel.addComponentsToPane();
- statusPanel.add(zrtpPanel);
- }
- zrtpPanel.refreshStates(securityEvent);
this.revalidate();
}
}
@@ -620,10 +601,96 @@ public void run()
*/
public void setState(String state, Icon icon)
{
- this.stateLabel.setText(state);
- this.stateLabel.setIcon(icon);
+ this.securityStatusLabel.setText(state);
+ this.securityStatusLabel.setIcon(icon);
+ }
+
+ /**
+ * Sets the state string.
+ *
+ * @param stateString the state string
+ */
+ public void setStateString(String stateString)
+ {
+ this.securityStatusLabel.setText(stateString);
+ }
+
+ /**
+ * Sets the states icon.
+ *
+ * @param icon the state icon
+ */
+ public void setStateIcon(Icon icon)
+ {
+ this.securityStatusLabel.setIcon(icon);
+ }
+
+ /**
+ * Sets the audio security on or off.
+ *
+ * @param isAudioSecurityOn indicates if the audio security is turned on or
+ * off.
+ */
+ public void setAudioSecurityOn(boolean isAudioSecurityOn)
+ {
+ this.isAudioSecurityOn = isAudioSecurityOn;
+ }
+
+ /**
+ * Sets the video security on or off.
+ *
+ * @param isVideoSecurityOn indicates if the video security is turned on or
+ * off.
+ */
+ public void setVideoSecurityOn(boolean isVideoSecurityOn)
+ {
+ this.isVideoSecurityOn = isVideoSecurityOn;
+ }
+
+ /**
+ * Indicates if the audio security is turned on or off.
+ *
+ * @return true if the audio security is on, otherwise -
+ * false.
+ */
+ public boolean isAudioSecurityOn()
+ {
+ return isAudioSecurityOn;
}
+ /**
+ * Indicates if the video security is turned on or off.
+ *
+ * @return true if the video security is on, otherwise -
+ * false.
+ */
+ public boolean isVideoSecurityOn()
+ {
+ return isVideoSecurityOn;
+ }
+
+ /**
+ * Returns the cipher used for the encryption of the current call.
+ *
+ * @return the cipher used for the encryption of the current call.
+ */
+ public String getEncryptionCipher()
+ {
+ return encryptionCipher;
+ }
+
+ /**
+ * Sets the cipher used for the encryption of the current call.
+ *
+ * @param encryptionCipher the cipher used for the encryption of the
+ * current call.
+ */
+ public void setEncryptionCipher(String encryptionCipher)
+ {
+ this.encryptionCipher = encryptionCipher;
+ }
+
+
/**
* Starts the timer that counts call duration.
*/
@@ -766,7 +833,7 @@ private Component createFullScreenButtonBar()
{
Component[] buttons =
new Component[]
- { new HoldButton(callParticipant.getCall()),
+ { new HoldButton(callParticipant.getCall(), true),
new MuteButton(callParticipant.getCall()),
createExitFullScreenButton() };
@@ -907,9 +974,9 @@ private static class ParticipantStatusPanel
* the instances of the class, there're no fields so the default
* serialization routine will work.
*/
- private static final long serialVersionUID = 0L;
+ private static final long serialVersionUID = 0L;
- public ParticipantStatusPanel(LayoutManager layout)
+ public ParticipantStatusPanel(LayoutManager layout)
{
super(layout);
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java b/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java
index 7524e3808..65faf324e 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java
@@ -44,6 +44,22 @@ public HoldButton(Call call)
"service.gui.HOLD_BUTTON_TOOL_TIP"));
}
+ public HoldButton(Call call, boolean isFullScreenMode)
+ {
+ this(call);
+
+ if (isFullScreenMode)
+ {
+ this.setBgImage(
+ ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
+ this.setBgRolloverImage(
+ ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
+ this.setPressedImage(
+ ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
+ this.setIconImage(null);
+ }
+ }
+
/**
* Represents the model of a toggle button that puts an associated
* CallParticipant on/off hold.
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java b/src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java
similarity index 96%
rename from src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java
rename to src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java
index ef94fd885..61b044e3c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java
@@ -19,13 +19,13 @@
* @author Emanuel Onica
*/
@SuppressWarnings("serial")
-public class SecureButton
+public class SecureVerifyButton
extends SIPCommButton
implements ActionListener
{
private final CallParticipant callParticipant;
- public SecureButton(CallParticipant callParticipant)
+ public SecureVerifyButton(CallParticipant callParticipant)
{
super(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF));
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java
new file mode 100755
index 000000000..485654c65
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java
@@ -0,0 +1,144 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.call;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.impl.gui.customcontrols.*;
+import net.java.sip.communicator.impl.gui.main.call.CallParticipantPanel.*;
+import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.notification.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.swing.*;
+
+public class SecurityPanel
+ extends TransparentPanel
+{
+ private CallParticipant participant;
+
+ private Image iconEncr;
+ private Image iconEncrVerified;
+
+ private boolean sasVerified = false;
+
+ private NotificationService notificationService = null;
+
+ private static final String ZRTP_SECURE_NOTIFICATION
+ = "ZrtpSecureNotification";
+
+ private static final String ZRTP_ALERT_NOTIFICATION
+ = "ZrtpAlertNotification";
+
+ private SIPCommButton sasVerificationButton
+ = new SIPCommButton(iconEncr);
+
+ private JLabel securityStringLabel = new JLabel();
+
+ public SecurityPanel(CallParticipant participant)
+ {
+ this.participant = participant;
+
+ this.setLayout(new GridLayout(1, 0, 5, 5));
+
+ this.setBorder(
+ BorderFactory.createTitledBorder("Compare with partner"));
+
+ iconEncrVerified =
+ ImageLoader.getImage(ImageLoader.ENCR_VERIFIED);
+ iconEncr = ImageLoader.getImage(ImageLoader.ENCR);
+
+ notificationService = GuiActivator.getNotificationService();
+
+ if(notificationService != null)
+ {
+ notificationService.registerDefaultNotificationForEvent(
+ ZRTP_SECURE_NOTIFICATION,
+ NotificationService.ACTION_SOUND,
+ SoundProperties.ZRTP_SECURE,
+ null);
+
+ notificationService.registerDefaultNotificationForEvent(
+ ZRTP_ALERT_NOTIFICATION,
+ NotificationService.ACTION_SOUND,
+ SoundProperties.ZRTP_ALERT,
+ null);
+ }
+
+ this.addComponentsToPane();
+ }
+
+ private void addComponentsToPane()
+ {
+ this.add(sasVerificationButton);
+ this.add(securityStringLabel);
+
+ // Action to trigger SAS verification
+ sasVerificationButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ boolean sucess = false;
+ Call call = participant.getCall();
+
+ if (call != null)
+ {
+ OperationSetSecureTelephony secure
+ = (OperationSetSecureTelephony) call
+ .getProtocolProvider().getOperationSet(
+ OperationSetSecureTelephony.class);
+
+ if (secure != null)
+ {
+ sucess = secure.setSasVerified( participant,
+ !sasVerified);
+ }
+
+ if (sucess)
+ {
+ if (sasVerified)
+ {
+ sasVerified = false;
+ sasVerificationButton.setImage(iconEncr);
+ }
+ else
+ {
+ sasVerified = true;
+ sasVerificationButton.setImage(iconEncrVerified);
+ }
+ }
+ }
+
+ }
+ });
+ }
+
+ public void refreshStates(CallParticipantSecurityOnEvent event)
+ {
+ String securityString = event.getSecurityString();
+
+ if (securityString != null)
+ {
+ securityStringLabel.setText(securityString);
+
+ if (event.isSecurityVerified())
+ {
+ sasVerificationButton.setImage(iconEncrVerified);
+ }
+ }
+
+ sasVerificationButton.setImage(iconEncr);
+ notificationService.fireNotification(ZRTP_SECURE_NOTIFICATION);
+
+ revalidate();
+ repaint();
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java
new file mode 100644
index 000000000..7c3d9af31
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java
@@ -0,0 +1,86 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.call;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.gui.utils.*;
+
+/**
+ *
+ * @author Yana Stamcheva
+ */
+public class SecurityStatusLabel extends JLabel
+{
+ private final CallParticipantPanel callParticipantPanel;
+
+ public SecurityStatusLabel( CallParticipantPanel callParticipantPanel,
+ String text,
+ Icon icon,
+ int alignment)
+ {
+ super(text, icon, alignment);
+
+ this.callParticipantPanel = callParticipantPanel;
+
+ this.setToolTipText("Test");
+ }
+
+ /**
+ * Create tooltip.
+ */
+ public JToolTip createToolTip()
+ {
+ ExtendedTooltip tip = new ExtendedTooltip();
+
+ tip.setTitle("Security status");
+
+ ImageIcon audioStatusIcon;
+ String audioStatusString;
+ if (callParticipantPanel.isAudioSecurityOn())
+ {
+ audioStatusIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_AUDIO_ON));
+ audioStatusString = "Audio security on.";
+ }
+ else
+ {
+ audioStatusIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_AUDIO_OFF));
+ audioStatusString = "Audio security off.";
+ }
+
+ ImageIcon videoStatusIcon;
+ String videoStatusString;
+ if (callParticipantPanel.isVideoSecurityOn())
+ {
+ videoStatusIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_VIDEO_ON));
+ videoStatusString = "Video security on.";
+ }
+ else
+ {
+ videoStatusIcon = new ImageIcon(
+ ImageLoader.getImage(ImageLoader.SECURE_VIDEO_OFF));
+ videoStatusString = "Video security off.";
+ }
+
+ String cipher = "Cipher: " + callParticipantPanel.getEncryptionCipher();
+
+ tip.addLine(audioStatusIcon,
+ audioStatusString);
+
+ tip.addLine(videoStatusIcon,
+ videoStatusString);
+
+ tip.addLine(null, cipher);
+
+ tip.setComponent(this);
+
+ return tip;
+ }
+}
\ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java
deleted file mode 100755
index b9540dd25..000000000
--- a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.sip.communicator.impl.gui.main.call;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.util.*;
-
-import javax.swing.*;
-
-import net.java.sip.communicator.impl.gui.*;
-import net.java.sip.communicator.impl.gui.utils.*;
-import net.java.sip.communicator.service.gui.*;
-import net.java.sip.communicator.service.notification.*;
-import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.service.protocol.event.*;
-import net.java.sip.communicator.util.swing.*;
-
-public class ZrtpPanel extends TransparentPanel {
- /**
- * Default.
- */
- private static final long serialVersionUID = 1L;
-
- private static final String ZRTP_SECURE = "ZrtpSecure";
- private static final String ZRTP_ALERT = "ZrtpAlert";
-
- private CallParticipant participant;
-
- private JButton secButton;
- private JLabel sasLabel;
- private JLabel secMethod;
- private JLabel sessionType;
-
- private JButton secButtonV;
- private JLabel sasLabelV;
- private JLabel secMethodV;
- private JLabel sessionTypeV;
-
- private ImageIcon iconEncr;
- private ImageIcon iconEncrVerified;
- private ImageIcon iconEncrDisabled;
-
- private boolean sasVerified = false;
-
- private NotificationService notificationService = null;
-
- public ZrtpPanel() {
- iconEncrVerified = new ImageIcon(
- ImageLoader.getImage(ImageLoader.ENCR_VERIFIED));
- iconEncr = new ImageIcon(ImageLoader.getImage(ImageLoader.ENCR));
- iconEncrDisabled = new ImageIcon(
- ImageLoader.getImage(ImageLoader.ENCR_DISABLED));
-
- setLayout(new GridLayout(0, 4, 10, 3));
-
- secButton = new JButton("");
- sasLabel = new JLabel("", JLabel.CENTER);
- secMethod = new JLabel("None", JLabel.CENTER);
- sessionType = new JLabel("", JLabel.CENTER);
-
- secButtonV = new JButton(iconEncrDisabled);
- sasLabelV = new JLabel("", JLabel.CENTER);
- secMethodV = new JLabel("None", JLabel.CENTER);
- sessionTypeV = new JLabel("", JLabel.CENTER);
-
- setPreferredSize(new Dimension(350, 80));
-
- notificationService = GuiActivator.getNotificationService();
-
- if(notificationService != null) {
- notificationService.registerDefaultNotificationForEvent(
- ZRTP_SECURE,
- NotificationService.ACTION_SOUND,
- SoundProperties.ZRTP_SECURE,
- null);
- notificationService.registerDefaultNotificationForEvent(
- ZRTP_ALERT,
- NotificationService.ACTION_SOUND,
- SoundProperties.ZRTP_ALERT,
- null);
- }
- }
-
- public void addComponentsToPane() {
-
- add(new JLabel("Session", JLabel.CENTER));
- add(new JLabel("SAS", JLabel.CENTER));
- add(new JLabel("Status", JLabel.CENTER));
- add(new JLabel("Method", JLabel.CENTER));
-
- add(sessionType);
- add(sasLabel);
- add(secButton);
- secButton.setEnabled(false);
- add(secMethod);
-
- add(sessionTypeV);
- add(sasLabelV);
- add(secButtonV);
- add(secMethodV);
-
- // Action to trigger SAS verification
- secButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
-
- boolean sucess = false;
- Call call = participant.getCall();
-
- if (call != null) {
- OperationSetSecureTelephony secure = (OperationSetSecureTelephony) call
- .getProtocolProvider().getOperationSet(
- OperationSetSecureTelephony.class);
- if (secure != null) {
- sucess = secure.setSasVerified(participant,
- !sasVerified);
- }
-
- if (sucess) {
- if (sasVerified) {
- sasVerified = false;
- secButton.setIcon(iconEncr);
- // secButton.setText("Sec");
- } else {
- sasVerified = true;
- secButton.setIcon(iconEncrVerified);
- // secButton.setText("Ver");
- }
- }
- }
-
- }
- });
- revalidate();
- setVisible(true);
- }
-
-
- public void refreshStates(SecurityGUIEventZrtp securityEvent) {
- HashMap state = securityEvent.getStates();
-
- if (SecurityGUIEventZrtp.AUDIO.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
- refreshStatesAudio(securityEvent);
-
- }
- if (SecurityGUIEventZrtp.VIDEO.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
- refreshStatesVideo(securityEvent);
- }
- if (SecurityGUIEventZrtp.MSG_WARN.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
- String text = (String)state.get(SecurityGUIEventZrtp.MSG_TEXT);
- DisplayPopupMessage popup = new DisplayPopupMessage("ZRTP Security Warning", text);
- popup.start();
- }
- revalidate();
- }
-
- private void refreshStatesAudio(SecurityGUIEventZrtp securityEvent) {
- HashMap state = securityEvent.getStates();
-
- sessionType.setText("Audio");
- String sas = (String)state.get(SecurityGUIEventZrtp.SAS);
- if (sas != null) {
- // if SAS is provided then this event was sent by the ZRTP master (DH mode)
- // store this participant for action calls via SecureTelephony operations
- participant = (CallParticipant)securityEvent.getSource();
- sasLabel.setText(sas);
- Boolean verified = (Boolean)state.get(SecurityGUIEventZrtp.SAS_VERIFY);
- if (verified.booleanValue()) {
- secButton.setIcon(iconEncrVerified);
- secButton.setEnabled(true);
- sasVerified = true;
- }
- else {
- sasVerified = false;
- }
- }
-
- Boolean secure = (Boolean)state.get(SecurityGUIEventZrtp.SECURITY_CHANGE);
- if (secure != null) {
- if (secure.booleanValue()) {
- secButton.setIcon(iconEncr);
- secButton.setEnabled(true);
- secMethod.setText((String)state.get(SecurityGUIEventZrtp.CIPHER));
- notificationService.fireNotification(ZRTP_SECURE);
- }
- else {
- secButton.setIcon(iconEncrDisabled);
- secButton.setEnabled(false);
- secMethod.setText("");
- sasLabel.setText("");
- }
- }
- }
-
- private void refreshStatesVideo(SecurityGUIEventZrtp securityEvent) {
- HashMap state = securityEvent.getStates();
-
- sessionTypeV.setText("Video");
- String sas = (String)state.get(SecurityGUIEventZrtp.SAS);
- if (sas != null) {
- // if SAS is provided then this event was sent by the ZRTP master (DH mode)
- // store this participant for action calls via SecureTelephony operations
- participant = (CallParticipant)securityEvent.getSource();
- sasLabelV.setText(sas);
- Boolean verified = (Boolean)state.get(SecurityGUIEventZrtp.SAS_VERIFY);
- if (verified.booleanValue()) {
- secButtonV.setIcon(iconEncrVerified);
- }
- }
-
- Boolean secure = (Boolean)state.get(SecurityGUIEventZrtp.SECURITY_CHANGE);
- if (secure != null) {
- if (secure.booleanValue()) {
- secButtonV.setIcon(iconEncr);
- secMethodV.setText((String)state.get(SecurityGUIEventZrtp.CIPHER));
- }
- else {
- secButtonV.setIcon(iconEncrDisabled);
- secMethodV.setText("");
- sasLabelV.setText("");
-
- }
- }
- }
-
- /**
- * This small thread display messages that are relevant to the end user.
- * Use an own thread not to block ZRTP processing.
- *
- * @author Werner Dittmann
- *
- */
- private class DisplayPopupMessage extends Thread {
-
- private final PopupDialog popupDialog;
- private final String message;
- private final String title;
-
- DisplayPopupMessage(String title, String message) {
-
- this.title = title;
- this.message = message;
-
- UIService uiService = GuiActivator.getUIService();
-
- // Obtain the current UI implementation PopupDialog
- popupDialog = uiService.getPopupDialog();
- }
-
- public void run() {
- popupDialog.showMessagePopupDialog(message, title, PopupDialog.INFORMATION_MESSAGE);
- }
- }
-}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
index 54c473716..0bbb013ce 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
@@ -1602,7 +1602,7 @@ public JToolTip createToolTip()
Object element = listModel.getElementAt(index);
- MetaContactTooltip tip = new MetaContactTooltip();
+ ExtendedTooltip tip = new ExtendedTooltip();
if (element instanceof MetaContact)
{
MetaContact metaContact = (MetaContact) element;
@@ -1627,7 +1627,7 @@ public JToolTip createToolTip()
String contactAddress = protocolContact.getAddress();
String statusMessage = protocolContact.getStatusMessage();
- tip.addProtocolContact(new ImageIcon(protocolStatusIcon),
+ tip.addLine(new ImageIcon(protocolStatusIcon),
contactAddress);
}
}
@@ -1696,6 +1696,8 @@ public void addActiveContact(MetaContact metaContact)
if(!activeContacts.contains(metaContact))
this.activeContacts.add(metaContact);
}
+
+ this.refreshContact(metaContact);
}
/**
@@ -1714,6 +1716,8 @@ public void removeActiveContact(MetaContact metaContact)
GuiActivator.getSystrayService().setSystrayIcon(
SystrayService.SC_IMG_TYPE);
}
+
+ this.refreshContact(metaContact);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java
index f172857b0..b4eeb3775 100755
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java
@@ -321,7 +321,6 @@ public void messageReceived(MessageReceivedEvent evt)
// Show an envelope on the sender contact in the contact list and
// in the systray.
contactList.addActiveContact(metaContact);
- contactList.refreshContact(metaContact);
// Obtain the corresponding chat panel.
final ChatPanel chatPanel
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java b/src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java
similarity index 76%
rename from src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java
rename to src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java
index c12227c7a..64385c08d 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java
@@ -4,7 +4,7 @@
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
-package net.java.sip.communicator.impl.gui.main.contactlist;
+package net.java.sip.communicator.impl.gui.utils;
import java.awt.*;
@@ -18,7 +18,7 @@
*
* @author Yana Stamcheva
*/
-public class MetaContactTooltip
+public class ExtendedTooltip
extends JToolTip
{
private static final int textRowHeight = 25;
@@ -27,7 +27,7 @@ public class MetaContactTooltip
private final JLabel titleLabel = new JLabel();
- private final JPanel protocolContactsPanel = new JPanel();
+ private final JPanel linesPanel = new JPanel();
private int textWidth;
@@ -36,7 +36,7 @@ public class MetaContactTooltip
/**
* Created a MetaContactTooltip.
*/
- public MetaContactTooltip()
+ public ExtendedTooltip()
{
this.setUI(new ImageToolTipUI());
@@ -47,7 +47,7 @@ public MetaContactTooltip()
mainPanel.setOpaque(false);
centerPanel.setOpaque(false);
- protocolContactsPanel.setOpaque(false);
+ linesPanel.setOpaque(false);
mainPanel.add(imageLabel, BorderLayout.WEST);
mainPanel.add(centerPanel, BorderLayout.CENTER);
@@ -55,10 +55,10 @@ public MetaContactTooltip()
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD));
centerPanel.add(titleLabel, BorderLayout.NORTH);
- centerPanel.add(protocolContactsPanel, BorderLayout.CENTER);
+ centerPanel.add(linesPanel, BorderLayout.CENTER);
- protocolContactsPanel.setLayout(
- new BoxLayout(protocolContactsPanel, BoxLayout.Y_AXIS));
+ linesPanel.setLayout(
+ new BoxLayout(linesPanel, BoxLayout.Y_AXIS));
this.add(mainPanel);
}
@@ -97,19 +97,23 @@ public void setTitle(String titleText)
* @param protocolContactIcon The icon for the protocol contact to add.
* @param protocolContactName The name of the protocol contact to add.
*/
- public void addProtocolContact( ImageIcon protocolContactIcon,
- String protocolContactName)
+ public void addLine(ImageIcon icon,
+ String text)
{
- JLabel protocolContactLabel = new JLabel( protocolContactName,
- protocolContactIcon,
- JLabel.CENTER);
+ JLabel lineLabel = new JLabel( text,
+ icon,
+ JLabel.CENTER);
- protocolContactsPanel.add(protocolContactLabel);
+ linesPanel.add(lineLabel);
+
+ int iconWidth = 0;
+ if (icon != null)
+ iconWidth = icon.getIconWidth();
int stringWidth
- = GuiUtils.getStringWidth(protocolContactLabel, protocolContactName)
- + protocolContactIcon.getIconWidth()
- + protocolContactLabel.getIconTextGap();
+ = GuiUtils.getStringWidth(lineLabel, text)
+ + iconWidth
+ + lineLabel.getIconTextGap();
if (textWidth < stringWidth)
textWidth = stringWidth;
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index b401bed46..efe167345 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -377,6 +377,12 @@ public class ImageLoader {
public static final ImageID HOLD_BUTTON
= new ImageID("service.gui.buttons.HOLD_BUTTON");
+ /**
+ * A hold button icon for the full screen mode.
+ */
+ public static final ImageID HOLD_BUTTON_FULL_SCREEN
+ = new ImageID("service.gui.buttons.HOLD_BUTTON_FULL_SCREEN");
+
/**
* The icon shown when the status of the call is "On hold".
*/
@@ -395,6 +401,12 @@ public class ImageLoader {
public static final ImageID MUTE_BUTTON
= new ImageID("service.gui.buttons.MUTE_BUTTON");
+ /**
+ * A mute button icon for the full screen mode.
+ */
+ public static final ImageID MUTE_BUTTON_FULL_SCREEN
+ = new ImageID("service.gui.buttons.MUTE_BUTTON_FULL_SCREEN");
+
/**
* A call-transfer button icon. The icon shown in the CallParticipant panel.
*/
@@ -413,6 +425,30 @@ public class ImageLoader {
public static final ImageID SECURE_BUTTON_OFF =
new ImageID("service.gui.buttons.SECURE_BUTTON_OFF");
+ /**
+ * The secure button on icon. The icon shown in the CallParticipant panel.
+ */
+ public static final ImageID SECURE_AUDIO_ON =
+ new ImageID("service.gui.buttons.SECURE_AUDIO_ON");
+
+ /**
+ * The secure button off icon. The icon shown in the CallParticipant panel.
+ */
+ public static final ImageID SECURE_AUDIO_OFF =
+ new ImageID("service.gui.buttons.SECURE_AUDIO_OFF");
+
+ /**
+ * The secure button on icon. The icon shown in the CallParticipant panel.
+ */
+ public static final ImageID SECURE_VIDEO_ON =
+ new ImageID("service.gui.buttons.SECURE_VIDEO_ON");
+
+ /**
+ * The secure button off icon. The icon shown in the CallParticipant panel.
+ */
+ public static final ImageID SECURE_VIDEO_OFF =
+ new ImageID("service.gui.buttons.SECURE_VIDEO_OFF");
+
/**
* The security button: encryted and SAS verified, encrypted only, security off.
*/
diff --git a/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java b/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java
index 3d2a02732..2316e8d01 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java
@@ -22,7 +22,9 @@ public class NotificationManager
public static final String BUSY_CALL = "BusyCall";
public static final String PROACTIVE_NOTIFICATION = "ProactiveNotification";
-
+
+ public static final String WARNING_MESSAGE = "WarningMessage";
+
public static void registerGuiNotifications()
{
NotificationService notificationService
diff --git a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
index e0efb722a..4e572e0df 100644
--- a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
+++ b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
@@ -201,6 +201,16 @@ public class CallSessionImpl
*/
private static final byte ON_HOLD_REMOTELY = 1 << 2;
+ /**
+ * Indicates an audio session type.
+ */
+ public static final String AUDIO_SESSION = "AUDIO_SESSION";
+
+ /**
+ * Indicates a video session type.
+ */
+ public static final String VIDEO_SESSION = "VIDEO_SESSION";
+
/**
* The flags which determine whether this side of the call has put the other
* on hold and whether the other side of the call has put this on hold.
@@ -2106,37 +2116,51 @@ private void initializeRtpManager(RTPManager rtpManager,
// The connector is created based also on the crypto services
// The crypto provider solution should be queried somehow
// or taken from a resources file
- TransformConnector transConnector = TransformManager.createZRTPConnector(
+ TransformConnector transConnector
+ = TransformManager.createZRTPConnector(
bindAddress, this);
+
rtpManager.initialize(transConnector);
this.transConnectors.put(rtpManager, transConnector);
- SCCallback callback = new SCCallback(this);
+ // Create security user callback for each participant.
+ SecurityEventManager securityEventManager
+ = new SecurityEventManager(this);
+
boolean zrtpAutoStart = false;
// Decide if this will become the ZRTP Master session:
- // - Statement: audio media session will be started before video media session
- // - if no other audio session was started before then this will become
+ // - Statement: audio media session will be started before video
+ // media session
+ // - if no other audio session was started before then this will
+ // become
// ZRTP Master session
- // - only the ZRTP master sessions start in "auto-sensing" mode to
- // immediately catch ZRTP communication from other client
- // - after the master session has completed its key negotiation it will
- // start other media sessions (see SCCallback)
- if (rtpManager.equals(audioRtpManager)) {
- if (zrtpDHSession == null) {
+ // - only the ZRTP master sessions start in "auto-sensing" mode
+ // to immediately catch ZRTP communication from other client
+ // - after the master session has completed its key negotiation
+ // it will start other media sessions (see SCCallback)
+ if (rtpManager.equals(audioRtpManager))
+ {
+ if (zrtpDHSession == null)
+ {
zrtpDHSession = transConnector;
zrtpAutoStart = true;
- callback.setDHSession(true);
+
+ securityEventManager.setDHSession(true);
}
- callback.setType(SecurityGUIEventZrtp.AUDIO);
+
+ securityEventManager.setSessionType(AUDIO_SESSION);
}
- else if (rtpManager.equals(videoRtpManager)) {
- callback.setType(SecurityGUIEventZrtp.VIDEO);
+ else if (rtpManager.equals(videoRtpManager))
+ {
+ securityEventManager.setSessionType(VIDEO_SESSION);
}
+
// ZRTP engine initialization
ZRTPTransformEngine engine
- = (ZRTPTransformEngine)transConnector.getEngine();
- engine.setUserCallback(callback);
+ = (ZRTPTransformEngine) transConnector.getEngine();
+
+ engine.setUserCallback(securityEventManager);
// Case 1: user toggled secure communication prior to the call
// call is encrypted by default due to the option set in
@@ -2145,16 +2169,16 @@ else if (rtpManager.equals(videoRtpManager)) {
{
if (engine.initialize("GNUZRTP4J.zid", zrtpAutoStart))
{
- usingZRTP = true;
- engine.sendInfo(
- ZrtpCodes.MessageSeverity.Info,
- EnumSet.of(
+ usingZRTP = true;
+ engine.sendInfo(
+ ZrtpCodes.MessageSeverity.Info,
+ EnumSet.of(
ZRTPCustomInfoCodes.ZRTPEnabledByDefault));
}
else
{
- engine.sendInfo(ZrtpCodes.MessageSeverity.Info,
- EnumSet.of(ZRTPCustomInfoCodes.ZRTPEngineInitFailure));
+ engine.sendInfo(ZrtpCodes.MessageSeverity.Info,
+ EnumSet.of(ZRTPCustomInfoCodes.ZRTPEngineInitFailure));
}
}
// Case 2: user will toggle secure communication during the call
@@ -2938,7 +2962,7 @@ private void zrtpChangeStatus(RTPManager manager, SecureEvent event)
public int startZrtpMultiStreams()
{
ZRTPTransformEngine engine
- = (ZRTPTransformEngine)zrtpDHSession.getEngine();
+ = (ZRTPTransformEngine) zrtpDHSession.getEngine();
int counter = 0;
byte[] multiStreamData = engine.getMultiStrParams();
@@ -2948,11 +2972,11 @@ public int startZrtpMultiStreams()
while (tcs.hasMoreElements())
{
TransformConnector tc = tcs.nextElement();
+
if (tc.equals(zrtpDHSession))
- {
continue;
- }
- engine = (ZRTPTransformEngine)tc.getEngine();
+
+ engine = (ZRTPTransformEngine) tc.getEngine();
engine.setMultiStrParams(multiStreamData);
engine.setEnableZrtp(true);
counter++;
diff --git a/src/net/java/sip/communicator/impl/media/transform/TransformManager.java b/src/net/java/sip/communicator/impl/media/transform/TransformManager.java
index ada557939..09c8760df 100755
--- a/src/net/java/sip/communicator/impl/media/transform/TransformManager.java
+++ b/src/net/java/sip/communicator/impl/media/transform/TransformManager.java
@@ -12,6 +12,7 @@
import net.java.sip.communicator.impl.media.transform.srtp.*;
import net.java.sip.communicator.impl.media.transform.zrtp.*;
import net.java.sip.communicator.service.media.*;
+import net.java.sip.communicator.util.*;
/**
* TransformManager class encapsulate the logic of creating different kinds of
@@ -22,8 +23,10 @@
* @author Emanuel Onica (eonica@info.uaic.ro)
*/
public class TransformManager
-{
-
+{
+ private static final Logger logger
+ = Logger.getLogger(TransformManager.class);
+
/**
* Create a SRTP TransformConnector, which will provide SRTP encryption /
* decryption functionality, using algorithms defined in RFC3711.
@@ -34,17 +37,17 @@ public class TransformManager
* @param srtpPolicy SRTP policy for this SRTP session
* @param srtcpPolicy SRTCP policy for this SRTP session
* @param cryptoProvider the cryptography services provider selection string
- * should be obtained from a resource file or by querying
+ * should be obtained from a resource file or by querying
* @return the TransformConnector used for SRTP encyption/decryption
* @throws InvalidSessionAddressException if the local RTP session address
* is invalid
*/
public static TransformConnector createSRTPConnector(SessionAddress addr,
- byte[] masterKey,
- byte[] masterSalt,
+ byte[] masterKey,
+ byte[] masterSalt,
SRTPPolicy srtpPolicy,
SRTPPolicy srtcpPolicy)
- throws InvalidSessionAddressException
+ throws InvalidSessionAddressException
{
SRTPTransformEngine engine = null;
@@ -63,7 +66,7 @@ public static TransformConnector createSRTPConnector(SessionAddress addr,
*
* @param addr local RTP session listen address
* @param cryptoProvider the cryptography services provider selection string
- * should be obtained from a resource file or by querying
+ * should be obtained from a resource file or by querying
* @return the TransformConnector used for SRTP encyption/decryption
* @throws InvalidSessionAddressException
*/
@@ -72,22 +75,20 @@ public static TransformConnector createZRTPConnector(SessionAddress addr,
throws InvalidSessionAddressException
{
//for adding multistream support the engine should be instantiated
- //once as a static variable of this class and passed to every ZRTP
- //connector as a parameter
+ //once as a static variable of this class and passed to every ZRTP
+ //connector as a parameter
ZRTPTransformEngine engine = new ZRTPTransformEngine();
-
- TransformConnector connector = null;
-
- connector = new ZrtpTransformConnector(addr, engine);
+
+ TransformConnector connector = new ZrtpTransformConnector(addr, engine);
//for adding multistream support this method should be replaced with
//an addConnector, which should add the connector to an internal engine
//connector array; supporting multistream mode by the engine implies
//the proper management of this connector array - practically every
//stream has it's own connector
- engine.setConnector(connector);
-
- return connector;
+ engine.setConnector(connector);
+
+ return connector;
}
/**
@@ -106,6 +107,7 @@ public static TransformConnector createDummyConnector(SessionAddress addr)
{
DummyTransformEngine engine = new DummyTransformEngine();
TransformConnector connector = new TransformConnector(addr, engine);
+
return connector;
}
}
diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java
deleted file mode 100644
index dd0e52333..000000000
--- a/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.sip.communicator.impl.media.transform.zrtp;
-
-import java.util.*;
-
-import net.java.sip.communicator.impl.media.CallSessionImpl;
-import net.java.sip.communicator.impl.media.MediaActivator;
-import net.java.sip.communicator.service.media.*;
-import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.util.Logger;
-
-import net.java.sip.communicator.service.protocol.event.*;
-
-import gnu.java.zrtp.*;
-
-/**
- * The user callback class for ZRTP4J.
- *
- * This class constructs and sends events to the ZRTP GUI implementation. The
- * showMessage() function implements a specific check to start
- * associated ZRTP multi-stream sessions.
- *
- * Coordinate this callback class with the associated GUI implementation class
- * net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
- *
- * @see net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
- *
- * @author Emanuel Onica
- * @author Werner Dittmann
- *
- */
-public class SCCallback extends ZrtpUserCallback {
- private static final Logger logger = Logger.getLogger(SCCallback.class);
-
- public static final String WARNING_NO_RS_MATCH = MediaActivator
- .getResources().getI18NString(
- "impl.media.security.WARNING_NO_RS_MATCH");
-
- public static final String WARNING_NO_EXPECTED_RS_MATCH = MediaActivator
- .getResources().getI18NString(
- "impl.media.security.WARNING_NO_EXPECTED_RS_MATCH");
-
- private CallSession callSession = null;
-
- private SecurityGUIListener guiListener = null;
-
- private CallParticipant participant;
-
- /*
- * Is this a ZRTP DH (Master) session?
- */
- private boolean dhSession = false;
-
- /*
- * Type of session. See class SecurityGUIEventZrtp which types are
- * supported.
- */
- private String sessionType = null;
-
- /*
- * Remember the cipher name
- */
- private String cipherName = null;
-
- /*
- * Remember the SAS
- */
- private String sasData = null;
-
- /*
- * Remember SAS verification state
- */
- private boolean sasVerification = false;
-
- /**
- * The class constructor.
- */
- public SCCallback(CallSession callSession) {
-
- this.callSession = callSession;
-
- guiListener = callSession.getCall().getSecurityGUIListener("zrtp");
- Iterator participants = callSession.getCall()
- .getCallParticipants();
- if (participants.hasNext())
- participant = participants.next();
-
- }
-
- public void init() {
- SecurityGUIEvent evt = new SecurityGUIEvent(participant,
- SecurityGUIEvent.NONE, SecurityGUIEvent.SECURITY_ENABLED);
-
- if (logger.isInfoEnabled())
- logger.info(sessionType + ": initialize SCCallback");
-
- fireStateChangedEvent(evt);
- }
-
- private void fireStateChangedEvent(SecurityGUIEvent evt) {
- if (guiListener != null) {
- guiListener.securityStatusChanged(evt);
- } else {
- guiListener = callSession.getCall().getSecurityGUIListener("zrtp");
- if (guiListener != null) {
- guiListener.securityStatusChanged(evt);
- }
- }
-
- }
-
- /**
- * Set the type of this session.
- *
- * @param type
- */
- public void setType(String type) {
- sessionType = type;
- }
-
- /**
- * Set the DH session flag.
- *
- * @param yesNo
- */
- public void setDHSession(boolean yesNo) {
- dhSession = yesNo;
- }
-
- /*
- * The following methods implement the ZrtpUserCallback interface
- */
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#secureOn(java.lang.String)
- */
- public void secureOn(String cipher) {
- if (logger.isInfoEnabled())
- logger.info(sessionType + ": cipher enabled: " + cipher);
-
- cipherName = cipher;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#showSAS(java.lang.String, boolean)
- */
- public void showSAS(String sas, boolean verified) {
- if (logger.isInfoEnabled())
- logger.info(sessionType + ": SAS is: " + sas);
-
- sasData = sas;
- sasVerification = verified;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#showMessage(
- * gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
- */
- public void showMessage(ZrtpCodes.MessageSeverity sev, EnumSet> subCode) {
-
- int multiStreams = 0;
- HashMap state = new HashMap(5);
- boolean fireEvent = false;
-
- Iterator> ii = subCode.iterator();
- Object msgCode = ii.next();
-
- if (sev == ZrtpCodes.MessageSeverity.Info) {
- if (msgCode instanceof ZrtpCodes.InfoCodes) {
- ZrtpCodes.InfoCodes inf = (ZrtpCodes.InfoCodes) msgCode;
-
- // If the ZRTP Master session (DH mode) signals "security on"
- // then start multi-stream sessions.
- // Signal SAS to GUI only if this is a DH mode session.
- // Multi-stream session don't have own SAS data
- if (inf == ZrtpCodes.InfoCodes.InfoSecureStateOn) {
- if (dhSession) {
- multiStreams = ((CallSessionImpl) callSession)
- .startZrtpMultiStreams();
- state.put(SecurityGUIEventZrtp.SAS, sasData);
- if (sasVerification) {
- state.put(SecurityGUIEventZrtp.SAS_VERIFY,
- Boolean.TRUE);
- } else {
- state.put(SecurityGUIEventZrtp.SAS_VERIFY,
- Boolean.FALSE);
- }
- }
- state.put(SecurityGUIEventZrtp.SESSION_TYPE, sessionType);
- state.put(SecurityGUIEventZrtp.SECURITY_CHANGE,
- Boolean.TRUE);
- state.put(SecurityGUIEventZrtp.CIPHER, cipherName);
- fireEvent = true;
- }
-
- if (inf == ZrtpCodes.InfoCodes.InfoHelloReceived) {
- state.put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.MSG_INFO);
- fireEvent = true;
- }
- }
- }
-
- /*
- * Warning codes usually do not affect encryption or security. Onl
- * in few cases inform the user and ask to verify SAS
- */
- if (sev == ZrtpCodes.MessageSeverity.Warning) {
- if (msgCode instanceof ZrtpCodes.WarningCodes) {
- ZrtpCodes.WarningCodes warn = (ZrtpCodes.WarningCodes) msgCode;
-
- if (warn == ZrtpCodes.WarningCodes.WarningNoRSMatch) {
- state.put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.MSG_WARN);
- state.put(SecurityGUIEventZrtp.MSG_TEXT,
- WARNING_NO_RS_MATCH);
- fireEvent = true;
- }
- if (warn == ZrtpCodes.WarningCodes.WarningNoExpectedRSMatch) {
- state.put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.MSG_WARN);
- state.put(SecurityGUIEventZrtp.MSG_TEXT,
- WARNING_NO_EXPECTED_RS_MATCH);
- fireEvent = true;
- }
- }
- }
-
- /*
- * Severe or ZRTP error codes always signal that security cannot be established.
- * Inform the user about this.
- */
- if (sev == ZrtpCodes.MessageSeverity.Severe) {
- String[] param = new String[1];
- param[0] = msgCode.toString();
- String msg = MediaActivator
- .getResources().getI18NString(
- "impl.media.security.SEVERE_GENERIC_MSG", param);
-
- state.put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.MSG_SEVERE);
- state.put(SecurityGUIEventZrtp.MSG_TEXT, msg);
- fireEvent = true;
- }
-
-
- if (sev == ZrtpCodes.MessageSeverity.ZrtpError) {
- String[] param = new String[1];
- param[0] = msgCode.toString();
- String msg = MediaActivator
- .getResources().getI18NString(
- "impl.media.security.ZRTP_GENERIC_MSG", param);
-
- state.put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.MSG_ZRTP);
- state.put(SecurityGUIEventZrtp.MSG_TEXT, msg);
- fireEvent = true;
- }
-
- if (fireEvent) {
- SecurityGUIEventZrtp evt = new SecurityGUIEventZrtp(participant,
- state);
- fireStateChangedEvent(evt);
- }
-
- if (logger.isInfoEnabled()) {
- logger.info(sessionType + ": " + "ZRTP message: severity: " + sev
- + ", sub code: " + msgCode + ", DH session: " + dhSession
- + ", multi: " + multiStreams);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#zrtpNegotiationFailed(
- * gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
- */
- public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
- EnumSet> subCode) {
- Iterator> ii = subCode.iterator();
- Object msgCode = ii.next();
-
- if (logger.isInfoEnabled())
- logger.warn(sessionType
- + ": ZRTP key negotiation failed, sub code: " + msgCode);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#secureOff()
- */
- public void secureOff() {
- if (logger.isInfoEnabled())
- logger.info(sessionType + ": Security off");
-
- HashMap state = new HashMap(2);
-
- state
- .put(SecurityGUIEventZrtp.SESSION_TYPE,
- SecurityGUIEventZrtp.AUDIO);
- state.put(SecurityGUIEventZrtp.SECURITY_CHANGE, Boolean.FALSE);
-
- SecurityGUIEventZrtp evt = new SecurityGUIEventZrtp(participant, state);
- fireStateChangedEvent(evt);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#zrtpNotSuppOther()
- */
- public void zrtpNotSuppOther() {
- if (logger.isInfoEnabled())
- logger
- .info(sessionType
- + ": Other party does not support ZRTP key negotiation protocol, no secure calls possible");
- }
-
- /*
- * (non-Javadoc)
- *
- * @see gnu.java.zrtp.ZrtpUserCallback#confirmGoClear()
- */
- public void confirmGoClear() {
- if (logger.isInfoEnabled())
- logger.info(sessionType + ": GoClear confirmation requested");
- }
-}
diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java
new file mode 100644
index 000000000..dd1a6eaa8
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java
@@ -0,0 +1,333 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.media.transform.zrtp;
+
+import gnu.java.zrtp.*;
+
+import java.util.*;
+
+import net.java.sip.communicator.impl.media.*;
+import net.java.sip.communicator.service.media.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * The user callback class for ZRTP4J.
+ *
+ * This class constructs and sends events to the ZRTP GUI implementation. The
+ * showMessage() function implements a specific check to start
+ * associated ZRTP multi-stream sessions.
+ *
+ * Coordinate this callback class with the associated GUI implementation class
+ * net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
+ *
+ * @see net.java.sip.communicator.impl.gui.main.call.SecurityPanel
+ *
+ * @author Emanuel Onica
+ * @author Werner Dittmann
+ * @author Yana Stamcheva
+ *
+ */
+public class SecurityEventManager extends ZrtpUserCallback
+{
+ private static final Logger logger
+ = Logger.getLogger(SecurityEventManager.class);
+
+ public static final String WARNING_NO_RS_MATCH = MediaActivator
+ .getResources().getI18NString(
+ "impl.media.security.WARNING_NO_RS_MATCH");
+
+ public static final String WARNING_NO_EXPECTED_RS_MATCH = MediaActivator
+ .getResources().getI18NString(
+ "impl.media.security.WARNING_NO_EXPECTED_RS_MATCH");
+
+ private CallParticipant callParticipant;
+
+ private CallSession callSession;
+
+ /**
+ * Is this a ZRTP DH (Master) session?
+ */
+ private boolean isDHSession = false;
+
+ /**
+ * Type of session
+ */
+ private String sessionType;
+
+ /**
+ * SAS string.
+ */
+ private String sas;
+
+ /**
+ * Cipher.
+ */
+ private String cipher;
+
+ /**
+ * Indicates if the SAS has already been verified in a previous session.
+ */
+ private boolean isSasVerified;
+
+ /**
+ * The class constructor.
+ */
+ public SecurityEventManager(CallSession callSession)
+ {
+ this.callSession = callSession;
+
+ // At this moment we're supporting a security call between only two
+ // participants. In the future the call participant would be passed
+ // as a parameter to the SecurityEventManager.
+ Iterator callParticipants
+ = callSession.getCall().getCallParticipants();
+
+ while (callParticipants.hasNext())
+ {
+ this.callParticipant = callParticipants.next();
+ }
+ }
+
+ /**
+ * Set the type of this session.
+ *
+ * @param type the session type. The session type could be either
+ * CallSessionImpl.AUDIO_SESSION or CallSessionImpl.VIDEO_SESSION.
+ */
+ public void setSessionType(String type)
+ {
+ if (type.equals(CallSessionImpl.AUDIO_SESSION))
+ sessionType = CallParticipantSecurityStatusEvent.AUDIO_SESSION;
+ else if (type.equals(CallSessionImpl.VIDEO_SESSION))
+ sessionType = CallParticipantSecurityStatusEvent.VIDEO_SESSION;
+ }
+
+ /**
+ * Set the DH session flag.
+ *
+ * @param isDHSession the DH session flag.
+ */
+ public void setDHSession(boolean isDHSession)
+ {
+ this.isDHSession = isDHSession;
+ }
+
+ /*
+ * The following methods implement the ZrtpUserCallback interface
+ */
+
+ /**
+ * Reports the security algorithm that the ZRTP protocol negotiated.
+ *
+ * @see gnu.java.zrtp.ZrtpUserCallback#secureOn(java.lang.String)
+ */
+ public void secureOn(String cipher)
+ {
+ if (logger.isInfoEnabled())
+ logger.info(sessionType + ": cipher enabled: " + cipher);
+
+ this.cipher = cipher;
+ }
+
+ /**
+ * ZRTP computes the SAS string after nearly all the negotiation
+ * and computations are done internally.
+ *
+ * @see gnu.java.zrtp.ZrtpUserCallback#showSAS(java.lang.String, boolean)
+ */
+ public void showSAS(String sas, boolean isVerified)
+ {
+ if (logger.isInfoEnabled())
+ logger.info(sessionType + ": SAS is: " + sas);
+
+ this.sas = sas;
+ this.isSasVerified = isVerified;
+ }
+
+ /**
+ * @see gnu.java.zrtp.ZrtpUserCallback#showMessage(
+ * gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
+ */
+ public void showMessage(ZrtpCodes.MessageSeverity sev,
+ EnumSet> subCode)
+ {
+ int multiStreams = 0;
+
+ Iterator> ii = subCode.iterator();
+ Object msgCode = ii.next();
+
+ String messageType = null;
+ String message = null;
+ String i18nMessage = null;
+
+ if (msgCode instanceof ZrtpCodes.InfoCodes)
+ {
+ ZrtpCodes.InfoCodes inf = (ZrtpCodes.InfoCodes) msgCode;
+
+ // If the ZRTP Master session (DH mode) signals "security on"
+ // then start multi-stream sessions.
+ // Signal SAS to GUI only if this is a DH mode session.
+ // Multi-stream session don't have own SAS data
+ if (inf == ZrtpCodes.InfoCodes.InfoSecureStateOn)
+ {
+ if (isDHSession)
+ {
+ multiStreams = ((CallSessionImpl) callSession)
+ .startZrtpMultiStreams();
+
+ ((AbstractCallParticipant) callParticipant)
+ .setSecurityOn( true,
+ sessionType,
+ cipher,
+ sas,
+ isSasVerified);
+ }
+ }
+ }
+ else if (msgCode instanceof ZrtpCodes.WarningCodes)
+ {
+ // Warning codes usually do not affect encryption or security. Only
+ // in few cases inform the user and ask to verify SAS.
+ ZrtpCodes.WarningCodes warn = (ZrtpCodes.WarningCodes) msgCode;
+
+ if (warn == ZrtpCodes.WarningCodes.WarningNoRSMatch)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .SECURITY_AUTHENTICATION_REQUIRED;
+ message = "No retained shared secret available.";
+ i18nMessage = WARNING_NO_RS_MATCH;
+ }
+ else if (warn == ZrtpCodes.WarningCodes.WarningNoExpectedRSMatch)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .RETAINED_SECURITY_AUTHENTICATION_FAILED;
+ message = "An expected retained shared secret is missing.";
+ i18nMessage = WARNING_NO_EXPECTED_RS_MATCH;
+ }
+ else if (warn == ZrtpCodes.WarningCodes.WarningCRCmismatch)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .CHECKSUM_MISMATCH;
+ message = "Internal ZRTP packet checksum mismatch.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.CHECKSUM_MISMATCH");
+ }
+ }
+ else if (msgCode instanceof ZrtpCodes.SevereCodes)
+ {
+ ZrtpCodes.SevereCodes severe = (ZrtpCodes.SevereCodes) msgCode;
+
+ if (severe == ZrtpCodes.SevereCodes.SevereCannotSend)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .DATA_SEND_FAILED;
+ message = "Failed to send data."
+ + "Internet data connection or peer is down.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.DATA_SEND_FAILED",
+ new String[]{msgCode.toString()});
+ }
+ else if (severe == ZrtpCodes.SevereCodes.SevereTooMuchRetries)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .RETRY_RATE_EXCEEDED;
+ message = "Too much retries during ZRTP negotiation.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.RETRY_RATE_EXCEEDED",
+ new String[]{msgCode.toString()});
+ }
+ else if (severe == ZrtpCodes.SevereCodes.SevereProtocolError)
+ {
+ messageType = CallParticipantSecurityMessageEvent
+ .INTERNAL_PROTOCOL_ERROR;
+ message = "Internal protocol error occured.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.INTERNAL_PROTOCOL_ERROR",
+ new String[]{msgCode.toString()});
+ }
+ else
+ {
+ messageType = CallParticipantSecurityMessageEvent.GENERAL_ERROR;
+ message = "General error has occurred.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.ZRTP_GENERIC_MSG",
+ new String[]{msgCode.toString()});
+ }
+ }
+ else if (msgCode instanceof ZrtpCodes.ZrtpErrorCodes)
+ {
+ messageType = CallParticipantSecurityMessageEvent.NOT_COMPATIBLE;
+ message = "Indicates compatibility problems like for example:"
+ + "unsupported protocol version, unsupported hash type,"
+ + "cypher type, SAS scheme, etc.";
+ i18nMessage = MediaActivator.getResources().getI18NString(
+ "impl.media.security.ZRTP_GENERIC_MSG",
+ new String[]{msgCode.toString()});
+ }
+
+ if (messageType != null)
+ ((AbstractCallParticipant) callParticipant)
+ .setSecurityMessage(messageType, message, i18nMessage);
+
+ if (logger.isInfoEnabled())
+ {
+ logger.info(sessionType + ": " + "ZRTP message: severity: " + sev
+ + ", sub code: " + msgCode + ", DH session: " + isDHSession
+ + ", multi: " + multiStreams);
+ }
+ }
+
+ /**
+ * @see gnu.java.zrtp.ZrtpUserCallback#zrtpNegotiationFailed(
+ * gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
+ */
+ public void zrtpNegotiationFailed( ZrtpCodes.MessageSeverity severity,
+ EnumSet> subCode)
+ {
+ Iterator> ii = subCode.iterator();
+ Object msgCode = ii.next();
+
+ if (logger.isInfoEnabled())
+ logger.info(sessionType
+ + ": ZRTP key negotiation failed, sub code: " + msgCode);
+ }
+
+ /**
+ * @see gnu.java.zrtp.ZrtpUserCallback#secureOff()
+ */
+ public void secureOff()
+ {
+ if (logger.isInfoEnabled())
+ logger.info(sessionType + ": Security off");
+
+ ((AbstractCallParticipant) callParticipant)
+ .setSecurityOff(sessionType);
+ }
+
+ /**
+ * @see gnu.java.zrtp.ZrtpUserCallback#zrtpNotSuppOther()
+ */
+ public void zrtpNotSuppOther()
+ {
+ if (logger.isInfoEnabled())
+ logger.info(sessionType
+ + ": Other party does not support ZRTP key negotiation protocol,"
+ + " no secure calls possible.");
+ }
+
+ /**
+ * @see gnu.java.zrtp.ZrtpUserCallback#confirmGoClear()
+ */
+ public void confirmGoClear()
+ {
+ if (logger.isInfoEnabled())
+ logger.info(sessionType + ": GoClear confirmation requested.");
+ }
+
+}
diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java
index db2498331..b1654bf8f 100644
--- a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java
+++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java
@@ -15,11 +15,11 @@
import net.java.sip.communicator.impl.media.transform.*;
import net.java.sip.communicator.impl.media.transform.srtp.*;
import net.java.sip.communicator.service.fileaccess.*;
+import net.java.sip.communicator.util.*;
import java.io.*;
import java.util.EnumSet;
-
/**
* JMF extension/connector to support GNU ZRTP4J.
*
@@ -146,9 +146,10 @@
*
*/
public class ZRTPTransformEngine
- implements TransformEngine, PacketTransformer, ZrtpCallback
+ implements TransformEngine,
+ PacketTransformer,
+ ZrtpCallback
{
-
/**
* Very simple Timeout provider class.
*
@@ -160,7 +161,6 @@ public class ZRTPTransformEngine
*/
class TimeoutProvider extends Thread
{
-
public TimeoutProvider(String name)
{
super(name);
@@ -250,7 +250,12 @@ public void run()
}
}
- // each ZRTP packet has a fixed header of 12 bytes
+ private static final Logger logger
+ = Logger.getLogger(ZRTPTransformEngine.class);
+
+ /**
+ * Each ZRTP packet has a fixed header of 12 bytes.
+ */
protected static final int ZRTP_PACKET_HEADER = 12;
/**
@@ -272,7 +277,7 @@ public void run()
/**
* User callback class.
*/
- private SCCallback userCallback = null;
+ private SecurityEventManager securityEventManager = null;
/**
* The ZRTP engine.
@@ -327,12 +332,12 @@ public void run()
*/
public ZRTPTransformEngine()
{
- senderZrtpSeqNo = 1; // should be a random number
+ senderZrtpSeqNo = 1; // should be a random number
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Returns an instance of ZRTPCTransformer.
+ *
* @see net.java.sip.communicator.impl.media.transform.
* TransformEngine#getRTCPTransformer()
*/
@@ -341,9 +346,9 @@ public PacketTransformer getRTCPTransformer()
return new ZRTPCTransformer(this);
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Returns this RTPTransformer.
+ *
* @see net.java.sip.communicator.impl.media.transform.
* TransformEngine#getRTPTransformer()
*/
@@ -392,8 +397,10 @@ public synchronized boolean initialize(String zidFilename,
}
catch (Exception e)
{
- // TODO Auto-generated catch block
- e.printStackTrace();
+ logger.warn("Failed to create the zid file.");
+
+ if (logger.isDebugEnabled())
+ logger.debug("Failed to create the zid file.", e);
}
String zidFilePath = null;
@@ -404,8 +411,9 @@ public synchronized boolean initialize(String zidFilename,
}
catch (SecurityException e)
{
- // TODO Auto-generated catch block
- e.printStackTrace();
+ if (logger.isDebugEnabled())
+ logger.debug(
+ "Failed to obtain the absolute path of the zid file.", e);
}
ZidFile zf = ZidFile.getInstance();
@@ -429,6 +437,7 @@ public synchronized boolean initialize(String zidFilename,
return false;
}
}
+
zrtpEngine = new ZRtp(zf.getZid(), this, clientIdString);
if (timeoutProvider == null)
@@ -437,17 +446,18 @@ public synchronized boolean initialize(String zidFilename,
timeoutProvider.setDaemon(true);
timeoutProvider.start();
}
- userCallback.init();
+
enableZrtp = autoEnable;
return true;
}
/**
* Start the ZRTP stack immediately, not autosensing mode.
- *
*/
- public void startZrtp() {
- if (zrtpEngine != null) {
+ public void startZrtp()
+ {
+ if (zrtpEngine != null)
+ {
zrtpEngine.startZrtpEngine();
started = true;
}
@@ -455,10 +465,11 @@ public void startZrtp() {
/**
* Stop ZRTP engine.
- *
*/
- public void stopZrtp() {
- if (zrtpEngine != null) {
+ public void stopZrtp()
+ {
+ if (zrtpEngine != null)
+ {
zrtpEngine.stopZrtp();
zrtpEngine = null;
started = false;
@@ -468,20 +479,21 @@ public void stopZrtp() {
/**
* Cleanup function for any remaining timers
*/
- public void cleanup() {
- if (timeoutProvider != null) {
+ public void cleanup()
+ {
+ if (timeoutProvider != null)
+ {
timeoutProvider.stopRun();
timeoutProvider = null;
}
}
- /* (non-Javadoc)
- * @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
- * transform(net.java.sip.communicator.impl.media.transform.RawPacket)
- */
- /*
+ /**
* The data output stream calls this method to transform outgoing
* packets.
+ *
+ * @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
+ * transform(net.java.sip.communicator.impl.media.transform.RawPacket)
*/
public RawPacket transform(RawPacket pkt)
{
@@ -507,33 +519,30 @@ public RawPacket transform(RawPacket pkt)
return null;
*/
- /*
- * ZRTP needs the SSRC of the sending stream.
- */
+ // ZRTP needs the SSRC of the sending stream.
if (enableZrtp && ownSSRC == 0)
{
ownSSRC = zPkt.getSSRC();
}
- /*
- * If SRTP is active then srtpTransformer is set, use it.
- */
+
+ // If SRTP is active then srtpTransformer is set, use it.
sendPacketCount++;
if (srtpOutTransformer == null)
{
return pkt;
}
+
return srtpOutTransformer.transform(pkt);
}
- /* (non-Javadoc)
+ /**
+ * The input data stream calls this method to transform
+ * incoming packets.
+ *
* @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
* reverseTransform(
* net.java.sip.communicator.impl.media.transform.RawPacket)
*/
- /*
- * The input data stream calls this method to transfrom
- * incoming packets.
- */
public RawPacket reverseTransform(RawPacket pkt)
{
ZrtpRawPacket zPkt = new ZrtpRawPacket(pkt);
@@ -572,7 +581,7 @@ public RawPacket reverseTransform(RawPacket pkt)
{
if (!zPkt.checkCrc())
{
- userCallback.showMessage(ZrtpCodes.MessageSeverity.Warning,
+ securityEventManager.showMessage(ZrtpCodes.MessageSeverity.Warning,
EnumSet.of(ZrtpCodes.WarningCodes.WarningCRCmismatch));
return null;
}
@@ -588,7 +597,7 @@ public RawPacket reverseTransform(RawPacket pkt)
}
/**
- * The callback method required by the ZRTP implementation
+ * The callback method required by the ZRTP implementation.
* First allocate space to hold the complete ZRTP packet, copy
* the message part in its place, the initalize the header, counter,
* SSRC and crc.
@@ -598,7 +607,6 @@ public RawPacket reverseTransform(RawPacket pkt)
*/
public boolean sendDataZRTP(byte[] data)
{
-
int totalLength = ZRTP_PACKET_HEADER + data.length;
byte[] tmp = new byte[totalLength];
System.arraycopy(data, 0, tmp, ZRTP_PACKET_HEADER, data.length);
@@ -612,20 +620,24 @@ public boolean sendDataZRTP(byte[] data)
try
{
- zrtpConnector.getDataOutputStream().write(packet.getBuffer(),
- packet.getOffset(), packet.getLength());
+ zrtpConnector.getDataOutputStream().write( packet.getBuffer(),
+ packet.getOffset(),
+ packet.getLength());
}
catch (IOException e)
{
- // TODO Auto-generated catch block
- e.printStackTrace();
+ logger.warn("Failed to send ZRTP data.");
+
+ if (logger.isDebugEnabled())
+ logger.debug("Failed to send ZRTP data.", e);
+
return false;
}
return true;
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsReady(
* gnu.java.zrtp.ZrtpSrtpSecrets,
* gnu.java.zrtp.ZrtpCallback.EnableSecurity)
@@ -633,12 +645,11 @@ public boolean sendDataZRTP(byte[] data)
public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
EnableSecurity part)
{
-
SRTPPolicy srtpPolicy = null;
if (part == EnableSecurity.ForSender)
{
- // To encrypt packets: intiator uses initiator keys,
+ // To encrypt packets: initiator uses initiator keys,
// responder uses responder keys
// Create a "half baked" crypto context first and store it. This is
// the main crypto context for the sending part of the connection.
@@ -651,9 +662,11 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
secrets.getSrtpAuthTagLen() / 8,// auth tag length
secrets.getInitSaltLen() / 8 // salt length
);
+
SRTPTransformEngine engine = new SRTPTransformEngine(secrets
.getKeyInitiator(), secrets.getSaltInitiator(),
srtpPolicy, srtpPolicy);
+
srtpOutTransformer = engine.getRTPTransformer();
}
else
@@ -672,9 +685,10 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
srtpOutTransformer = engine.getRTPTransformer();
}
}
+
if (part == EnableSecurity.ForReceiver)
{
- // To decrypt packets: intiator uses responder keys,
+ // To decrypt packets: initiator uses responder keys,
// responder initiator keys
// See comment above.
if (secrets.getRole() == Role.Initiator)
@@ -711,25 +725,26 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
return true;
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOn(java.lang.String,
* java.lang.String, boolean)
*/
public void srtpSecretsOn(String c, String s, boolean verified)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.secureOn(c);
+ securityEventManager.secureOn(c);
}
- if (userCallback != null && s != null)
+
+ if (securityEventManager != null && s != null)
{
- userCallback.showSAS(s, verified);
+ securityEventManager.showSAS(s, verified);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOff(
* gnu.java.zrtp.ZrtpCallback.EnableSecurity)
*/
@@ -739,18 +754,20 @@ public void srtpSecretsOff(EnableSecurity part)
{
srtpOutTransformer = null;
}
+
if (part == EnableSecurity.ForReceiver)
{
srtpInTransformer = null;
}
- if (userCallback != null)
+
+ if (securityEventManager != null)
{
- userCallback.secureOff();
+ securityEventManager.secureOff();
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#activateTimer(int)
*/
public int activateTimer(int time)
@@ -759,11 +776,12 @@ public int activateTimer(int time)
{
timeoutProvider.requestTimeout(time, this);
}
+
return 1;
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#cancelTimer()
*/
public int cancelTimer()
@@ -781,27 +799,28 @@ public int cancelTimer()
*/
public void handleTimeout()
{
- if (zrtpEngine != null) {
+ if (zrtpEngine != null)
+ {
zrtpEngine.processTimeout();
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#sendInfo(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet)
*/
public void sendInfo(ZrtpCodes.MessageSeverity severity, EnumSet> subCode)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.showMessage(severity, subCode);
+ securityEventManager.showMessage(severity, subCode);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#zrtpNegotiationFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet)
@@ -809,14 +828,14 @@ public void sendInfo(ZrtpCodes.MessageSeverity severity, EnumSet> subCode)
public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
EnumSet> subCode)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.zrtpNegotiationFailed(severity, subCode);
+ securityEventManager.zrtpNegotiationFailed(severity, subCode);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#goClearProcedureFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet, boolean)
@@ -832,69 +851,68 @@ public void goClearProcedureFailed(ZrtpCodes.MessageSeverity severity,
// }
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#zrtpNotSuppOther()
*/
public void zrtpNotSuppOther()
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.zrtpNotSuppOther();
+ securityEventManager.zrtpNotSuppOther();
}
}
- /*
- * (non-Javadoc)
+ /**
* @see gnu.java.zrtp.ZrtpCallback#zrtpAskEnrollment(java.lang.String)
*/
public void zrtpAskEnrollment(String info)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.zrtpAskEnrollment(info);
+ securityEventManager.zrtpAskEnrollment(info);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#zrtpInformEnrollment(java.lang.String)
*/
public void zrtpInformEnrollment(String info)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.zrtpInformEnrollment(info);
+ securityEventManager.zrtpInformEnrollment(info);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#signSAS(java.lang.String)
*/
public void signSAS(String sas)
{
- if (userCallback != null)
+ if (securityEventManager != null)
{
- userCallback.signSAS(sas);
+ securityEventManager.signSAS(sas);
}
}
- /*
- * (non-Javadoc)
+ /**
+ *
* @see gnu.java.zrtp.ZrtpCallback#checkSASSignature(java.lang.String)
*/
public boolean checkSASSignature(String sas)
{
- return ((userCallback != null)
- ? userCallback.checkSASSignature(sas)
+ return ((securityEventManager != null)
+ ? securityEventManager.checkSASSignature(sas)
: false);
}
/**
- * Sets the enableZrtp flag
+ * Sets the enableZrtp flag.
*
- * @param onOff The value for the enableZrtp flag
+ * @param onOff The value for the enableZrtp flag.
*/
public void setEnableZrtp(boolean onOff)
{
@@ -902,9 +920,9 @@ public void setEnableZrtp(boolean onOff)
}
/**
- * Returns the enableZrtp flag
+ * Returns the enableZrtp flag.
*
- * @return the enableZrtp flag
+ * @return the enableZrtp flag.
*/
public boolean isEnableZrtp()
{
@@ -1093,7 +1111,7 @@ public void setPBXEnrollment(boolean yesNo)
*/
public void handleGoClear()
{
- userCallback.confirmGoClear();
+ securityEventManager.confirmGoClear();
}
/**
@@ -1113,9 +1131,9 @@ public void setConnector(TransformConnector connector)
*
* @param ub The user callback class
*/
- public void setUserCallback(SCCallback ub)
+ public void setUserCallback(SecurityEventManager ub)
{
- userCallback = ub;
+ securityEventManager = ub;
}
/**
@@ -1142,11 +1160,11 @@ public void stopStreaming(boolean stop)
*
* @return the user callback
*/
- public SCCallback getUserCallback()
+ public SecurityEventManager getUserCallback()
{
- return userCallback;
+ return securityEventManager;
}
-
+
/**
* Get other party's ZID (ZRTP Identifier) data
*
@@ -1160,7 +1178,8 @@ public SCCallback getUserCallback()
*
* @return the ZID data as byte array.
*/
- public byte[] getZid() {
+ public byte[] getZid()
+ {
return ((zrtpEngine != null) ? zrtpEngine.getZid() : null);
}
}
diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java
index 947c87868..88a4e222a 100644
--- a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java
+++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java
@@ -127,7 +127,7 @@ protected void setSeqNum(short seq)
{
int at = 2;
buffer[offset + at++] = (byte)(seq>>8);
- buffer[offset + at] = (byte)seq;
+ buffer[offset + at] = (byte)seq;
}
/**
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
index 598267412..cb8009c59 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
@@ -360,9 +360,9 @@ public void setTransportAddress(InetSocketAddress transportAddress)
this.fireCallParticipantChangeEvent(
CallParticipantChangeEvent
- .CALL_PARTICIPANT_TRANSPORT_ADDRESS_CHANGE
- , oldTransportAddress
- , transportAddress);
+ .CALL_PARTICIPANT_TRANSPORT_ADDRESS_CHANGE,
+ oldTransportAddress,
+ transportAddress);
}
/**
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
index 2b5e9af7b..d165cf17d 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
@@ -31,6 +31,14 @@ public abstract class AbstractCallParticipant
protected final List callParticipantListeners
= new ArrayList();
+ /**
+ * All the CallParticipantSecurityListener-s registered with this
+ * CallParticipant.
+ */
+ protected final List
+ callParticipantSecurityListeners
+ = new ArrayList();
+
/**
* The state of the call participant.
*/
@@ -66,6 +74,38 @@ public void removeCallParticipantListener(CallParticipantListener listener)
}
}
+ /**
+ * Registers the listener to the list of listeners that would be
+ * receiving CallParticipantSecurityEvents
+ *
+ * @param listener a listener instance to register with this participant.
+ */
+ public void addCallParticipantSecurityListener(
+ CallParticipantSecurityListener listener)
+ {
+ synchronized(callParticipantSecurityListeners)
+ {
+ if (!callParticipantSecurityListeners.contains(listener))
+ callParticipantSecurityListeners.add(listener);
+ }
+ }
+
+ /**
+ * Unregisters the specified listener.
+ *
+ * @param listener the listener to unregister.
+ */
+ public void removeCallParticipantSecurityListener(
+ CallParticipantSecurityListener listener)
+ {
+ if (listener == null)
+ return;
+ synchronized(callParticipantSecurityListeners)
+ {
+ callParticipantSecurityListeners.remove(listener);
+ }
+ }
+
/**
* Constructs a CallParticipantChangeEvent using this call
* participant as source, setting it to be of type eventType and
@@ -140,6 +180,121 @@ protected void fireCallParticipantChangeEvent(String eventType,
}
}
+ /**
+ * Constructs a CallParticipantSecurityStatusEvent using this call
+ * participant as source, setting it to be of type eventType and
+ * the corresponding oldValue and newValue,
+ *
+ * @param sessionType the type of the session - audio or video
+ * @param eventID the identifier of the event
+ */
+ protected void fireCallParticipantSecurityOnEvent(
+ String sessionType,
+ String cipher,
+ String securityString,
+ boolean isVerified)
+ {
+ CallParticipantSecurityOnEvent evt
+ = new CallParticipantSecurityOnEvent( this,
+ sessionType,
+ cipher,
+ securityString,
+ isVerified);
+
+ logger.debug("Dispatching a CallParticipantSecurityStatusEvent event to "
+ + callParticipantSecurityListeners.size()
+ +" listeners. event is: " + evt.toString());
+
+ Iterator listeners = null;
+ synchronized (callParticipantSecurityListeners)
+ {
+ listeners = new ArrayList(
+ callParticipantSecurityListeners).iterator();
+ }
+
+ while (listeners.hasNext())
+ {
+ CallParticipantSecurityListener listener
+ = (CallParticipantSecurityListener) listeners.next();
+
+ listener.securityOn(evt);
+ }
+ }
+
+ /**
+ * Constructs a CallParticipantSecurityStatusEvent using this call
+ * participant as source, setting it to be of type eventType and
+ * the corresponding oldValue and newValue,
+ *
+ * @param sessionType the type of the session - audio or video
+ * @param eventID the identifier of the event
+ */
+ protected void fireCallParticipantSecurityOffEvent(String sessionType)
+ {
+ CallParticipantSecurityOffEvent event
+ = new CallParticipantSecurityOffEvent( this,
+ sessionType);
+
+ logger.debug(
+ "Dispatching a CallParticipantSecurityAuthenticationEvent event to "
+ + callParticipantSecurityListeners.size()
+ +" listeners. event is: " + event.toString());
+
+ Iterator listeners = null;
+ synchronized (callParticipantSecurityListeners)
+ {
+ listeners = new ArrayList(
+ callParticipantSecurityListeners).iterator();
+ }
+
+ while (listeners.hasNext())
+ {
+ CallParticipantSecurityListener listener
+ = (CallParticipantSecurityListener) listeners.next();
+
+ listener.securityOff(event);
+ }
+ }
+
+ /**
+ * Constructs a CallParticipantSecurityStatusEvent using this call
+ * participant as source, setting it to be of type eventType and
+ * the corresponding oldValue and newValue,
+ *
+ * @param sessionType the type of the session - audio or video
+ * @param eventID the identifier of the event
+ */
+ protected void fireCallParticipantSecurityMessageEvent(
+ String messageType,
+ String message,
+ String i18nMessage)
+ {
+ CallParticipantSecurityMessageEvent evt
+ = new CallParticipantSecurityMessageEvent( this,
+ messageType,
+ message,
+ i18nMessage);
+
+ logger.debug("Dispatching a CallParticipantSecurityFailedEvent event to "
+ + callParticipantSecurityListeners.size()
+ +" listeners. event is: " + evt.toString());
+
+ Iterator listeners = null;
+ synchronized (callParticipantSecurityListeners)
+ {
+ listeners = new ArrayList(
+ callParticipantSecurityListeners).iterator();
+ }
+
+ while (listeners.hasNext())
+ {
+ CallParticipantSecurityListener listener
+ = (CallParticipantSecurityListener) listeners.next();
+
+ listener.securityMessageRecieved(evt);
+ }
+ }
+
/**
* Returns a string representation of the participant in the form of
*
@@ -252,4 +407,46 @@ public boolean isMute()
{
return false;
}
+
+ /**
+ * Sets the security status for this call participant.
+ *
+ * @param isSecurityOn true to indicate that the security is
+ * turned on and false - otherwise.
+ * @param sessionType the type of the call session - audio or video.
+ */
+ public void setSecurityOn( boolean isSecurityOn,
+ String sessionType,
+ String cipher,
+ String securityString,
+ boolean isVerified)
+ {
+ if (isSecurityOn)
+ fireCallParticipantSecurityOnEvent(
+ sessionType,
+ cipher,
+ securityString,
+ isVerified);
+ }
+
+ public void setSecurityOff(String sessionType)
+ {
+ fireCallParticipantSecurityOffEvent(sessionType);
+ }
+
+ /**
+ * Sets the security message associated with a failure/warning or
+ * information coming from the encryption protocol.
+ *
+ * @param messageType the type of the message.
+ * @param message the message
+ */
+ public void setSecurityMessage( String messageType,
+ String message,
+ String i18nMessage)
+ {
+ fireCallParticipantSecurityMessageEvent(messageType,
+ message,
+ i18nMessage);
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/Call.java b/src/net/java/sip/communicator/service/protocol/Call.java
index 3cf2ae8f9..bc0428173 100644
--- a/src/net/java/sip/communicator/service/protocol/Call.java
+++ b/src/net/java/sip/communicator/service/protocol/Call.java
@@ -47,7 +47,7 @@ public abstract class Call
* be needed inside specific layers of the call securing, depending on the
* securing algorithm used
*/
- private Hashtable