Package org.jmule.core.networkmanager

Source Code of org.jmule.core.networkmanager.PacketReader

/*
*  JMule - Java file sharing client
*  Copyright (C) 2007-2009 JMule team ( jmule@jmule.org / http://jmule.org )
*
*  Any parts of this program derived from other projects, or contributed
*  by third-party developers are copyrighted by their respective authors.
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
*/
package org.jmule.core.networkmanager;

import static org.jmule.core.edonkey.E2DKConstants.FT_FILERATING;
import static org.jmule.core.edonkey.E2DKConstants.OP_ANSWERSOURCES;
import static org.jmule.core.edonkey.E2DKConstants.OP_CHATCAPTCHAREQ;
import static org.jmule.core.edonkey.E2DKConstants.OP_CHATCAPTCHARES;
import static org.jmule.core.edonkey.E2DKConstants.OP_COMPRESSEDPART;
import static org.jmule.core.edonkey.E2DKConstants.OP_EMULEHELLOANSWER;
import static org.jmule.core.edonkey.E2DKConstants.OP_EMULE_HELLO;
import static org.jmule.core.edonkey.E2DKConstants.OP_EMULE_QUEUERANKING;
import static org.jmule.core.edonkey.E2DKConstants.OP_END_OF_DOWNLOAD;
import static org.jmule.core.edonkey.E2DKConstants.OP_FILEREQANSNOFILE;
import static org.jmule.core.edonkey.E2DKConstants.OP_FILEREQANSWER;
import static org.jmule.core.edonkey.E2DKConstants.OP_FILEREQUEST;
import static org.jmule.core.edonkey.E2DKConstants.OP_FILESTATREQ;
import static org.jmule.core.edonkey.E2DKConstants.OP_FILESTATUS;
import static org.jmule.core.edonkey.E2DKConstants.OP_GLOBSERVSTATUS;
import static org.jmule.core.edonkey.E2DKConstants.OP_HASHSETANSWER;
import static org.jmule.core.edonkey.E2DKConstants.OP_HASHSETREQUEST;
import static org.jmule.core.edonkey.E2DKConstants.OP_MESSAGE;
import static org.jmule.core.edonkey.E2DKConstants.OP_PEERHELLO;
import static org.jmule.core.edonkey.E2DKConstants.OP_PEERHELLOANSWER;
import static org.jmule.core.edonkey.E2DKConstants.OP_REQUESTPARTS;
import static org.jmule.core.edonkey.E2DKConstants.OP_REQUESTSOURCES;
import static org.jmule.core.edonkey.E2DKConstants.OP_SENDINGPART;
import static org.jmule.core.edonkey.E2DKConstants.OP_SERVERLIST;
import static org.jmule.core.edonkey.E2DKConstants.OP_SERVER_DESC_ANSWER;
import static org.jmule.core.edonkey.E2DKConstants.OP_SLOTGIVEN;
import static org.jmule.core.edonkey.E2DKConstants.OP_SLOTRELEASE;
import static org.jmule.core.edonkey.E2DKConstants.OP_SLOTREQUEST;
import static org.jmule.core.edonkey.E2DKConstants.OP_SLOTTAKEN;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_CALLBACKFAILED;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_CALLBACKREQUESTED;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_SRVFOUNDSOURCES;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_SRVIDCHANGE;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_SRVMESSAGE;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_SRVSEARCHRESULT;
import static org.jmule.core.edonkey.E2DKConstants.PACKET_SRVSTATUS;
import static org.jmule.core.edonkey.E2DKConstants.PROTO_EDONKEY_PEER_UDP;
import static org.jmule.core.edonkey.E2DKConstants.PROTO_EDONKEY_SERVER_UDP;
import static org.jmule.core.edonkey.E2DKConstants.PROTO_EDONKEY_TCP;
import static org.jmule.core.edonkey.E2DKConstants.PROTO_EMULE_COMPRESSED_TCP;
import static org.jmule.core.edonkey.E2DKConstants.PROTO_EMULE_EXTENDED_TCP;
import static org.jmule.core.edonkey.E2DKConstants.SERVER_SEARCH_RATIO;
import static org.jmule.core.utils.Misc.getByteBuffer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.zip.DataFormatException;

