/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.protocol.jabber.debugger;
import net.java.sip.communicator.impl.protocol.jabber.*;
import org.jitsi.service.packetlogging.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.*;
/**
* The jabber packet listener that logs the packets to the packet logging
* service.
* @author Damian Minkov
*/
public class SmackPacketDebugger
implements PacketListener,
PacketInterceptor
{
/**
* The current jabber connection.
*/
private XMPPConnection connection = null;
/**
* Local address for the connection.
*/
private byte[] localAddress;
/**
* Remote address for the connection.
*/
private byte[] remoteAddress;
/**
* Instance for the packet logging service.
*/
private PacketLoggingService packetLogging = null;
/**
* Creates the SmackPacketDebugger instance.
*/
public SmackPacketDebugger()
{
packetLogging = JabberActivator.getPacketLogging();
}
/**
* Sets current connection.
* @param connection the connection.
*/
public void setConnection(XMPPConnection connection)
{
this.connection = connection;
}
/**
* Process the packet that is about to be sent to the server. The intercepted
* packet can be modified by the interceptor.<p>
* <p/>
* Interceptors are invoked using the same thread that requested the packet
* to be sent, so it's very important that implementations of this method
* not block for any extended period of time.
*
* @param packet the packet to is going to be sent to the server.
*/
public void interceptPacket(Packet packet)
{
try
{
if(packetLogging.isLoggingEnabled(
PacketLoggingService.ProtocolName.JABBER)
&& packet != null && connection.getSocket() != null)
{
if(remoteAddress == null)
{
remoteAddress = connection.getSocket()
.getInetAddress().getAddress();
localAddress = connection.getSocket()
.getLocalAddress().getAddress();
}
byte[] packetBytes;
if(packet instanceof Message)
{
packetBytes = cloneAnonyMessage(packet)
.toXML().getBytes("UTF-8");
}
else
{
packetBytes = packet.toXML().getBytes("UTF-8");
}
packetLogging.logPacket(
PacketLoggingService.ProtocolName.JABBER,
localAddress,
connection.getSocket().getLocalPort(),
remoteAddress,
connection.getPort(),
PacketLoggingService.TransportName.TCP,
true,
packetBytes
);
}
}
catch(Throwable t)
{
t.printStackTrace();
}
}
/**
* Clones if messages and process subject and bodies.
* @param packet
* @return
*/
private Message cloneAnonyMessage(Packet packet)
{
Message oldMsg = (Message)packet;
// if the message has no body, or the bodies list is empty
if(oldMsg.getBody() == null
&& (oldMsg.getBodies() == null || oldMsg.getBodies().size() == 0))
{
return oldMsg;
}
Message newMsg = new Message();
newMsg.setPacketID(packet.getPacketID());
newMsg.setTo(packet.getTo());
newMsg.setFrom(packet.getFrom());
// we don't modify them, just use existing
for(PacketExtension pex : packet.getExtensions())
newMsg.addExtension(pex);
for(String propName : packet.getPropertyNames())
newMsg.setProperty(propName, packet.getProperty(propName));
newMsg.setError(packet.getError());
newMsg.setType(oldMsg.getType());
newMsg.setThread(oldMsg.getThread());
newMsg.setLanguage(oldMsg.getLanguage());
for(Message.Subject sub : oldMsg.getSubjects())
{
if(sub.getSubject() != null)
newMsg.addSubject(sub.getLanguage(),
new String(new char[sub.getSubject().length()])
.replace('\0', '.'));
else
newMsg.addSubject(sub.getLanguage(), sub.getSubject());
}
for(Message.Body b : oldMsg.getBodies())
{
if(b.getMessage() != null)
newMsg.addBody(b.getLanguage(),
new String(new char[b.getMessage().length()])
.replace('\0', '.'));
else
newMsg.addSubject(b.getLanguage(), b.getMessage());
}
return newMsg;
}
/**
* Process the next packet sent to this packet listener.<p>
* <p/>
* A single thread is responsible for invoking all listeners, so
* it's very important that implementations of this method not block
* for any extended period of time.
*
* @param packet the packet to process.
*/
public void processPacket(Packet packet)
{
try
{
if(packetLogging.isLoggingEnabled(
PacketLoggingService.ProtocolName.JABBER)
&& packet != null && connection.getSocket() != null)
{
byte[] packetBytes;
if(packet instanceof Message)
{
packetBytes = cloneAnonyMessage(packet)
.toXML().getBytes("UTF-8");
}
else
{
packetBytes = packet.toXML().getBytes("UTF-8");
}
packetLogging.logPacket(
PacketLoggingService.ProtocolName.JABBER,
remoteAddress,
connection.getPort(),
localAddress,
connection.getSocket().getLocalPort(),
PacketLoggingService.TransportName.TCP,
false,
packetBytes
);
}
}
catch(Throwable t)
{
t.printStackTrace();
}
}
}