void ConnectionManager::connect(const Node::Ptr& node, const string& token, bool secure)
	{
		// don't allow connection if we didn't proceed a handshake
		if(!node->isOnline())
		{
			// do handshake at first
			DHT::getInstance()->info(node->getIdentity().getIp(), static_cast<uint16_t>(Util::toInt(node->getIdentity().getUdpPort())), 
				DHT::PING | DHT::MAKE_ONLINE, node->getUser()->getCID(), node->getUdpKey());
			return;
		}
		
		bool active = ClientManager::getInstance()->isActive();

		// if I am not active, send reverse connect to me request
		AdcCommand cmd(active ? AdcCommand::CMD_CTM : AdcCommand::CMD_RCM, AdcCommand::TYPE_UDP);
		cmd.addParam(secure ? SECURE_CLIENT_PROTOCOL_TEST : CLIENT_PROTOCOL);
		
		if(active)
		{
			uint16_t port = secure ? dcpp::ConnectionManager::getInstance()->getSecurePort() : dcpp::ConnectionManager::getInstance()->getPort();
			cmd.addParam(Util::toString(port));
		}		

		cmd.addParam(token);
		
		DHT::getInstance()->send(cmd, node->getIdentity().getIp(), static_cast<uint16_t>(Util::toInt(node->getIdentity().getUdpPort())), 
			node->getUser()->getCID(), node->getUdpKey());
	}
    /*
     * Sends request to create connection with me
     */
    void ConnectionManager::revConnectToMe(const Node::Ptr& node, const AdcCommand& cmd)
    {
        // don't allow connection if we didn't proceed a handshake
        //if(!node->isOnline())
        //  return;

        // this is valid for active-passive connections only
        if(!ClientManager::getInstance()->isActive())
            return;

        const string& protocol = cmd.getParam(1);
        const string& token = cmd.getParam(2);

        bool secure;
        if(protocol == CLIENT_PROTOCOL)
        {
            secure = false;
        }
        else if(protocol == SECURE_CLIENT_PROTOCOL_TEST && CryptoManager::getInstance()->TLSOk())
        {
            secure = true;
        }
        else
        {
            AdcCommand sta(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_UNSUPPORTED, "Protocol unknown", AdcCommand::TYPE_UDP);
            sta.addParam("PR", protocol);
            sta.addParam("TO", token);

            DHT::getInstance()->send(sta, node->getIdentity().getIp(), node->getIdentity().getUdpPort(),
                node->getUser()->getCID(), node->getUdpKey());
            return;
        }

        connect(node, token, secure);
    }