import org.jmule.core.configmanager.ConfigurationManager;
import org.jmule.core.configmanager.ConfigurationManagerException;
import org.jmule.core.configmanager.ConfigurationManagerSingleton;
import org.jmule.core.downloadmanager.FileChunk;
import org.jmule.core.edonkey.ClientID;
import org.jmule.core.edonkey.E2DKConstants;
import org.jmule.core.edonkey.FileHash;
import org.jmule.core.edonkey.PartHashSet;
import org.jmule.core.edonkey.UserHash;
import org.jmule.core.edonkey.E2DKConstants.ServerFeatures;
import org.jmule.core.edonkey.packet.tag.Tag;
import org.jmule.core.edonkey.packet.tag.TagList;
import org.jmule.core.edonkey.packet.tag.TagScanner;
import org.jmule.core.edonkey.utils.Utils;
import org.jmule.core.jkad.JKadConstants;
import org.jmule.core.jkad.packet.KadPacket;
import org.jmule.core.peermanager.InternalPeerManager;
import org.jmule.core.peermanager.PeerManagerSingleton;
import org.jmule.core.searchmanager.SearchResultItem;
import org.jmule.core.searchmanager.SearchResultItemList;
import org.jmule.core.sharingmanager.JMuleBitSet;
import org.jmule.core.uploadmanager.FileChunkRequest;
import org.jmule.core.utils.Convert;
import org.jmule.core.utils.JMuleZLib;
import org.jmule.core.utils.Misc;

/**
* Created on Aug 16, 2009
* @author binary256
* @author javajox
* @version $Revision: 1.21 $
* Last changed by $Author: binary255 $ on $Date: 2010/01/12 14:45:16 $
*/
public class PacketReader {

