Package org.jmule.core.jkad

Source Code of org.jmule.core.jkad.JKadManagerImpl

/*
*  JMule - Java file sharing client
*  Copyright (C) 2007-2008 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.jkad;

import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_HELLO_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_HELLO_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_PUBLISH_KEY_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_PUBLISH_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_PUBLISH_SOURCE_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_SEARCH_KEY_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_SEARCH_NOTES_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA2_SEARCH_SOURCE_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_BOOTSTRAP_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_BOOTSTRAP_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_CALLBACK_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_FINDBUDDY_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_FIREWALLED_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_FIREWALLED_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_HELLO_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_HELLO_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_PUBLISH_NOTES_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_PUBLISH_NOTES_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_PUBLISH_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_PUBLISH_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_SEARCH_NOTES_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_SEARCH_NOTES_RES;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_SEARCH_REQ;
import static org.jmule.core.jkad.JKadConstants.KADEMLIA_SEARCH_RES;
import static org.jmule.core.jkad.JKadConstants.PROTO_KAD_UDP;
import static org.jmule.core.jkad.JKadConstants.PUBLISHER_PUBLISH_CHECK_INTERVAL;
import static org.jmule.core.jkad.JKadConstants.TAG_FILENAME;
import static org.jmule.core.jkad.JKadConstants.TAG_FILERATING;
import static org.jmule.core.jkad.JKadConstants.TAG_FILESIZE;
import static org.jmule.core.jkad.JKadConstants.TAG_SOURCEIP;
import static org.jmule.core.jkad.JKadConstants.TAG_SOURCEPORT;
import static org.jmule.core.jkad.JKadConstants.TAG_SOURCETYPE;
import static org.jmule.core.jkad.JKadManagerImpl.JKadStatus.CONNECTED;
import static org.jmule.core.jkad.JKadManagerImpl.JKadStatus.CONNECTING;
import static org.jmule.core.jkad.JKadManagerImpl.JKadStatus.DISCONNECTED;
import static org.jmule.core.jkad.utils.Utils.getRandomInt128;
import static org.jmule.core.utils.Convert.byteToHexString;
import static org.jmule.core.utils.Convert.byteToInt;
import static org.jmule.core.utils.Convert.shortToInt;
import static org.jmule.core.utils.Misc.getByteBuffer;

import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jmule.core.JMRunnable;
import org.jmule.core.JMuleAbstractManager;
import org.jmule.core.JMuleManagerException;
import org.jmule.core.configmanager.ConfigurationAdapter;
import org.jmule.core.configmanager.ConfigurationManager;
import org.jmule.core.configmanager.ConfigurationManagerException;
import org.jmule.core.configmanager.ConfigurationManagerSingleton;
import org.jmule.core.configmanager.InternalConfigurationManager;
import org.jmule.core.edonkey.FileHash;
import org.jmule.core.edonkey.packet.tag.IntTag;
import org.jmule.core.edonkey.packet.tag.StringTag;
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.jkad.JKadConstants.RequestType;
import org.jmule.core.jkad.indexer.Indexer;
import org.jmule.core.jkad.indexer.Source;
import org.jmule.core.jkad.logger.Logger;
import org.jmule.core.jkad.lookup.Lookup;
import org.jmule.core.jkad.packet.CorruptedPacketException;
import org.jmule.core.jkad.packet.KadPacket;
import org.jmule.core.jkad.packet.PacketFactory;
import org.jmule.core.jkad.packet.UnknownPacketOPCodeException;
import org.jmule.core.jkad.packet.UnknownPacketType;
import org.jmule.core.jkad.publisher.Publisher;
import org.jmule.core.jkad.routingtable.KadContact;
import org.jmule.core.jkad.routingtable.RoutingTable;
import org.jmule.core.jkad.search.Search;
import org.jmule.core.jkad.utils.Convert;
import org.jmule.core.jkad.utils.timer.Task;
import org.jmule.core.jkad.utils.timer.Timer;
import org.jmule.core.networkmanager.InternalNetworkManager;
import org.jmule.core.networkmanager.NetworkManagerException;
import org.jmule.core.networkmanager.NetworkManagerSingleton;
import org.jmule.core.peermanager.Peer;
import org.jmule.core.peermanager.PeerManagerSingleton;
import org.jmule.core.peermanager.Peer.PeerSource;
import org.jmule.core.sharingmanager.PartialFile;
import org.jmule.core.sharingmanager.SharedFile;
import org.jmule.core.sharingmanager.SharingManager;
import org.jmule.core.sharingmanager.SharingManagerSingleton;

/**
*
* Utilization :
*  Kad.getSingelton()
*  Kad.initialize()
*  Kad.connect() / Kad.connect(IP to bootstrap);
*  Kad.disconnect()
*  Kad.stop();
* Created on Dec 29, 2008
* @author binary256
* @version $Revision: 1.9 $
* Last changed by $Author: binary255 $ on $Date: 2010/01/13 18:42:15 $
*/
public class JKadManagerImpl extends JMuleAbstractManager implements
    InternalJKadManager {
  public enum JKadStatus {
    CONNECTED, CONNECTING, DISCONNECTED
  }

  private ClientID clientID;
  private RoutingTable routing_table = null;
  private Indexer indexer = null;
  private FirewallChecker firewallChecker = null;
  private BootStrap bootStrap = null;
  private Lookup lookup = null;
  private Search search = null;
  private Publisher publisher = null;
  private JKadStatus status = DISCONNECTED;
  private Map<Byte, List<PacketListener>> packetListeners = new ConcurrentHashMap<Byte, List<PacketListener>>();
  private Task filesToPublishChecker;
  private InternalConfigurationManager _config_manager = null;
  private InternalNetworkManager _network_manager = null;

  private List<JKadListener> listener_list = new LinkedList<JKadListener>();

  private boolean is_started = false;

  JKadManagerImpl() {
  }

  public void initialize() {

    try {
      super.initialize();
    } catch (JMuleManagerException e1) {
      e1.printStackTrace();
      return;
    }

    _config_manager = (InternalConfigurationManager) ConfigurationManagerSingleton
        .getInstance();
    _network_manager = (InternalNetworkManager) NetworkManagerSingleton
        .getInstance();

    Logger.getSingleton().start();
    routing_table = RoutingTable.getSingleton();
    indexer = Indexer.getSingleton();
    indexer.start();

    firewallChecker = FirewallChecker.getSingleton();
    bootStrap = BootStrap.getInstance();
    lookup = Lookup.getSingleton();
    search = Search.getSingleton();
    publisher = Publisher.getInstance();

    if (clientID == null) {
      clientID = new ClientID(getRandomInt128());
      try {
        _config_manager.setJKadClientID(clientID);
      } catch (ConfigurationManagerException e) {

        e.printStackTrace();
      }
    }

    filesToPublishChecker = new Task() {
      Set<FileHash> publishedFiles = new HashSet<FileHash>();

      public void run() {
        if (getStatus() != JKadStatus.CONNECTED) return;
        SharingManager sharing_manager = SharingManagerSingleton
            .getInstance();
        Publisher publisher = Publisher.getInstance();
        ConfigurationManager config_manager = ConfigurationManagerSingleton
            .getInstance();
        Iterable<SharedFile> shared_files = sharing_manager
            .getSharedFiles();
        long filesToPublish = 0;
        for (SharedFile file : shared_files) {
          if (publisher.getPublishKeywordCount() > JKadConstants.MAX_CONCURRENT_PUBLISH_FILES) {
            break;
          }
          if (publishedFiles.contains(file.getFileHash()))
            continue;
          if (filesToPublish > JKadConstants.ITERATION_MAX_PUBLISH_FILES)
            break;
          if (file instanceof PartialFile) {
            PartialFile p_file = (PartialFile) file;
            if (p_file.getAvailablePartCount()==0) continue;
          }
          publishedFiles.add(file.getFileHash());

          byte[] hash = file.getFileHash().getHash().clone();
          Convert.updateSearchID(hash);
          Int128 id = new Int128(hash);

          if (!publisher.isPublishingSource(id)) {
            filesToPublish++;
            List<Tag> tagList = new LinkedList<Tag>();
            tagList.add(new StringTag(TAG_FILENAME, file
                .getSharingName()));
            tagList.add(new IntTag(TAG_FILESIZE, (int) file
                .length()));
            tagList
                .add(new IntTag(TAG_SOURCEIP,
                    org.jmule.core.utils.Convert
                        .byteToInt(getIPAddress()
                            .getAddress())));
            try {
              tagList.add(new IntTag(TAG_SOURCEPORT,
                  config_manager.getTCP()));
            } catch (ConfigurationManagerException e) {
              e.printStackTrace();
            }

            publisher.publishSource(id, tagList);
          }
          if (!publisher.isPublishingKeyword(id)) {
            filesToPublish++;
            List<Tag> tagList = new LinkedList<Tag>();
            tagList.add(new StringTag(TAG_FILENAME, file
                .getSharingName()));
            tagList.add(new IntTag(TAG_FILESIZE, (int) file
                .length()));

            publisher.publishKeyword(id, tagList);
          }

          if (file.getTagList().hasTag(TAG_FILERATING))
            if (!publisher.isPublishingNote(id)) {
              filesToPublish++;
              List<Tag> tagList = new LinkedList<Tag>();
              tagList.add(new StringTag(TAG_FILENAME, file
                  .getSharingName()));
              tagList.add(new IntTag(TAG_FILESIZE, (int) file
                  .length()));
              tagList.add(new IntTag(TAG_FILERATING, file
                  .getFileQuality().getAsInt()));

              publisher.publishNote(id, tagList);
            }
        }
      }
    };

    ConfigurationManagerSingleton.getInstance().addConfigurationListener(
        new ConfigurationAdapter() {
          public void jkadStatusChanged(boolean newStatus) {
            if (newStatus == false)
              if (!isDisconnected())
                disconnect();
            if (newStatus == true)
              if (getStatus() == DISCONNECTED)
                connect();
          }
        });

  }

  public void shutdown() {
    try {
      super.shutdown();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }
    is_started = false;
    if (!isDisconnected())
      disconnect();
  }

  public void start() {
    try {
      super.start();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }

    is_started = true;
    this.connect();
  }

  protected boolean iAmStoppable() {
    return true;
  }

  public void connect() {
    setStatus(CONNECTING);
    routing_table.start();

    lookup.start();
    publisher.start();
    search.start();
    indexer.start();

    bootStrap.start();

    Timer.getSingleton().addTask(PUBLISHER_PUBLISH_CHECK_INTERVAL,
        filesToPublishChecker, true);
  }

  public void connect(ContactAddress address) {
    setStatus(CONNECTING);
    routing_table.start();

    lookup.start();
    publisher.start();
    search.start();
    indexer.start();

    bootStrap.start(address.getAddress(), address.getUDPPort());

    Timer.getSingleton().addTask(PUBLISHER_PUBLISH_CHECK_INTERVAL,
        filesToPublishChecker, true);
  }

  public void disconnect() {
    if (isDisconnected())
      return;
    Timer.getSingleton().removeTask(filesToPublishChecker);

    firewallChecker.stop();
    indexer.stop();
    search.stop();

    publisher.stop();
    lookup.stop();
    bootStrap.stop();
    routing_table.stop();

    setStatus(DISCONNECTED);
  }

  public boolean isStarted() {
    return is_started;
  }

  public void setStatus(JKadStatus newStatus) {
    if (status == CONNECTED) {
      if (!firewallChecker.isStarted())
        firewallChecker.start();
    }

    if (status != newStatus)
      notifyListeners(newStatus);

    status = newStatus;
  }

  public boolean isFirewalled() {
    return firewallChecker.isFirewalled();
  }

  public void receivePacket(KadPacket packet) {
    try {
      processPacket(packet);
    } catch (Throwable t) {
      t.printStackTrace();
      Logger.getSingleton().logException(t);
      ByteBuffer unkPacket = getByteBuffer(packet.getAsByteBuffer()
          .capacity());
      packet.getAsByteBuffer().position(0);
      packet.getAsByteBuffer().get(unkPacket.array(), 0,
          packet.getAsByteBuffer().capacity());
      Logger.getSingleton().logMessage(
          "Exception in processing : \n"
              + byteToHexString(unkPacket.array(), " "));
    }
  }

  private void processPacket(KadPacket packet)
      throws UnknownPacketOPCodeException, CorruptedPacketException,
      UnknownPacketType {
    IPAddress sender_address = new IPAddress(packet.getAddress());
    int sender_port = packet.getAddress().getPort();

    if (isDisconnected())
      return;
    if (packet.isCompressed())
      packet.decompress();

    if (packet.getProtocol() != PROTO_KAD_UDP)
      throw new UnknownPacketType();

    // update last response
    KadContact rcontact = routing_table.getContact(packet.getAddress());
    if (rcontact != null) {
      rcontact.setLastResponse(System.currentTimeMillis());
      rcontact.setConnected(true);
      rcontact.setIPVerified(true);
    }

    // notify packet listeners
    List<PacketListener> listener_list = packetListeners.get(packet
        .getCommand());
    if (listener_list != null)
      for (PacketListener listener : listener_list)
        try {
          if (listener.processAddress(packet.getAddress()))
            listener.packetReceived(packet);
        } catch (Throwable t) {
          t.printStackTrace();
          Logger.getSingleton().logException(t);
        }

    byte packetOPCode = packet.getCommand();
    ByteBuffer rawData = packet.getAsByteBuffer();
    rawData.position(2);
    boolean unknown_packet = false;
    try {
      if (packetOPCode == KADEMLIA_BOOTSTRAP_REQ) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        byte[] address = new byte[4];
        rawData.get(address);
        int udp_port = shortToInt(rawData.getShort());
        int tcp_port = shortToInt(rawData.getShort());

        bootStrap.processBootStrapReq(new ClientID(client_id_raw),
            new IPAddress(address), udp_port);
      } else if (packetOPCode == KADEMLIA_BOOTSTRAP_RES) {

        int contactCount = shortToInt(rawData.getShort());
        List<KadContact> contact_list = new LinkedList<KadContact>();
        for (int i = 0; i < contactCount; i++) {
          contact_list.add(getContact(rawData));
        }

        bootStrap.processBootStrapRes(contact_list);
      } else if (packetOPCode == KADEMLIA_HELLO_REQ) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        byte[] address = new byte[4];
        rawData.get(address);
        int udp_port = shortToInt(rawData.getShort());
        int tcp_port = shortToInt(rawData.getShort());

        KadContact contact = routing_table.getContact(new ClientID(
            client_id_raw));
        if (contact != null) {
          contact.setTCPPort(tcp_port);
          contact.setUDPPort(udp_port);

        }

        KadPacket response;
        response = PacketFactory.getHello1ResPacket();
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);

      } else if (packetOPCode == KADEMLIA_HELLO_RES) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        byte address[] = new byte[4];
        rawData.get(address);
        int udp_port = shortToInt(rawData.getShort());
        int tcp_port = shortToInt(rawData.getShort());

        KadContact contact = routing_table.getContact(new ClientID(
            client_id_raw));

        if (contact != null) {
          contact.setTCPPort(tcp_port);
          contact.setUDPPort(udp_port);
        }
        // if contact is not in routing table ignore message
        /*
         * KadContact add_contact = new KadContact(new
         * ClientID(client_id_raw), new ContactAddress(new
         * IPAddress(address),udp_port), tcp_port, (byte)0, null);
         * routing_table.addContact(add_contact);
         *
         * add_contact.setConnected(true);
         */

      } else if (packetOPCode == KADEMLIA_REQ) {
        byte type = rawData.get();

        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID targetClientID = new ClientID(client_id_raw);

        client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID receiverClientID = new ClientID(client_id_raw);
        RequestType requestType = RequestType.FIND_VALUE;
        switch (type) {
        case JKadConstants.FIND_VALUE:
          requestType = RequestType.FIND_VALUE;
          break;

        case JKadConstants.STORE:
          requestType = RequestType.STORE;
          break;

        case JKadConstants.FIND_NODE:
          requestType = RequestType.FIND_NODE;
          break;
        }
        lookup.processRequest(packet.getAddress(), requestType,
            targetClientID, receiverClientID, 1);
      } else if (packetOPCode == KADEMLIA_RES) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        int contactCount = byteToInt(rawData.get());
        List<KadContact> contact_list = new LinkedList<KadContact>();
        for (int i = 0; i < contactCount; i++) {
          contact_list.add(getContact(rawData));
        }

        lookup.processResponse(packet.getAddress(), new ClientID(
            client_id_raw), contact_list);
      } else if (packetOPCode == KADEMLIA_PUBLISH_REQ) {
        byte target_id[] = new byte[16];
        rawData.get(target_id);
        Int128 targetID = new Int128(target_id);
        int clientCount = shortToInt(rawData.getShort());

        List<Source> list = new LinkedList<Source>();

        for (int i = 0; i < clientCount; i++) {
          byte clientID[] = new byte[16];
          rawData.get(clientID);
          int tagCount = shortToInt(rawData.get());
          TagList tagList = new TagList();
          for (int k = 0; k < tagCount; k++) {
            Tag tag = TagScanner.scanTag(rawData);
            tagList.addTag(tag);
          }
          ClientID client_id = new ClientID(clientID);
          Source source = new Source(client_id, tagList);

          source.setAddress(new IPAddress(packet.getAddress()));
          source.setUDPPort(packet.getAddress().getPort());

          KadContact contact = routing_table.getContact(client_id);
          if (contact != null)
            source.setTCPPort(contact.getTCPPort());

          list.add(source);
        }

        boolean source_load = false;

        for (Source source : list) {
          boolean isSourcePublish = false;
          isSourcePublish = source.getTagList()
              .hasTag(TAG_SOURCETYPE);
          if (isSourcePublish) {
            indexer.addFileSource(targetID, source);
            source_load = true;
          } else
            indexer.addFileSource(targetID, source);
        }
        KadPacket response = null;
        if (source_load)
          response = PacketFactory.getPublishResPacket(targetID,
              indexer.getFileSourcesLoad());
        else
          response = PacketFactory.getPublishResPacket(targetID,
              indexer.getKeywordLoad());
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);

      } else if (packetOPCode == KADEMLIA_PUBLISH_RES) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        int load = byteToInt(rawData.get());
        publisher.processGenericResponse(new ClientID(targetID), load);
      } else if (packetOPCode == KADEMLIA_SEARCH_NOTES_REQ) {
        byte[] targetID = new byte[16];
        rawData.get(targetID);
        List<Source> source_list = indexer.getNoteSources(new Int128(
            targetID));
        KadPacket response = PacketFactory.getNotesRes(new Int128(
            targetID), source_list);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA_SEARCH_NOTES_RES) {
        byte[] noteID = new byte[16];
        rawData.get(noteID);
        int resultCount = shortToInt(rawData.getShort());
        List<Source> sourceList = new LinkedList<Source>();

        for (int i = 0; i < resultCount; i++) {
          byte[] clientID = new byte[16];
          rawData.get(clientID);
          Convert.updateSearchID(clientID);
          int tagCount = shortToInt(rawData.get());
          TagList tagList = new TagList();
          for (int k = 0; k < tagCount; k++) {
            Tag tag = TagScanner.scanTag(rawData);
            tagList.addTag(tag);
          }
          Source source = new Source(new ClientID(clientID), tagList);
          source.setAddress(new IPAddress(packet.getAddress()));
          source.setUDPPort(packet.getAddress().getPort());
          KadContact contact = RoutingTable.getSingleton()
              .getContact(new ClientID(clientID));
          if (contact != null)
            source.setTCPPort(contact.getTCPPort());
          sourceList.add(source);
        }
        search.processResults(packet.getAddress(), new Int128(noteID),
            sourceList);
      } else if (packetOPCode == KADEMLIA_PUBLISH_NOTES_REQ) {
        byte[] noteID = new byte[16];
        rawData.get(noteID);
        byte[] publisherID = new byte[16];
        rawData.get(publisherID);
        int tagCount = byteToInt(rawData.get());
        TagList tagList = new TagList();
        for (int i = 0; i < tagCount; i++) {
          Tag tag = TagScanner.scanTag(rawData);
          tagList.addTag(tag);
        }
        ClientID publisher_id = new ClientID(publisherID);
        Source source = new Source(publisher_id, tagList);
        source.setAddress(new IPAddress(packet.getAddress()));
        source.setUDPPort(packet.getAddress().getPort());

        KadContact contact = routing_table.getContact(publisher_id);
        if (contact != null)
          source.setTCPPort(contact.getTCPPort());

        indexer.addNoteSource(new Int128(noteID), source);
        KadPacket response = PacketFactory.getPublishNotesRes(
            new Int128(noteID), indexer.getNoteLoad());
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);

      } else if (packetOPCode == KADEMLIA_PUBLISH_NOTES_RES) {
        byte[] noteID = new byte[16];
        rawData.get(noteID);
        int load = byteToInt(rawData.get());
        publisher.processNoteResponse(new Int128(noteID), load);
      } else if (packetOPCode == KADEMLIA_SEARCH_REQ) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        boolean sourceSearch = false;
        if (rawData.limit() == 17)
          if (rawData.get() == 1)
            sourceSearch = true;
        List<Source> source_list;

        if (sourceSearch)
          source_list = indexer.getFileSources(new Int128(targetID));
        else
          source_list = indexer
              .getKeywordSources(new Int128(targetID));
        KadPacket response = PacketFactory.getSearchResPacket(
            new Int128(targetID), source_list);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA_SEARCH_RES) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        int resultCount = shortToInt(rawData.getShort());

        List<Source> sourceList = new LinkedList<Source>();

        for (int i = 0; i < resultCount; i++) {
          byte[] contactID = new byte[16];
          rawData.get(contactID);
          int tagCount = byteToInt(rawData.get());
          TagList tagList = new TagList();
          for (int k = 0; k < tagCount; k++) {
            try {
              Tag tag = TagScanner.scanTag(rawData);
              if (tag == null)
                continue;

              tagList.addTag(tag);
            } catch (Throwable t) {
              t.printStackTrace();
            }
          }
          ClientID client_id = new ClientID(contactID);
          Source source = new Source(client_id, tagList);
          KadContact contact = routing_table.getContact(client_id);
          if (contact != null) {
            source.setUDPPort(contact.getUDPPort());
            source.setTCPPort(contact.getTCPPort());
          }
          sourceList.add(source);
        }
        search.processResults(packet.getAddress(),
            new Int128(targetID), sourceList);
      } else if (packetOPCode == KADEMLIA_FIREWALLED_REQ) {
        int tcpPort = shortToInt(rawData.getShort());
        firewallChecker.processFirewallRequest(packet.getAddress(),
            tcpPort);
      } else if (packetOPCode == KADEMLIA_FIREWALLED_RES) {
        byte[] address = new byte[4];
        rawData.get(address);
        firewallChecker.porcessFirewallResponse(packet.getAddress(),
            new IPAddress(address));
      } else if (packetOPCode == KADEMLIA2_HELLO_REQ) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID clientID = new ClientID(client_id_raw);
        int tcpPort = shortToInt(rawData.getShort());
        byte version = rawData.get();
        byte tag_count = rawData.get();
        List<Tag> tag_list = new LinkedList<Tag>();
        for (byte i = 0; i < tag_count; i++) {
          Tag tag = TagScanner.scanTag(rawData);
          if (tag == null)
            throw new CorruptedPacketException();
          tag_list.add(tag);
        }

        KadContact contact = routing_table.getContact(clientID);
        if (contact != null) {
          contact.setTCPPort(tcpPort);
          contact.setUDPPort(packet.getAddress().getPort());
          contact.setVersion(version);
        }

        KadPacket response = PacketFactory
            .getHello2ResPacket(TagList.EMPTY_TAG_LIST);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA2_HELLO_RES) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID clientID = new ClientID(client_id_raw);
        int tcpPort = shortToInt(rawData.getShort());
        byte version = rawData.get();
        byte tag_count = rawData.get();
        List<Tag> tag_list = new LinkedList<Tag>();

        for (byte i = 0; i < tag_count; i++) {
          Tag tag = TagScanner.scanTag(rawData);
          if (tag == null)
            throw new CorruptedPacketException();
          tag_list.add(tag);
        }

        KadContact contact = routing_table.getContact(clientID);
        if (contact != null) {
          contact.setTCPPort(tcpPort);
          contact.setVersion(version);
        }
        // ignore message if contact is not in routing table
        /*
         * ContactAddress address = new ContactAddress(new
         * IPAddress(packet.getSender()),packet.getSender().getPort());
         * KadContact add_contact = new KadContact(clientID, address,
         * tcpPort,version, null);
         * routing_table.addContact(add_contact);
         *
         * add_contact.setConnected(true);
         */

      } else if (packetOPCode == KADEMLIA2_REQ) {
        byte type = rawData.get();

        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID targetClientID = new ClientID(client_id_raw);

        client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        ClientID receiverClientID = new ClientID(client_id_raw);
        RequestType requestType = RequestType.FIND_VALUE;
        switch (type) {
        case JKadConstants.FIND_VALUE:
          requestType = RequestType.FIND_VALUE;
          break;

        case JKadConstants.STORE:
          requestType = RequestType.STORE;
          break;

        case JKadConstants.FIND_NODE:
          requestType = RequestType.FIND_NODE;
          break;
        }

        lookup.processRequest(packet.getAddress(), requestType,
            targetClientID, receiverClientID, 2);
      } else if (packetOPCode == KADEMLIA2_RES) {
        byte[] client_id_raw = new byte[16];
        rawData.get(client_id_raw);
        int contactCount = byteToInt(rawData.get());
        List<KadContact> contact_list = new LinkedList<KadContact>();
        for (int i = 0; i < contactCount; i++) {
          contact_list.add(getContact(rawData));
        }
        lookup.processResponse(packet.getAddress(), new ClientID(
            client_id_raw), contact_list);
      } else if (packetOPCode == KADEMLIA2_PUBLISH_KEY_REQ) {
        byte[] client_id = new byte[16];
        rawData.get(client_id);
        ClientID clientID = new ClientID(client_id);
        int count = rawData.getShort();
        for (int i = 0; i < count; i++) {
          byte[] hash = new byte[16];
          rawData.get(hash);
          byte tagCount = rawData.get();
          TagList tag_list = new TagList();
          for (int j = 0; j < tagCount; j++) {
            Tag tag = TagScanner.scanTag(rawData);
            if (tag == null)
              throw new CorruptedPacketException();
            tag_list.addTag(tag);
          }
          Source source = new Source(clientID, tag_list);
          source.setAddress(new IPAddress(packet.getAddress()));
          source.setUDPPort(packet.getAddress().getPort());

          KadContact contact = routing_table.getContact(clientID);
          if (contact != null)
            source.setTCPPort(contact.getTCPPort());

          indexer.addKeywordSource(new Int128(hash), source);
        }
        KadPacket response = PacketFactory.getPublishRes2Packet(
            clientID, indexer.getKeywordLoad());
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);

      } else if (packetOPCode == KADEMLIA2_PUBLISH_RES) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        int load = byteToInt(rawData.get());
        publisher.processGenericResponse(new ClientID(targetID), load);
      } else if (packetOPCode == KADEMLIA2_PUBLISH_SOURCE_REQ) {
        byte[] client_id = new byte[16];
        byte[] source_id = new byte[16];

        rawData.get(client_id);
        rawData.get(source_id);

        int tagCount = rawData.get();
        TagList tag_list = new TagList();
        for (int i = 0; i < tagCount; i++) {
          Tag tag = TagScanner.scanTag(rawData);
          if (tag == null)
            throw new CorruptedPacketException();
          tag_list.addTag(tag);
        }
        Source source = new Source(new ClientID(client_id), tag_list);
        source.setAddress(new IPAddress(packet.getAddress()));
        source.setUDPPort(packet.getAddress().getPort());

        KadContact contact = routing_table.getContact(new ClientID(
            client_id));
        if (contact != null)
          source.setTCPPort(contact.getTCPPort());

        indexer.addFileSource(new Int128(source_id), source);

        KadPacket response = PacketFactory.getPublishRes2Packet(
            new ClientID(client_id), indexer.getFileSourcesLoad());
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA_FINDBUDDY_REQ) {
        byte[] receiver_id = new byte[16];
        byte[] sender_id = new byte[16];
        short tcp_port;

        rawData.get(receiver_id);
        rawData.get(sender_id);
        tcp_port = rawData.getShort();

        Buddy buddy = Buddy.getInstance();
        Logger.getSingleton().logMessage(
            "Buddy request : " + packet.getAddress());
        if (!buddy.isJKadUsedAsBuddy()) {
          ClientID receiverID = new ClientID(receiver_id);
          Int128 senderID = new Int128(sender_id);

          if (getClientID().equals(receiverID)) {
            buddy.setClientID(senderID);
            buddy.setAddress(new IPAddress(packet.getAddress()));
            buddy.setTCPPort(tcp_port);
            buddy.setUDPPort(org.jmule.core.utils.Convert
                .intToShort(packet.getAddress().getPort()));

            buddy.setKadIsUsedAsBuddy(true);

            Logger.getSingleton().logMessage(
                "New buddy : " + buddy.getAddress() + " TCP : "
                    + buddy.getTCPPort() + " UDP : "
                    + buddy.getUDPPort());

            ConfigurationManager configManager = ConfigurationManagerSingleton
                .getInstance();
            KadPacket response;
            try {
              response = PacketFactory.getBuddyResPacket(
                  new ClientID(sender_id), getClientID(),
                  (short) configManager.getTCP());
              _network_manager.sendKadPacket(response,
                  sender_address, sender_port);
            } catch (ConfigurationManagerException e) {
              e.printStackTrace();
            }

          }

        }

      } else if (packetOPCode == KADEMLIA2_SEARCH_KEY_REQ) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        List<Source> source_list;

        source_list = indexer.getKeywordSources(new Int128(targetID));
        KadPacket response = PacketFactory.getSearchRes2Packet(
            new Int128(targetID), source_list);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA2_SEARCH_SOURCE_REQ) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        short start_pos;
        start_pos = rawData.getShort();
        long fileSize = rawData.getLong();
        List<Source> source_list;

        source_list = indexer.getFileSources(new Int128(targetID),
            start_pos, fileSize);
        KadPacket response = PacketFactory.getSearchRes2Packet(
            new Int128(targetID), source_list);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA2_SEARCH_NOTES_REQ) {
        byte targetID[] = new byte[16];
        rawData.get(targetID);
        long fileSize = rawData.getLong();
        List<Source> source_list;

        source_list = indexer.getNoteSources(new Int128(targetID),
            fileSize);
        KadPacket response = PacketFactory.getSearchRes2Packet(
            new Int128(targetID), source_list);
        _network_manager.sendKadPacket(response, sender_address,
            sender_port);
      } else if (packetOPCode == KADEMLIA_CALLBACK_REQ) {
        Buddy buddy = Buddy.getInstance();
        if (buddy.isJKadUsedAsBuddy()) {
          Logger.getSingleton().logMessage("KAD callback request");
          byte[] cid = new byte[16];
          rawData.get(cid);
          final Int128 clientID = new Int128(cid);
          byte[] fid = new byte[16];
          rawData.get(fid);
          final FileHash fileHash = new FileHash(fid);
          final short port = rawData.getShort();
          final IPAddress ipAddress = new IPAddress(packet
              .getAddress());

          // final Peer peer = new Peer(buddy.getAddress().toString(),
          // buddy.getTCPPort(), PeerSource.KAD);
          final Peer peer = PeerManagerSingleton.getInstance()
              .newPeer(buddy.getAddress().toString(),
                  buddy.getTCPPort(), PeerSource.KAD);
          Logger.getSingleton().logMessage(
              "KAD callback request, Peer : " + peer);
          JMRunnable task = new JMRunnable() {
            public void JMRun() {
              try {
                _network_manager.addPeer(peer.getIP(), peer
                    .getPort());
              } catch (NetworkManagerException e1) {
                e1.printStackTrace();
              }
              long counter = 0;
              while (!peer.isConnected()) {
                counter++;
                if (counter == 5) {
                  Logger
                      .getSingleton()
                      .logMessage(
                          "KAD callback request, Peer : failed to connect");
                  return;
                }
                try {
                  Thread.sleep(5000);
                } catch (InterruptedException e) {
                  e.printStackTrace();
                }
              }
              Logger.getSingleton().logMessage(
                  "KAD callback request, Peer : connected & send packet to :  "
                      + peer);

              _network_manager.sendCallBackRequest(peer.getIP(),
                  peer.getPort(), clientID, fileHash,
                  ipAddress, port);
              try {
                Thread.sleep(500);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
              Logger.getSingleton().logMessage(
                  "KAD callback request : Disconnecting from  "
                      + peer);
              _network_manager.disconnectPeer(peer.getIP(), peer
                  .getPort());

            }
          };
          new Thread(task).start();
        }
      } else
        unknown_packet = true;

    } catch (Throwable cause) {
      cause.printStackTrace();
    }

    if (unknown_packet)
      throw new UnknownPacketOPCodeException(packetOPCode);

  }

  public void addPacketListener(PacketListener listener) {
    List<PacketListener> list = packetListeners.get(listener
        .getPacketOPCode());
    if (list == null) {
      list = new CopyOnWriteArrayList<PacketListener>();
      packetListeners.put(listener.getPacketOPCode(), list);
    }

    list.add(listener);
  }

  public void removePacketListener(PacketListener listener) {
    List<PacketListener> list = packetListeners.get(listener
        .getPacketOPCode());
    if (list == null)
      return;
    list.remove(listener);
    if (list.isEmpty())
      packetListeners.remove(listener.getPacketOPCode());
  }

  public IPAddress getIPAddress() {
    return firewallChecker.getMyIPAddress();
  }

  public ClientID getClientID() {
    return clientID;
  }

  public JKadStatus getStatus() {
    return status;
  }

  public boolean isConnected() {
    return status == CONNECTED;
  }

  public boolean isDisconnected() {
    return status == DISCONNECTED;
  }

  public boolean isConnecting() {
    return status == CONNECTING;
  }

  public void addJKadListener(JKadListener listener) {
    listener_list.add(listener);
  }

  public void removeJKadListener(JKadListener listener) {
    listener_list.remove(listener);
  }

  private void notifyListeners(JKadStatus newStatus) {
    for (JKadListener listener : listener_list)
      if (newStatus == JKadStatus.CONNECTED)
        listener.JKadIsConnected();
      else if (newStatus == JKadStatus.CONNECTING)
        listener.JKadIsConnecting();
      else if (newStatus == JKadStatus.DISCONNECTED)
        listener.JKadIsDisconnected();
  }

  public RoutingTable getRoutingTable() {
    return routing_table;
  }

  public BootStrap getBootStrap() {
    return bootStrap;
  }

  public FirewallChecker getFirewallChecker() {
    return firewallChecker;
  }

  public Indexer getIndexer() {
    return indexer;
  }

  public Lookup getLookup() {
    return lookup;
  }
 
  public Search getSearch() {
    return search;
  }

  public Publisher getPublisher() {
    return publisher;
  }

  private KadContact getContact(ByteBuffer packetData) {
    byte[] client_id_raw = new byte[16];
    packetData.get(client_id_raw);
    byte[] address = new byte[4];
    packetData.get(address);
    int udp_port = shortToInt(packetData.getShort());
    int tcp_port = shortToInt(packetData.getShort());
    byte client_version = packetData.get();
    return new KadContact(new ClientID(client_id_raw), new ContactAddress(
        address, udp_port), tcp_port, client_version, null, false);
  }
}
TOP

Related Classes of org.jmule.core.jkad.JKadManagerImpl

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.