Beispiel #3
0
	/*
	 * Adds node to routing table
	 */
	bool KBucket::insert(const Node::Ptr& node)
	{
		if(node->isInList)
			return true;	// node is already in the table

		string ip = node->getIdentity().getIp();
		string port = node->getIdentity().getUdpPort();

		// allow only one same IP:port
		bool isAcceptable = (ipMap.find(ip + ":" + port) == ipMap.end());

		if((nodes.size() < (K * ID_BITS)) && isAcceptable)
		{
			nodes.push_back(node);
			node->isInList = true;
			ipMap.insert(ip + ":" + port);

			if(DHT::getInstance())
				DHT::getInstance()->setDirty();

			return true;
		}

		return isAcceptable;
	}
	/*
	 * Creates connection to specified node 
	 */
	void ConnectionManager::connectToMe(const Node::Ptr& node, const AdcCommand& cmd)
	{
		// don't allow connection if we didn't proceed a handshake
		if(!node->isOnline())
		{
			// do handshake at first
			DHT::getInstance()->info(node->getIdentity().getIp(), static_cast<uint16_t>(Util::toInt(node->getIdentity().getUdpPort())),
				DHT::PING | DHT::MAKE_ONLINE, node->getUser()->getCID(), node->getUdpKey());
			return;
		}
	
		const string& protocol = cmd.getParam(1);
		const string& port = cmd.getParam(2);
		const string& token = cmd.getParam(3);

		bool secure = false;
		if(protocol == CLIENT_PROTOCOL) 
		{
			// Nothing special
		} 
		else if(protocol == SECURE_CLIENT_PROTOCOL_TEST && CryptoManager::getInstance()->TLSOk()) 
		{
			secure = true;
		} 
		else 
		{
			AdcCommand cmd(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_UNSUPPORTED, "Protocol unknown", AdcCommand::TYPE_UDP);
			cmd.addParam("PR", protocol);
			cmd.addParam("TO", token);

			DHT::getInstance()->send(cmd, node->getIdentity().getIp(), static_cast<uint16_t>(Util::toInt(node->getIdentity().getUdpPort())), 
				node->getUser()->getCID(), node->getUdpKey());
			return;
		}

		if(!node->getIdentity().isTcpActive(0)) 
		{
			AdcCommand err(AdcCommand::SEV_FATAL, AdcCommand::ERROR_PROTOCOL_GENERIC, "IP unknown", AdcCommand::TYPE_UDP);
			DHT::getInstance()->send(err, node->getIdentity().getIp(), static_cast<uint16_t>(Util::toInt(node->getIdentity().getUdpPort())), 
				node->getUser()->getCID(), node->getUdpKey());
			return;
		}

		dcpp::ConnectionManager::getInstance()->adcConnect(*node, static_cast<uint16_t>(Util::toInt(port)), token, secure);		
	}
    /*
     * Add new source to tth list
     */
    void IndexManager::addSource(const TTHValue& tth, const Node::Ptr& node, uint64_t size, bool partial)
    {
        Source source;
        source.setCID(node->getUser()->getCID());
        source.setIp(node->getIdentity().getIp());
        source.setUdpPort(node->getIdentity().getUdpPort());
        source.setSize(size);
        source.setExpires(GET_TICK() + (partial ? PFS_REPUBLISH_TIME : REPUBLISH_TIME));
        source.setPartial(partial);

        Lock l(cs);

        TTHMap::iterator i = tthList.find(tth);
        if(i != tthList.end())
        {
            // no user duplicites
            SourceList& sources = i->second;
            for(SourceList::iterator s = sources.begin(); s != sources.end(); ++s)
            {
                if(node->getUser()->getCID() == (*s).getCID())
                {
                    // delete old item
                    sources.erase(s);
                    break;
                }
            }

            // old items in front, new items in back
            sources.push_back(source);

            // if maximum sources reached, remove the oldest one
            if(sources.size() > MAX_SEARCH_RESULTS)
                sources.pop_front();
        }
        else
        {
            // new file
            tthList.insert(std::make_pair(tth, SourceList(1, source)));
        }

        DHT::getInstance()->setDirty();
    }
    /*
     * Processes incoming request to publish file
     */
    void IndexManager::processPublishSourceRequest(const Node::Ptr& node, const AdcCommand& cmd)
    {
        string tth;
        if(!cmd.getParam("TR", 1, tth))
            return; // nothing to identify a file?

        string size;
        if(!cmd.getParam("SI", 1, size))
            return; // no file size?

        string partial;
        cmd.getParam("PF", 1, partial);

        addSource(TTHValue(tth), node, Util::toInt64(size), partial == "1");

        // send response
        AdcCommand res(AdcCommand::SEV_SUCCESS, AdcCommand::SUCCESS, "File published", AdcCommand::TYPE_UDP);
        res.addParam("FC", "PUB");
        res.addParam("TR", tth);
        DHT::getInstance()->send(res, node->getIdentity().getIp(), node->getIdentity().getUdpPort(), node->getUser()->getCID(), node->getUdpKey());
    }
Beispiel #7
0
	/*
	 * Creates new (or update existing) node which is NOT added to our routing table
	 */
	Node::Ptr KBucket::createNode(const UserPtr& u, const string& ip, uint16_t port, bool update, bool isUdpKeyValid)
	{
		if(u->isSet(User::DHT)) // is this user already known in DHT?
		{
			Node::Ptr node = NULL;

			// no online node found, try get from routing table
			for(NodeList::iterator it = nodes.begin(); it != nodes.end(); ++it)
			{
				if(u->getCID() == (*it)->getUser()->getCID())
				{
					node = *it;

					// put node at the end of the list
					nodes.erase(it);
					nodes.push_back(node);
					break;
				}
			}

			if(node == NULL && u->isOnline())
			{
				// try to get node from ClientManager (user can be online but not in our routing table)
				// this fixes the bug with DHT node online twice
				node = (Node*)ClientManager::getInstance()->findDHTNode(u->getCID());
				node = node.get();
			}

			if(node != NULL)
			{
				// fine, node found, update it and return it
				if(update)
				{
					string oldIp	= node->getIdentity().getIp();
					string oldPort	= node->getIdentity().getUdpPort();
					if(ip != oldIp || static_cast<uint16_t>(Util::toInt(oldPort)) != port)
					{
						node->setIpVerified(false);

						 // TODO: don't allow update when new IP already exists for different node

						// erase old IP and remember new one
						ipMap.erase(oldIp + ":" + oldPort);
						ipMap.insert(ip + ":" + Util::toString(port));
					}

					if(!node->isIpVerified())
						node->setIpVerified(isUdpKeyValid);

					node->setAlive();
					node->getIdentity().setIp(ip);
					node->getIdentity().setUdpPort(Util::toString(port));

					DHT::getInstance()->setDirty();
				}

				return node;
			}
		}

		u->setFlag(User::DHT);

		Node::Ptr node(new Node(u));
		node->getIdentity().setIp(ip);
		node->getIdentity().setUdpPort(Util::toString(port));
		node->setIpVerified(isUdpKeyValid);
		return node;
	}