  public static void readServerPacket(JMuleSocketChannel channel)
      throws JMEndOfStreamException, IOException, DataFormatException,
      UnknownPacketException, MalformattedPacketException,
      MalformattedPacketException {
    InternalNetworkManager _network_manager = (InternalNetworkManager) NetworkManagerSingleton
        .getInstance();

    ByteBuffer header_buffer;

    header_buffer = Misc.getByteBuffer(1);

    channel.read(header_buffer);

    byte packet_header = header_buffer.get(0);

    ByteBuffer packet_length = Misc.getByteBuffer(4);
    channel.read(packet_length);

    ByteBuffer packet_opcode_buffer = Misc.getByteBuffer(1);
    channel.read(packet_opcode_buffer);

    byte packet_opcode = packet_opcode_buffer.get(0);

    int packet_length_proto = packet_length.getInt(0);

    if ((packet_length_proto >= E2DKConstants.MAXPACKETSIZE)
        || (packet_length_proto <= 0))
      throw new MalformattedPacketException("Invalid packet length "
          + " Header :" + Convert.byteToHex(packet_header)
          + " Packet opcode : " + packet_opcode + " Length : "
          + packet_length_proto);

    ByteBuffer packet_data = Misc.getByteBuffer(packet_length_proto - 1);
    channel.read(packet_data);
    packet_data.position(0);

    if (packet_header == PROTO_EMULE_COMPRESSED_TCP) {
      packet_data = JMuleZLib.decompressData(packet_data);
      packet_header = PROTO_EDONKEY_TCP;
      packet_data.position(0);
    }

    if (packet_header != PROTO_EDONKEY_TCP) {
      throw new UnknownPacketException(packet_header, packet_opcode,
          packet_data.array());
    }
    try {
      switch (packet_opcode) {
      case PACKET_SRVMESSAGE: {
        String server_message = readString(packet_data);
        _network_manager.receivedMessageFromServer(server_message);

        return;
      }
      case PACKET_SRVIDCHANGE: {
        byte client_id[] = new byte[4];
        packet_data.get(client_id);
        ClientID clientID = new ClientID(client_id);
        int server_features = packet_data.getInt();
        Set<ServerFeatures> features = Utils
            .scanTCPServerFeatures(server_features);
        _network_manager.receivedIDChangeFromServer(clientID, features);
        return;
      }
      case PACKET_SRVSTATUS: {
        int user_count = packet_data.getInt();
        int file_count = packet_data.getInt();
        _network_manager.receivedServerStatus(user_count, file_count);
        return;
      }

      case OP_SERVERLIST: {
        int server_count = packet_data.get();
        List<String> ip_list = new LinkedList<String>();
        List<Integer> port_list = new LinkedList<Integer>();
        for (int i = 0; i < server_count; i++) {
          byte address[] = new byte[4];
          int port;

          packet_data.get(address);
          port = Convert.shortToInt(packet_data.getShort());
          ip_list.add(Convert.IPtoString(address));
          port_list.add(port);
        }

        _network_manager.receivedServerList(ip_list, port_list);
        return;
      }

      case PACKET_SRVSEARCHRESULT: {
        int result_count = packet_data.getInt();
        SearchResultItemList searchResults = new SearchResultItemList();
        for (int i = 0; i < result_count; i++) {
          byte fileHash[] = new byte[16];
          packet_data.get(fileHash);

          byte clientID[] = new byte[4];
          packet_data.get(clientID);

          short clientPort = packet_data.getShort();

          SearchResultItem result = new SearchResultItem(
              new FileHash(fileHash), new ClientID(clientID),
              clientPort);
          int tag_count = packet_data.getInt();

          for (int j = 0; j < tag_count; j++) {
            Tag tag = TagScanner.scanTag(packet_data);
            result.addTag(tag);
          }
          // transform Server's file rating into eMule file rating
          if (result.hasTag(FT_FILERATING)) {
            Tag tag = result.getTag(FT_FILERATING);
            try {
              int data = (Integer) tag.getValue();
              data = Convert.byteToInt(Misc.getByte(data, 0));
              int rating_value = data / SERVER_SEARCH_RATIO;
              tag.setValue(rating_value);
            } catch (Throwable e) {
              e.printStackTrace();
            }
          }
          searchResults.add(result);

        }
        _network_manager.receivedSearchResult(searchResults);
        return;
      }

      case PACKET_SRVFOUNDSOURCES: {
        byte[] file_hash = new byte[16];
        packet_data.get(file_hash);

        int source_count = Convert.byteToInt(packet_data.get());
        List<String> client_ip_list = new LinkedList<String>();
        List<Integer> port_list = new LinkedList<Integer>();

        byte[] peerID = new byte[4];
        int peerPort;
        ByteBuffer data = Misc.getByteBuffer(4);
        for (int i = 0; i < source_count; i++) {
          for (int j = 0; j < 4; j++) {
            data.clear();
            data.rewind();
            byte b = packet_data.get();
            data.put(b);
            peerID[j] = Convert.intToByte(data.getInt(0));
          }

          byte[] portArray = new byte[2];
          packet_data.get(portArray);

          ByteBuffer tmpData = Misc.getByteBuffer(4);
          tmpData.put(portArray);
          tmpData.position(0);
          peerPort = tmpData.getInt();

          ClientID cid = new ClientID(peerID);
          // if (PeerManagerFactory.getInstance().hasPeer(cid))
          // continue;
          // if (PeerManagerFactory.getInstance().isFull()) continue;
          client_ip_list.add(cid.getAsString());
          port_list.add(peerPort);
        }
        _network_manager.receivedSourcesFromServer(new FileHash(
            file_hash), client_ip_list, port_list);
        return;
      }

      case PACKET_CALLBACKREQUESTED: {
        byte[] ip_address = new byte[4];
        int port;

        packet_data.get(ip_address);

        port = Convert.shortToInt(packet_data.getShort());

        _network_manager.receivedCallBackRequest(Convert
            .IPtoString(ip_address), port);

        return;
      }

      case PACKET_CALLBACKFAILED: {
        _network_manager.receivedCallBackFailed();
        return;
      }
      default:
        throw new UnknownPacketException(packet_header, packet_opcode,
            packet_data.array());
      }
    } catch (Throwable cause) {
      if (cause instanceof UnknownPacketException)
        throw (UnknownPacketException) cause;
      throw new MalformattedPacketException(packet_data.array(), cause);
    }
  }

