Search in sources :

Example 11 with NodeAddress

use of io.bitsquare.p2p.NodeAddress in project bitsquare by bitsquare.

the class DisputeManager method sendPeerPublishedPayoutTxMessage.

// winner (or buyer in case of 50/50) sends tx to other peer
private void sendPeerPublishedPayoutTxMessage(Transaction transaction, Dispute dispute, Contract contract) {
    PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing();
    NodeAddress peerNodeAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerNodeAddress() : contract.getBuyerNodeAddress();
    log.trace("sendPeerPublishedPayoutTxMessage to peerAddress " + peerNodeAddress);
    p2PService.sendEncryptedMailboxMessage(peerNodeAddress, peersPubKeyRing, new PeerPublishedPayoutTxMessage(transaction.bitcoinSerialize(), dispute.getTradeId(), p2PService.getAddress()), new SendMailboxMessageListener() {

        @Override
        public void onArrived() {
        }

        @Override
        public void onStoredInMailbox() {
        }

        @Override
        public void onFault(String errorMessage) {
            log.error("sendEncryptedMessage failed");
        }
    });
}
Also used : PubKeyRing(io.bitsquare.common.crypto.PubKeyRing) NodeAddress(io.bitsquare.p2p.NodeAddress) SendMailboxMessageListener(io.bitsquare.p2p.messaging.SendMailboxMessageListener)

Example 12 with NodeAddress

use of io.bitsquare.p2p.NodeAddress in project bitsquare by bitsquare.

the class DisputeManager method sendDisputeResultMessage.

// arbitrator send result to trader
public void sendDisputeResultMessage(DisputeResult disputeResult, Dispute dispute, String text) {
    DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage(dispute.getTradeId(), dispute.getTraderPubKeyRing().hashCode(), false, text, p2PService.getAddress());
    dispute.addDisputeMessage(disputeCommunicationMessage);
    disputeResult.setDisputeCommunicationMessage(disputeCommunicationMessage);
    NodeAddress peerNodeAddress;
    Contract contract = dispute.getContract();
    if (contract.getBuyerPubKeyRing().equals(dispute.getTraderPubKeyRing()))
        peerNodeAddress = contract.getBuyerNodeAddress();
    else
        peerNodeAddress = contract.getSellerNodeAddress();
    p2PService.sendEncryptedMailboxMessage(peerNodeAddress, dispute.getTraderPubKeyRing(), new DisputeResultMessage(disputeResult, p2PService.getAddress()), new SendMailboxMessageListener() {

        @Override
        public void onArrived() {
            disputeCommunicationMessage.setArrived(true);
        }

        @Override
        public void onStoredInMailbox() {
            disputeCommunicationMessage.setStoredInMailbox(true);
        }

        @Override
        public void onFault(String errorMessage) {
            log.error("sendEncryptedMessage failed");
        }
    });
}
Also used : NodeAddress(io.bitsquare.p2p.NodeAddress) SendMailboxMessageListener(io.bitsquare.p2p.messaging.SendMailboxMessageListener) Contract(io.bitsquare.trade.Contract)

Example 13 with NodeAddress

use of io.bitsquare.p2p.NodeAddress in project bitsquare by bitsquare.

the class RequestDataHandler method requestData.

