package com.aionemu.packetsamurai.session; import com.aionemu.packetsamurai.PacketSamurai; import com.aionemu.packetsamurai.protocol.Protocol; import com.aionemu.packetsamurai.session.packetbuffer.DefaultPacketBuffer; import com.aionemu.packetsamurai.session.packetbuffer.PacketBuffer; import jpcap.packet.TCPPacket; /** * @author Ulysses R. Ribeiro * */ public class TCPSession extends Session { private PacketBuffer _csPacketBuffer; private PacketBuffer _scPacketBuffer; private TCPPacketBuffer _scTCPPacketBuffer = new TCPPacketBuffer(); private TCPPacketBuffer _csTCPPacketBuffer = new TCPPacketBuffer(); public TCPSession(long sessionId, Protocol protocol, String prefix, boolean crypted) { this(sessionId, protocol, prefix, crypted, true); } public TCPSession(long sessionId, Protocol protocol, String prefix, boolean crypted, boolean decrypt) { super(sessionId, protocol, prefix, crypted, decrypt); this.initBuffers(); } private void initBuffers() { String pBufType = this.getProtocol().getPacketBufferType(); Class<?> clazz = null; try { clazz = Class.forName("com.aionemu.packetsamurai.session.packetbuffer."+pBufType); if(clazz == null) { PacketSamurai.getUserInterface().log("Wrong PacketBuffer type in "+this.getProtocol().getFileName()+" defaulting to DefaultPacketBuffer"); _csPacketBuffer = new DefaultPacketBuffer(); _scPacketBuffer = new DefaultPacketBuffer(); return; } _csPacketBuffer = (PacketBuffer) clazz.newInstance(); _scPacketBuffer = (PacketBuffer) clazz.newInstance(); } catch (Exception e) { PacketSamurai.getUserInterface().log("Wrong PacketBuffer type in "+this.getProtocol().getFileName()+" defaulting to DefaultPacketBuffer"); _csPacketBuffer = new DefaultPacketBuffer(); _scPacketBuffer = new DefaultPacketBuffer(); } _csPacketBuffer.setProtocol(this.getProtocol()); _scPacketBuffer.setProtocol(this.getProtocol()); } public void receivePacket(TCPPacket p, boolean fromServer, long time) { int size; if (fromServer) { // sequence packets from server if (p.data.length > 0) { _scTCPPacketBuffer.add(p); } // ack on the other side _csTCPPacketBuffer.ack(p); // process pos ack for (TCPPacket packet : _csTCPPacketBuffer.getSequencedPackets()) { _csPacketBuffer.addData(packet.data); while ((size = _csPacketBuffer.nextAvaliablePacket()) > 0) { byte[] header = new byte[2]; byte[] packetData = new byte[size]; _csPacketBuffer.getNextPacket(header, packetData); //System.out.println("TCPSession : receivePacket : New Full Packet (ClientPacket) size="+size+" time="+time); this.addPacket(packetData, !fromServer,time); } } _csTCPPacketBuffer.flush(); } else //from client { // sequence packets from server if (p.data.length > 0) { _csTCPPacketBuffer.add(p); } // ack on the other side _scTCPPacketBuffer.ack(p); // process pos ack for (TCPPacket packet : _scTCPPacketBuffer.getSequencedPackets()) { if (packet.data.length > 0) { _scPacketBuffer.addData(packet.data); while ((size = _scPacketBuffer.nextAvaliablePacket()) > 0) { byte[] header = new byte[2]; byte[] packetData = new byte[size]; _scPacketBuffer.getNextPacket(header, packetData); //System.out.println("TCPSession : receivePacket : New Full Packet (ServerPacket) size="+size+" time="+time); this.addPacket(packetData, !fromServer,time); } } // Connection end? if (packet.fin || packet.rst) { PacketSamurai.getUserInterface().log("[S -> C] TCP Sequencing Buffer Report: Pending: "+_scTCPPacketBuffer.getPendingSequencePackets()); PacketSamurai.getUserInterface().log("[S -> C] TCP Data Buffer Report: Pending: "+_scPacketBuffer.nextAvaliablePacket()); PacketSamurai.getUserInterface().log("[C -> S] TCP Sequencing Buffer Report: Pending: "+_csTCPPacketBuffer.getPendingSequencePackets()); PacketSamurai.getUserInterface().log("[C -> S] TCP Data Buffer Report: Pending: "+_csPacketBuffer.nextAvaliablePacket()); PacketSamurai.getUserInterface().log("Connection ended. (FIN: "+packet.fin+" - RST: "+packet.rst+")"); this.saveSession(); this.close(); return; } } _scTCPPacketBuffer.flush(); } } public void receivePacket(TCPPacket p, boolean fromServer) { this.receivePacket(p, fromServer, (p.sec * 1000) + (p.usec/1000)); } public void close() { GameSessionTable.getInstance().removeGameSession(this.getSessionId()); } }