package com.aionemu.packetsamurai; import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import com.aionemu.packetsamurai.logreaders.AbstractLogReader; import com.aionemu.packetsamurai.protocol.Protocol; import com.aionemu.packetsamurai.session.GameSessionTable; import com.aionemu.packetsamurai.session.TCPSession; import jpcap.PacketReceiver; import jpcap.packet.Packet; import jpcap.packet.TCPPacket; /** * * @author Ulysses R. Ribeiro * @author Gilles Duboscq * */ public class PacketHandler implements PacketReceiver { private final Captor _captor; private final Executor _asyncPacketProcessor; public PacketHandler(Captor captor) { _captor = captor; _asyncPacketProcessor = Executors.newSingleThreadExecutor(); } public void receivePacket(final Packet p) { // do processing async _asyncPacketProcessor.execute ( new Runnable() { public void run() { PacketHandler.this.processReceivedPacket(p); } } ); } public void processReceivedPacket(Packet p) { try { if (!(p instanceof TCPPacket)) return; TCPPacket tcpPacket = (TCPPacket) p; long sessionId = tcpPacket.src_port * tcpPacket.dst_port; int port; InetAddress client; InetAddress server; if (_captor.isClientAddress(tcpPacket.src_ip)) { port = tcpPacket.dst_port; client = tcpPacket.src_ip; server = tcpPacket.dst_ip; } else { port = tcpPacket.src_port; client = tcpPacket.dst_ip; server = tcpPacket.src_ip; } if (_captor instanceof FileCaptor) { FileCaptor fCaptor = (FileCaptor)_captor; TCPSession tcpSession = fCaptor.getSessionByID(sessionId); long time = (p.sec * 1000) + (p.usec / 1000); if (tcpSession == null) { System.err.println("PacketHandler : receivePacket (from FileCaptor) : New TCPSession ("+sessionId+") - Port: "+port); Protocol proto = AbstractLogReader.getLogProtocolByPort(port); if (proto != null) { tcpSession = new TCPSession(sessionId, proto, "pcap", true); tcpSession.setClientIp((Inet4Address) client); tcpSession.setServerIp((Inet4Address) server); fCaptor.addFileTCPSession(tcpSession); System.err.println("CAPTOR: "+fCaptor); tcpSession.receivePacket(tcpPacket, !_captor.isClientAddress(tcpPacket.src_ip), time); } else { //XXX future packets of this sessionid, will once again try to create the session //we should somehow "ban" the session PacketSamurai.getUserInterface().log("PCapReader: ERROR: No protocol specified."); } } else { tcpSession.receivePacket(tcpPacket, !_captor.isClientAddress(tcpPacket.src_ip), time); } } else { if ((tcpPacket.fin || tcpPacket.rst) && !GameSessionTable.getInstance().sessionExists(sessionId)) return; if (!GameSessionTable.getInstance().sessionExists(sessionId)) { try { TCPSession session = GameSessionTable.getInstance().newGameSession(sessionId, port, server, client); session.receivePacket(tcpPacket, !_captor.isClientAddress(tcpPacket.src_ip)); } catch (IOException e) { PacketSamurai.getUserInterface().log("ERROR: Failed to create new Log Session, an I/O error occurred when creating the respective log file."); } catch (IllegalStateException e) { PacketSamurai.getUserInterface().log(e.getMessage()); } } else { GameSessionTable.getInstance().getSession(sessionId).receivePacket(tcpPacket, !_captor.isClientAddress(tcpPacket.src_ip)); } } } catch (Throwable t) { /* * If this methods throws an exception when called by a native jpcap method (ie loopPacket) * i do get a full JVM crash (EXCEPTION_ACCESS_VIOLATION) * thus im enclosing it on a try as a way to increase the logger stability */ PacketSamurai.getUserInterface().log("SEVERE: ERROR: Please report the exception trace, the logger will attempt to proceed through. ("+t.toString()+")"); t.printStackTrace(); } } }