io.vertx.ext.eventbus.bridge.tcp.impl.TcpEventBusBridgeImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2015 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.ext.eventbus.bridge.tcp.impl;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.*;
import io.vertx.core.internal.logging.Logger;
import io.vertx.core.internal.logging.LoggerFactory;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;
import io.vertx.core.net.NetSocket;
import io.vertx.ext.bridge.BridgeEventType;
import io.vertx.ext.bridge.BridgeOptions;
import io.vertx.ext.bridge.PermittedOptions;
import io.vertx.ext.eventbus.bridge.tcp.BridgeEvent;
import io.vertx.ext.eventbus.bridge.tcp.TcpEventBusBridge;
import io.vertx.ext.eventbus.bridge.tcp.impl.protocol.FrameParser;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static io.vertx.ext.eventbus.bridge.tcp.impl.protocol.FrameHelper.sendErrFrame;
import static io.vertx.ext.eventbus.bridge.tcp.impl.protocol.FrameHelper.sendFrame;
/**
* Abstract TCP EventBus bridge. Handles all common socket operations but has no knowledge on the payload.
*
* @author Paulo Lopes
*/
public class TcpEventBusBridgeImpl implements TcpEventBusBridge {
private static final Logger log = LoggerFactory.getLogger(TcpEventBusBridgeImpl.class);
private final EventBus eb;
private final NetServer server;
private final Map compiledREs = new HashMap<>();
private final BridgeOptions options;
private final Handler bridgeEventHandler;
public TcpEventBusBridgeImpl(Vertx vertx, BridgeOptions options, NetServerOptions netServerOptions, Handler eventHandler) {
this.eb = vertx.eventBus();
this.options = options != null ? options : new BridgeOptions();
this.bridgeEventHandler = eventHandler;
server = vertx.createNetServer(netServerOptions == null ? new NetServerOptions() : netServerOptions);
server.connectHandler(this::handler);
}
@Override
public Future listen() {
return server.listen().map(this);
}
@Override
public Future listen(int port) {
return server.listen(port).map(this);
}
@Override
public Future listen(int port, String address) {
return server.listen(port, address).map(this);
}
private void doSendOrPub(NetSocket socket, String address, JsonObject msg, Map> registry, Map> replies) {
final Object body = msg.getValue("body");
final JsonObject headers = msg.getJsonObject("headers");
// default to message
final String type = msg.getString("type", "message");
DeliveryOptions deliveryOptions = parseMsgHeaders(new DeliveryOptions(), headers);
switch (type) {
case "send":
if (checkMatches(true, address, replies)) {
final String replyAddress = msg.getString("replyAddress");
if (replyAddress != null) {
// reply address is not null, it is a request from TCP endpoint that will wait for a response
eb.request(address, body, deliveryOptions).onComplete((AsyncResult> res1) -> {
if (res1.failed()) {
sendErrFrame(address, replyAddress, (ReplyException) res1.cause(), socket);
} else {
final Message> response = res1.result();
final JsonObject responseHeaders = new JsonObject();
// clone the headers from / to
for (Map.Entry entry : response.headers()) {
responseHeaders.put(entry.getKey(), entry.getValue());
}
if (response.replyAddress() != null) {
replies.put(response.replyAddress(), response);
}
sendFrame("message", replyAddress, response.replyAddress(), responseHeaders, true, response.body(), socket);
}
});
} else {
// no reply address it might be a response, a failure or a request that does not need a response
if (replies.containsKey(address)) {
// address is registered, it is not a request
Integer failureCode = msg.getInteger("failureCode");
if ( failureCode == null ) {
//No failure code, it is a response
replies.get(address).reply(body, deliveryOptions);
} else {
//Failure code, fail the original response
replies.get(address).fail(msg.getInteger("failureCode"), msg.getString("message"));
}
} else {
// it is a request that does not expect a response
eb.send(address, body, deliveryOptions);
}
}
// replies are a one time off operation
replies.remove(address);
} else {
sendErrFrame("access_denied", socket);
}
break;
case "publish":
if (checkMatches(true, address)) {
eb.publish(address, body, deliveryOptions);
} else {
sendErrFrame("access_denied", socket);
}
break;
case "register":
if (checkMatches(false, address)) {
registry.put(address, eb.consumer(address, (Message
© 2015 - 2025 Weber Informatics LLC | Privacy Policy