///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void requestData(NodeAddress nodeAddress, boolean isPreliminaryDataRequest) {
    Log.traceCall("nodeAddress=" + nodeAddress);
    peersNodeAddress = nodeAddress;
    if (!stopped) {
        GetDataRequest getDataRequest;
        // We collect the keys of the PersistedStoragePayload items so we exclude them in our request.
        // PersistedStoragePayload items don't get removed, so we don't have an issue with the case that
        // an object gets removed in between PreliminaryGetDataRequest and the GetUpdatedDataRequest and we would 
        // miss that event if we do not load the full set or use some delta handling.
        Set<byte[]> excludedKeys = dataStorage.getMap().entrySet().stream().filter(e -> e.getValue().getStoragePayload() instanceof PersistedStoragePayload).map(e -> e.getKey().bytes).collect(Collectors.toSet());
        if (isPreliminaryDataRequest)
            getDataRequest = new PreliminaryGetDataRequest(nonce, excludedKeys);
        else
            getDataRequest = new GetUpdatedDataRequest(networkNode.getNodeAddress(), nonce, excludedKeys);
        if (timeoutTimer == null) {
            timeoutTimer = UserThread.runAfter(() -> {
                // setup before sending to avoid race conditions
                if (!stopped) {
                    String errorMessage = "A timeout occurred at sending getDataRequest:" + getDataRequest + " on nodeAddress:" + nodeAddress;
                    log.debug(errorMessage + " / RequestDataHandler=" + RequestDataHandler.this);
                    handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT);
                } else {
                    log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + "Might be caused by an previous networkNode.sendMessage.onFailure.");
                }
            }, TIME_OUT_SEC);
        }
        log.debug("We send a {} to peer {}. ", getDataRequest.getClass().getSimpleName(), nodeAddress);
        networkNode.addMessageListener(this);
        SettableFuture<Connection> future = networkNode.sendMessage(nodeAddress, getDataRequest);
        Futures.addCallback(future, new FutureCallback<Connection>() {

            @Override
            public void onSuccess(Connection connection) {
                if (!stopped) {
                    RequestDataHandler.this.connection = connection;
                    log.trace("Send " + getDataRequest + " to " + nodeAddress + " succeeded.");
                } else {
                    log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + "Might be caused by an previous timeout.");
                }
            }

            @Override
            public void onFailure(@NotNull Throwable throwable) {
                if (!stopped) {
                    String errorMessage = "Sending getDataRequest to " + nodeAddress + " failed. That is expected if the peer is offline.\n\t" + "getDataRequest=" + getDataRequest + "." + "\n\tException=" + throwable.getMessage();
                    log.debug(errorMessage);
                    handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE);
                } else {
                    log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + "Might be caused by an previous timeout.");
                }
            }
        });
    } else {
        log.warn("We have stopped already. We ignore that requestData call.");
    }
}
Also used : java.util(java.util) ProtectedStorageEntry(io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry) LoggerFactory(org.slf4j.LoggerFactory) Connection(io.bitsquare.p2p.network.Connection) Timer(io.bitsquare.common.Timer) SettableFuture(com.google.common.util.concurrent.SettableFuture) GetDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetDataRequest) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) PersistedStoragePayload(io.bitsquare.p2p.storage.payload.PersistedStoragePayload) PeerManager(io.bitsquare.p2p.peers.PeerManager) Log(io.bitsquare.app.Log) P2PDataStorage(io.bitsquare.p2p.storage.P2PDataStorage) GetUpdatedDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest) Logger(org.slf4j.Logger) GetDataResponse(io.bitsquare.p2p.peers.getdata.messages.GetDataResponse) UserThread(io.bitsquare.common.UserThread) Message(io.bitsquare.p2p.Message) NodeAddress(io.bitsquare.p2p.NodeAddress) StoragePayload(io.bitsquare.p2p.storage.payload.StoragePayload) Collectors(java.util.stream.Collectors) FutureCallback(com.google.common.util.concurrent.FutureCallback) TimeUnit(java.util.concurrent.TimeUnit) Nullable(org.jetbrains.annotations.Nullable) Futures(com.google.common.util.concurrent.Futures) LazyProcessedStoragePayload(io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload) MessageListener(io.bitsquare.p2p.network.MessageListener) CloseConnectionReason(io.bitsquare.p2p.network.CloseConnectionReason) NotNull(org.jetbrains.annotations.NotNull) NetworkNode(io.bitsquare.p2p.network.NetworkNode) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) PersistedStoragePayload(io.bitsquare.p2p.storage.payload.PersistedStoragePayload) Connection(io.bitsquare.p2p.network.Connection) GetDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetDataRequest) PreliminaryGetDataRequest(io.bitsquare.p2p.peers.getdata.messages.PreliminaryGetDataRequest) GetUpdatedDataRequest(io.bitsquare.p2p.peers.getdata.messages.GetUpdatedDataRequest)

Example 14 with NodeAddress

use of io.bitsquare.p2p.NodeAddress in project bitsquare by bitsquare.

the class RequestDataHandler method onMessage.

