Exemplo n.º 1
0
void Peer::handle_read(const system::error_code& e, std::size_t bytes_transferred) {
    log_trace("args error: %s, bytes: %d", e.message(), bytes_transferred);
    if (!e) {
        _activity = true;
        string rx;
        for(int i = 0; i < bytes_transferred; i++)
            rx.push_back(_buffer[i]);
        
        vRecv += rx;
        
        // Now call the parser:
        bool fRet = false;
        loop {
            boost::tuple<boost::tribool, CDataStream::iterator> parser_result = _msgParser.parse(_chain, _message, vRecv.begin(), vRecv.end());
            tribool result = get<0>(parser_result);
            vRecv.erase(vRecv.begin(), get<1>(parser_result));
            if (result) {
                if (_messageHandler.handleMessage(this, _message) ) fRet = true;
            }
            else if (!result) {
                log_warn("Peer %s sending bogus - disconnecting", addr.toString());
                _peerManager.post_stop(shared_from_this());
            }//                continue; // basically, if we get a false result, we should consider to disconnect from the Peer!
            else
                break;
        }

        // now if fRet is true, something were processed by the filters - we want to send to the peers / we check for which vSends cointains stuff and the we run
        
        if (fRet && nVersion > 0) {
            // first reply
            reply();
            
            // then trickle
            Peers peers = _peerManager.getAllPeers();
            size_t rand = GetRand(peers.size());
            for (Peers::iterator peer = peers.begin(); peer != peers.end(); ++peer)
                if(rand-- == 0) {
                    (*peer)->trickle();
                    break;
                }
            
            // then broadcast
            for (Peers::iterator peer = peers.begin(); peer != peers.end(); ++peer)
                (*peer)->broadcast();
            
            // now write to the peers with non-empty vSend buffers
            for (Peers::iterator peer = peers.begin(); peer != peers.end(); ++peer) {
                (*peer)->flush();
            }
        }
        
        // then wait for more data
        _socket.async_read_some(buffer(_buffer), boost::bind(&Peer::handle_read, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred));
        //        async_read(_socket, _recv, boost::bind(&Peer::handle_read, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred));
    }
Exemplo n.º 2
0
            /** accepts and keeps track of connections. reads data
              from connected peers and notifies through virtual methods
              if packets can be deserialized 
             \param tls use GnuTLS for encryption 
             \param port listen for incoming connections at this port
             \param maxPeers maximum number of connected peers */
            void serve(bool tls, int port, int maxPeers) {
                if (tls)
                    sock.reset(new TLSSocket());
                else
                    sock.reset(new Socket());
                sock->setNonBlocking();
                sock->bind(port);
                sock->listen(maxPeers);
                Select select;
                /* Wait for a peer, send data and term */
                while (!closed)
                {
                    select.reset();
                    if (peers.size() < maxPeers)
                        select.input(sock->getFd());
                    for (typename Peers::iterator i = peers.begin(); i != peers.end(); i++) {
                        select.input((*i)->getFd());
                    }
                    if (select.select(100) == -1)
                        continue;
                    if (select.canRead(sock->getFd()) 
                            && peers.size() < maxPeers) {
                        try {
                            Socket* csock = sock->accept();

                            if (tls)  {
                                boost::threadpool::schedule(pool, 
                                        boost::bind(&Server::handshake, this, csock));
                            } else {
                                peers.push_back(boost::shared_ptr<PeerT>(new PeerT()));
                                csock->setNonBlocking();
                                peers.back()->setup(csock);
                                onJoin(*peers.back());

                            }
                        } catch (SocketExcept& e) {
                            std::cerr << e.what() << std::endl;
                        }
                    }
                    if (tls)  {
                        Socket* sock = NULL;
                        socketsReady.try_pop_front(sock);
                        if (sock) {
                            sock->setNonBlocking();
                            peers.push_back(boost::shared_ptr<PeerT>(new PeerT()));
                            peers.back()->setup(sock);
                            onJoin(*peers.back());
                        }
                    }
                    for (size_t i = 0; i < peers.size(); i++) {
                        boost::shared_ptr<PeerT>& p = peers[i];
                        if (select.canRead(p->getFd()))
                            p->onInput();
                        while (p->hasPacket()) {
                            onPacket(*p);
                        }
                    }
                    // collect dead peers
                    size_t count = peers.size();
                    for (size_t i = 0; i < count; ) {
                        if (!peers[i]->isActive()) {
                            onLeave(*peers[i]);

                            peers[i] = peers[peers.size() - 1];
                            count--;
                        } else
                            i++;
                    }
                    if (count < peers.size()) {
                        peers.resize(count);
                    }

                }
            }