@GuardedBy("lock") private void receiveCloseMessage() throws InsufficientMoneyException { log.info("Got CLOSE message, closing channel"); if (state != null) { settlePayment(CloseReason.CLIENT_REQUESTED_CLOSE); } else { conn.destroyConnection(CloseReason.CLIENT_REQUESTED_CLOSE); } }
private void error(String message, Protos.Error.ErrorCode errorCode, CloseReason closeReason) { log.error(message); Protos.Error.Builder errorBuilder; errorBuilder = Protos.Error.newBuilder().setCode(errorCode).setExplanation(message); conn.sendToClient( Protos.TwoWayChannelMessage.newBuilder() .setError(errorBuilder) .setType(Protos.TwoWayChannelMessage.MessageType.ERROR) .build()); conn.destroyConnection(closeReason); }
/** * Closes the connection by generating a settle message for the client and calls {@link * ServerConnection#destroyConnection(CloseReason)}. Note that this does not broadcast the payment * transaction and the client may still resume the same channel if they reconnect * * <p> * * <p>Note that {@link PaymentChannelServer#connectionClosed()} must still be called after the * connection fully closes. */ public void close() { lock.lock(); try { if (connectionOpen && !channelSettling) { final Protos.TwoWayChannelMessage.Builder msg = Protos.TwoWayChannelMessage.newBuilder(); msg.setType(Protos.TwoWayChannelMessage.MessageType.CLOSE); conn.sendToClient(msg.build()); conn.destroyConnection(CloseReason.SERVER_REQUESTED_CLOSE); } } finally { lock.unlock(); } }
/** * Called when a message is received from the client. Processes the given message and generates * events based on its content. */ public void receiveMessage(Protos.TwoWayChannelMessage msg) { lock.lock(); try { checkState(connectionOpen); if (channelSettling) return; // If we generate an error, we set errorBuilder and closeReason and break, otherwise we return Protos.Error.Builder errorBuilder; CloseReason closeReason; try { switch (msg.getType()) { case CLIENT_VERSION: receiveVersionMessage(msg); return; case PROVIDE_REFUND: receiveRefundMessage(msg); return; case PROVIDE_CONTRACT: receiveContractMessage(msg); return; case UPDATE_PAYMENT: checkState(step == InitStep.CHANNEL_OPEN && msg.hasUpdatePayment()); receiveUpdatePaymentMessage(msg.getUpdatePayment(), true); return; case CLOSE: receiveCloseMessage(); return; case ERROR: checkState(msg.hasError()); log.error( "Client sent ERROR {} with explanation {}", msg.getError().getCode().name(), msg.getError().hasExplanation() ? msg.getError().getExplanation() : ""); conn.destroyConnection(CloseReason.REMOTE_SENT_ERROR); return; default: final String errorText = "Got unknown message type or type that doesn't apply to servers."; error( errorText, Protos.Error.ErrorCode.SYNTAX_ERROR, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } } catch (VerificationException e) { log.error("Caught verification exception handling message from client", e); error( e.getMessage(), Protos.Error.ErrorCode.BAD_TRANSACTION, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } catch (ValueOutOfRangeException e) { log.error("Caught value out of range exception handling message from client", e); error( e.getMessage(), Protos.Error.ErrorCode.BAD_TRANSACTION, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } catch (InsufficientMoneyException e) { log.error("Caught insufficient money exception handling message from client", e); error( e.getMessage(), Protos.Error.ErrorCode.BAD_TRANSACTION, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } catch (IllegalStateException e) { log.error("Caught illegal state exception handling message from client", e); error( e.getMessage(), Protos.Error.ErrorCode.SYNTAX_ERROR, CloseReason.REMOTE_SENT_INVALID_MESSAGE); } } finally { lock.unlock(); } }