  public static void readPeerPacket(JMuleSocketChannel channel, int usePort)
      throws JMEndOfStreamException, IOException, DataFormatException,
      UnknownPacketException, MalformattedPacketException {
    ByteBuffer data2;

    channel.transferred_bytes = 0;

    data2 = Misc.getByteBuffer(1);
    channel.read(data2);
    byte packet_header = data2.get(0);
    InternalNetworkManager _network_manager = (InternalNetworkManager) NetworkManagerSingleton
        .getInstance();
    InternalPeerManager _peer_manager = (InternalPeerManager) PeerManagerSingleton
        .getInstance();

    int peerPort = channel.getChannel().socket().getPort();
    String peerIP = Convert.IPtoString(channel.getChannel().socket()
        .getInetAddress().getAddress());

    if (usePort != 0)
      peerPort = usePort;

    ByteBuffer packet_length = Misc.getByteBuffer(4);
    channel.read(packet_length);

    ByteBuffer packet_opcode_buffer = Misc.getByteBuffer(1);
    channel.read(packet_opcode_buffer);

    byte packet_opcode = packet_opcode_buffer.get(0);

    int pkLength = packet_length.getInt(0);

    if ((pkLength >= E2DKConstants.MAXPACKETSIZE) || (pkLength <= 0))
      throw new MalformattedPacketException("Invalid packet length "
          + " Header :" + Convert.byteToHex(packet_header)
          + " Packet opcode : " + packet_opcode + " Length : "
          + pkLength);

    ByteBuffer packet_data = Misc.getByteBuffer(pkLength - 1);
    channel.read(packet_data);
    packet_data.position(0);

    if (packet_header == PROTO_EMULE_COMPRESSED_TCP) {
      packet_data = JMuleZLib.decompressData(packet_data);
      packet_data.position(0);
      packet_header = PROTO_EDONKEY_TCP;
    }
    // System.out.println("Peer packet from : " + peerIP + " : " + peerPort
    // +" Header : " + Convert.byteToHex(packet_header) + " opcode : " +
    // Convert.byteToHex(packet_opcode));
    try {
      if (packet_header == PROTO_EDONKEY_TCP)
        switch (packet_opcode) {
        case OP_PEERHELLO: {
          byte[] data = new byte[16];
          packet_data.get(); // skip user hash's length
          packet_data.get(data);
          UserHash userHash = new UserHash(data);

          byte client_id[] = new byte[4];
          packet_data.get(client_id);
          ClientID clientID = new ClientID(client_id);

          int tcpPort = Convert.shortToInt(packet_data.getShort());

          TagList tag_list = readTagList(packet_data);

          byte[] server_ip_array = new byte[4];
          packet_data.get(server_ip_array);
          String server_ip = Convert.IPtoString(server_ip_array);
          int server_port;
          server_port = Convert.shortToInt(packet_data.getShort());

          _network_manager.receivedHelloFromPeerAndRespondTo(peerIP,
              peerPort, userHash, clientID, tcpPort, tag_list,
              server_ip, server_port);

          break;
        }

        case OP_PEERHELLOANSWER: {
          byte[] data = new byte[16];
          packet_data.get(data);
          UserHash userHash = new UserHash(data);

          byte client_id[] = new byte[4];
          packet_data.get(client_id);
          ClientID clientID = new ClientID(client_id);

          int tcpPort = Convert.shortToInt(packet_data.getShort());

          TagList tag_list = readTagList(packet_data);

          byte[] server_ip_array = new byte[4];
          packet_data.get(server_ip_array);
          String server_ip = Convert.IPtoString(server_ip_array);
          int server_port;
          server_port = Convert.shortToInt(packet_data.getShort());

          _network_manager.receivedHelloAnswerFromPeer(peerIP,
              peerPort, userHash, clientID, tcpPort, tag_list,
              server_ip, server_port);

          break;
        }

        case OP_SENDINGPART: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          long chunk_start = Convert.intToLong(packet_data.getInt());
          long chunk_end = Convert.intToLong(packet_data.getInt());
          ByteBuffer chunk_content = Misc.getByteBuffer(chunk_end
              - chunk_start);
          packet_data.get(chunk_content.array());
          _network_manager.receivedRequestedFileChunkFromPeer(peerIP,
              peerPort, new FileHash(file_hash), new FileChunk(
                  chunk_start, chunk_end, chunk_content));

          break;
        }

        case OP_REQUESTPARTS: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          long[] startPos = new long[3];
          long[] endPos = new long[3];
          List<FileChunkRequest> chunks = new LinkedList<FileChunkRequest>();
          for (int i = 0; i < 3; i++)
            startPos[i] = Convert.intToLong(packet_data.getInt());

          for (int i = 0; i < 3; i++)
            endPos[i] = Convert.intToLong(packet_data.getInt());

          for (int i = 0; i < 3; i++) {
            if ((startPos[i] == endPos[i]) && (startPos[i] == 0))
              break;
            chunks
                .add(new FileChunkRequest(startPos[i],
                    endPos[i]));
          }

          _network_manager.receivedFileChunkRequestFromPeer(peerIP,
              peerPort, new FileHash(file_hash), chunks);

          break;
        }

        case OP_END_OF_DOWNLOAD: {
          _network_manager.receivedEndOfDownloadFromPeer(peerIP,
              peerPort);
          break;
        }

        case OP_HASHSETREQUEST: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);