///////////////////////////////////////////////////////////////////////////////////////////
// MessageListener implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onMessage(Message message, Connection connection) {
    if (connection.getPeersNodeAddressOptional().isPresent() && connection.getPeersNodeAddressOptional().get().equals(peersNodeAddress)) {
        if (message instanceof GetDataResponse) {
            Log.traceCall(message.toString() + "\n\tconnection=" + connection);
            if (!stopped) {
                GetDataResponse getDataResponse = (GetDataResponse) message;
                Map<String, Set<StoragePayload>> payloadByClassName = new HashMap<>();
                final HashSet<ProtectedStorageEntry> dataSet = getDataResponse.dataSet;
                dataSet.stream().forEach(e -> {
                    final StoragePayload storagePayload = e.getStoragePayload();
                    String className = storagePayload.getClass().getSimpleName();
                    if (!payloadByClassName.containsKey(className))
                        payloadByClassName.put(className, new HashSet<>());
                    payloadByClassName.get(className).add(storagePayload);
                });
                StringBuilder sb = new StringBuilder("Received data size: ").append(dataSet.size()).append(", data items: ");
                payloadByClassName.entrySet().stream().forEach(e -> sb.append(e.getValue().size()).append(" items of ").append(e.getKey()).append("; "));
                log.info(sb.toString());
                if (getDataResponse.requestNonce == nonce) {
                    stopTimeoutTimer();
                    checkArgument(connection.getPeersNodeAddressOptional().isPresent(), "RequestDataHandler.onMessage: connection.getPeersNodeAddressOptional() must be present " + "at that moment");
                    final NodeAddress sender = connection.getPeersNodeAddressOptional().get();
                    List<ProtectedStorageEntry> processDelayedItems = new ArrayList<>();
                    dataSet.stream().forEach(e -> {
                        if (e.getStoragePayload() instanceof LazyProcessedStoragePayload)
                            processDelayedItems.add(e);
                        else {
                            dataStorage.add(e, sender, null, false, false);
                        }
                    });
                    // We process the LazyProcessedStoragePayload items (TradeStatistics) in batches with a delay in between.
                    // We want avoid that the UI get stuck when processing many entries.
                    // The dataStorage.add call is a bit expensive as sig checks is done there.
                    // Using a background thread might be an alternative but it would require much more effort and 
                    // it would also decrease user experience if the app gets under heavy load (like at startup with wallet sync).
                    // Beside that we mitigated the problem already as we will not get the whole TradeStatistics as we 
                    // pass the excludeKeys and we pack the latest data dump 
                    // into the resources, so a new user do not need to request all data.
                    // In future we will probably limit by date or load on demand from user intent to not get too much data.
                    // We split the list into sub lists with max 50 items and delay each batch with 200 ms.
                    int size = processDelayedItems.size();
                    int chunkSize = 50;
                    int chunks = 1 + size / chunkSize;
                    int startIndex = 0;
                    for (int i = 0; i < chunks && startIndex < size; i++, startIndex += chunkSize) {
                        long delay = (i + 1) * 200;
                        int endIndex = Math.min(size, startIndex + chunkSize);
                        List<ProtectedStorageEntry> subList = processDelayedItems.subList(startIndex, endIndex);
                        UserThread.runAfter(() -> {
                            subList.stream().forEach(protectedStorageEntry -> dataStorage.add(protectedStorageEntry, sender, null, false, false));
                        }, delay, TimeUnit.MILLISECONDS);
                    }
                    cleanup();
                    listener.onComplete();
                } else {
                    log.debug("Nonce not matching. That can happen rarely if we get a response after a canceled " + "handshake (timeout causes connection close but peer might have sent a msg before " + "connection was closed).\n\t" + "We drop that message. nonce={} / requestNonce={}", nonce, getDataResponse.requestNonce);
                }
            } else {
                log.warn("We have stopped already. We ignore that onDataRequest call.");
            }
        }
    } else {
        log.trace("We got a message from another connection and ignore it.");
    }
}
Also used : LazyProcessedStoragePayload(io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload) GetDataResponse(io.bitsquare.p2p.peers.getdata.messages.GetDataResponse) NodeAddress(io.bitsquare.p2p.NodeAddress) PersistedStoragePayload(io.bitsquare.p2p.storage.payload.PersistedStoragePayload) StoragePayload(io.bitsquare.p2p.storage.payload.StoragePayload) LazyProcessedStoragePayload(io.bitsquare.p2p.storage.payload.LazyProcessedStoragePayload) ProtectedStorageEntry(io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry)

Example 15 with NodeAddress

use of io.bitsquare.p2p.NodeAddress in project bitsquare by bitsquare.

the class RequestDataManager method requestPreliminaryData.

///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void requestPreliminaryData() {
    Log.traceCall();
    ArrayList<NodeAddress> nodeAddresses = new ArrayList<>(seedNodeAddresses);
    if (!nodeAddresses.isEmpty()) {
        Collections.shuffle(nodeAddresses);
        NodeAddress nextCandidate = nodeAddresses.get(0);
        nodeAddresses.remove(nextCandidate);
        isPreliminaryDataRequest = true;
        requestData(nextCandidate, nodeAddresses);
    }
}
Also used : NodeAddress(io.bitsquare.p2p.NodeAddress)

Aggregations

NodeAddress (io.bitsquare.p2p.NodeAddress)34 WalletService (io.bitsquare.btc.WalletService)5 Contract (io.bitsquare.trade.Contract)5 Logger (org.slf4j.Logger)5 LoggerFactory (org.slf4j.LoggerFactory)5 Log (io.bitsquare.app.Log)4 AddressEntry (io.bitsquare.btc.AddressEntry)4 Timer (io.bitsquare.common.Timer)4 UserThread (io.bitsquare.common.UserThread)4 PubKeyRing (io.bitsquare.common.crypto.PubKeyRing)4 P2PService (io.bitsquare.p2p.P2PService)4 SendMailboxMessageListener (io.bitsquare.p2p.messaging.SendMailboxMessageListener)4 TimeUnit (java.util.concurrent.TimeUnit)4 DummySeedNode (io.bitsquare.p2p.DummySeedNode)3 P2PServiceListener (io.bitsquare.p2p.P2PServiceListener)3 Connection (io.bitsquare.p2p.network.Connection)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 Collectors (java.util.stream.Collectors)3 FutureCallback (com.google.common.util.concurrent.FutureCallback)2 Futures (com.google.common.util.concurrent.Futures)2