          _network_manager.receivedHashSetRequestFromPeer(peerIP,
              peerPort, new FileHash(file_hash));
          break;
        }

        case OP_HASHSETANSWER: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          int partCount = Convert.shortToInt(packet_data.getShort());
          PartHashSet partSet = new PartHashSet(new FileHash(
              file_hash));
          byte[] partHash = new byte[16];

          for (short i = 1; i <= partCount; i++) {
            packet_data.get(partHash);
            partSet.add(partHash);
          }
          _network_manager.receivedHashSetResponseFromPeer(peerIP,
              peerPort, partSet);
          break;
        }

        case OP_SLOTREQUEST: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          _network_manager.receivedSlotRequestFromPeer(peerIP,
              peerPort, new FileHash(file_hash));
          break;
        }

        case OP_SLOTGIVEN: {
          _network_manager
              .receivedSlotGivenFromPeer(peerIP, peerPort);
          break;
        }

        case OP_SLOTRELEASE: {
          _network_manager.receivedSlotReleaseFromPeer(peerIP,
              peerPort);
          break;
        }

        case OP_SLOTTAKEN: {
          _network_manager
              .receivedSlotTakenFromPeer(peerIP, peerPort);
          break;
        }

        case OP_FILEREQUEST: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);

          _network_manager.receivedFileRequestFromPeer(peerIP,
              peerPort, new FileHash(file_hash));
          break;
        }

        case OP_FILEREQANSWER: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          int name_length = Convert
              .shortToInt(packet_data.getShort());
          ByteBuffer str_bytes = Misc.getByteBuffer(name_length);
          packet_data.get(str_bytes.array());
          _network_manager.receivedFileRequestAnswerFromPeer(peerIP,
              peerPort, new FileHash(file_hash), new String(
                  str_bytes.array()));
          break;
        }

        case OP_FILEREQANSNOFILE: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);

          _network_manager.receivedFileNotFoundFromPeer(peerIP,
              peerPort, new FileHash(file_hash));
          break;
        }

        case OP_FILESTATREQ: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);

          _network_manager.receivedFileStatusRequestFromPeer(peerIP,
              peerPort, new FileHash(file_hash));

          break;
        }

        case OP_FILESTATUS: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);
          short partCount = packet_data.getShort();
          int count = (partCount + 7) / 8;
          // if (((partCount + 7) / 8) != 0)
          // if (count == 0)
          // count++;

          byte[] data = new byte[count];
          for (int i = 0; i < count; i++)
            data[i] = packet_data.get();

          JMuleBitSet bitSet;
          bitSet = Convert.byteToBitset(data);
          bitSet.setPartCount(partCount);

          _network_manager.receivedFileStatusResponseFromPeer(peerIP,
              peerPort, new FileHash(file_hash), bitSet);
          break;
        }

        case OP_MESSAGE: {
          int message_length = Convert.shortToInt(packet_data
              .getShort());
          ByteBuffer message_bytes = Misc
              .getByteBuffer(message_length);
          packet_data.get(message_bytes.array());
          String message = new String(message_bytes.array());
          message_bytes.clear();
          message_bytes = null;
          _peer_manager.receivedMessage(peerIP, peerPort, message);
          break;
        }

        default: {
          throw new UnknownPacketException(packet_header,
              packet_opcode, packet_data.array());
        }
        }
      else if (packet_header == PROTO_EMULE_EXTENDED_TCP)
        switch (packet_opcode) {
        case OP_EMULE_HELLO: {
          byte client_version = packet_data.get();
          byte protocol_version = packet_data.get();
          TagList tag_list = readTagList(packet_data);
          _network_manager.receivedEMuleHelloFromPeer(peerIP,
              peerPort, client_version, protocol_version,
              tag_list);
          break;
        }

        case OP_EMULEHELLOANSWER: {
          byte client_version = packet_data.get();
          byte protocol_version = packet_data.get();
          TagList tag_list = readTagList(packet_data);
          _network_manager.receivedEMuleHelloAnswerFromPeer(peerIP,
              peerPort, client_version, protocol_version,
              tag_list);
          break;
        }

        case OP_COMPRESSEDPART: {
          byte[] file_hash = new byte[16];
          packet_data.get(file_hash);

          long chunkStart = Convert.intToLong(packet_data.getInt());
          long chunkEnd = Convert.intToLong(packet_data.getInt());
          long compressedSize = packet_data.capacity()
              - packet_data.position();
          ByteBuffer data = Misc.getByteBuffer(compressedSize);
          packet_data.get(data.array());

          _network_manager.receivedCompressedFileChunkFromPeer(
              peerIP, peerPort, new FileHash(file_hash),
              new FileChunk(chunkStart, chunkEnd, data));
          break;
        }

        case OP_EMULE_QUEUERANKING: {
          short queue_rank = packet_data.getShort();
          _network_manager.receivedQueueRankFromPeer(peerIP,
              peerPort, Convert.shortToInt(queue_rank));
          break;
        }

        case OP_REQUESTSOURCES: {
          byte[] hash = new byte[16];
          packet_data.get(hash);
          _network_manager.receivedSourcesRequestFromPeer(peerIP,
              peerPort, new FileHash(hash));
          break;
        }

        case OP_ANSWERSOURCES: {
          byte[] hash = new byte[16];
          packet_data.get(hash);
          int source_count = Convert.shortToInt(packet_data
              .getShort());
          List<String> ip_list = new ArrayList<String>();
          List<Integer> port_list = new ArrayList<Integer>();
          byte[] ip = new byte[4];
          short port;
          for (int k = 0; k < source_count; k++) {
            packet_data.get(ip);
            port = packet_data.getShort();
            ip = Convert.reverseArray(ip);

            ip_list.add(Convert.IPtoString(ip));
            port_list.add(Convert.shortToInt(port));
          }
          _network_manager.receivedSourcesAnswerFromPeer(peerIP,
              peerPort, new FileHash(hash), ip_list, port_list);
          break;
        }

        case OP_CHATCAPTCHAREQ: {
          packet_data.get();

          ByteBuffer image_data = Misc.getByteBuffer(pkLength - 2);
          image_data.position(0);
          packet_data.get(image_data.array());
          image_data.position(0);
          _peer_manager.receivedCaptchaImage(peerIP, peerPort,
              image_data);
          break;
        }

        case OP_CHATCAPTCHARES: {
          byte response = packet_data.get();
          _peer_manager.receivedCaptchaStatusAnswer(peerIP, peerPort,
              response);
          break;
        }

        default: {
          throw new UnknownPacketException(packet_header,
              packet_opcode, packet_data.array());
        }
        }
    } catch (Throwable cause) {
      if (cause instanceof UnknownPacketException)
        throw (UnknownPacketException) cause;
      throw new MalformattedPacketException(packet_header,
          (packet_opcode), packet_data.array(), cause);
    }
    if ((packet_opcode == OP_SENDINGPART)
        || (packet_opcode == OP_COMPRESSEDPART)) {
      channel.file_transfer_trafic
          .addReceivedBytes(channel.transferred_bytes);
    } else {
      channel.service_trafic.addReceivedBytes(channel.transferred_bytes);
    }
    packet_data = null;
  }

  private static ByteBuffer packetBuffer = Misc
      .getByteBuffer(ConfigurationManager.MAX_UDP_PACKET_SIZE);

  private enum PacketType {
    SERVER_UDP, PEER_UDP, KAD, KAD_COMPRESSED
  };

  public static void readUDPPacket(DatagramChannel channel)
      throws NetworkManagerException, UnknownPacketException,
      MalformattedPacketException {

    InetSocketAddress packetSender;
    boolean kad_enabled = false;
    PacketType type;
    ByteBuffer packet_content;
    try {
      kad_enabled = ConfigurationManagerSingleton.getInstance()
          .isJKadAutoconnectEnabled();
    } catch (ConfigurationManagerException cause) {
      cause.printStackTrace();
    }
    try {
      packetBuffer.clear();
      packetSender = (InetSocketAddress) channel.receive(packetBuffer);
      packet_content = getByteBuffer(packetBuffer.position());

      packetBuffer.limit(packetBuffer.position());
      packetBuffer.position(0);
      packet_content.position(0);
      packet_content.put(packetBuffer);

      packet_content.position(0);

      if (packet_content.get(0) == PROTO_EDONKEY_SERVER_UDP)
        type = PacketType.SERVER_UDP;
      else if (packet_content.get(0) == PROTO_EDONKEY_PEER_UDP)
        type = PacketType.PEER_UDP;
      else if (packet_content.get(0) == JKadConstants.PROTO_KAD_UDP) {
        if (!kad_enabled)
          return;
        type = PacketType.KAD;
      } else if (packet_content.get(0) == JKadConstants.PROTO_KAD_COMPRESSED_UDP) {
        if (!kad_enabled)
          return;
        type = PacketType.KAD_COMPRESSED;
      } else
        throw new NetworkManagerException(
            "Unknown UDP packet header : "
                + Convert.byteToHex(packet_content.get(0)));
    } catch (Throwable cause) {
      throw new NetworkManagerException(Misc.getStackTrace(cause));
    }

    InternalNetworkManager _network_manager = (InternalNetworkManager) NetworkManagerSingleton
        .getInstance();

    if ((type == PacketType.KAD) || (type == PacketType.KAD_COMPRESSED)) {
      _network_manager.receiveKadPacket(new KadPacket(packet_content,
          packetSender));
      return;
    }

    byte packet_protocol = packet_content.get(0);

    byte packet_op_code = packet_content.get(1);

    packet_content.position(1 + 1);

    String ip = packetSender.getAddress().getHostAddress();
    int port = packetSender.getPort();

    // System.out.println("UDP Packet  " + ip + ":" + port + " Protocol : "
    // + Convert.byteToHex(packet_protocol)+"  OpCode : " +
    // Convert.byteToHex(packet_op_code));
    try {
      switch (packet_protocol) {
      case PROTO_EDONKEY_SERVER_UDP: {
        switch (packet_op_code) {
        case OP_GLOBSERVSTATUS: {
          if (packet_content.capacity() < 15) {
            int challenge = packet_content.getInt();
            long user_count = Convert.intToLong(packet_content
                .getInt());
            long files_count = Convert.intToLong(packet_content
                .getInt());
            _network_manager.receivedOldServerStatus(ip, port,
                challenge, user_count, files_count);
            return;
          }
          int challenge = packet_content.getInt();
          long user_count = Convert
              .intToLong(packet_content.getInt());
          long files_count = Convert.intToLong(packet_content
              .getInt());
          long soft_limit = Convert
              .intToLong(packet_content.getInt());
          long hard_limit = Convert
              .intToLong(packet_content.getInt());
          int udp_flags = packet_content.getInt();
          Set<ServerFeatures> server_features = Utils
              .scanUDPFeatures(udp_flags);
          _network_manager.receivedServerStatus(ip, port, challenge,
              user_count, files_count, soft_limit, hard_limit,
              server_features);
          return;
        }
        case OP_SERVER_DESC_ANSWER: {
          boolean new_packet = false;
          short test_short = packet_content.getShort();
          test_short = packet_content.getShort();
          byte[] test_read = Convert.shortToByte(test_short);
          if (test_read[0] == (byte) 0xFF)
            if (test_read[1] == (byte) 0xFF) {
              new_packet = true;
            }
          packet_content.position(packet_content.position() - 4);
          if (new_packet) {
            int challenge = packet_content.getInt();
            TagList tag_list = readTagList(packet_content);
            _network_manager.receivedNewServerDescription(ip, port,
                challenge, tag_list);
            return;
          }
          String server_name = readString(packet_content);
          String server_desc = readString(packet_content);
          _network_manager.receivedServerDescription(ip, port,
              server_name, server_desc);
          return;
        }

        default: {
          throw new UnknownPacketException(packet_protocol,
              packet_op_code, packet_content.array());
        }
        }
      }
      }
    } catch (Throwable cause) {
      if (cause instanceof UnknownPacketException)
        throw (UnknownPacketException) cause;
      throw new MalformattedPacketException(packet_content.array(), cause);
    }
  }

  private static TagList readTagList(ByteBuffer packet) {
    int tag_count = packet.getInt();
    TagList tag_list = new TagList();
    for (int i = 0; i < tag_count; i++) {
      Tag Tag = TagScanner.scanTag(packet);
      tag_list.addTag(Tag);
    }
    return tag_list;
  }

  public static String readString(ByteBuffer packet) {
    int message_length = (packet.getShort());
    ByteBuffer bytes = Misc.getByteBuffer(message_length);
    bytes.position(0);
    for (int i = 0; i < message_length; i++)
      bytes.put(packet.get());
    return new String(bytes.array());
  }

}
TOP

Related Classes of org.jmule.core.networkmanager.PacketReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.