解决通过mc基岩 udp代理,同一个代理端口只能有一个人连接的问题
This commit is contained in:
+7
@@ -59,6 +59,13 @@ public class ProxyTunnelChannelHandler extends SimpleChannelInboundHandler<Proxy
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
{
|
||||
// udp情况下不能使用visitorChannel上的visitorId,因为所有的用户都是走的同一个VisitorChannel
|
||||
String visitorId = ctx.channel().attr(Constants.VISITOR_ID).get();
|
||||
// 删除Udp的SocketAddress
|
||||
ProxyUtil.removeSocketAddressByVisitorId(visitorId);
|
||||
}
|
||||
|
||||
Channel visitorChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
|
||||
if (null != visitorChannel) {
|
||||
Integer licenseId = ctx.channel().attr(Constants.LICENSE_ID).get();
|
||||
|
||||
+13
-6
@@ -35,7 +35,12 @@ public class UdpVisitorChannelHandler extends SimpleChannelInboundHandler<Datagr
|
||||
datagramPacket.content().readBytes(bytes);
|
||||
datagramPacket.content().resetReaderIndex();
|
||||
ProxyAttachment proxyAttachment = new ProxyAttachment(ctx.channel(), bytes, (channel, buf) -> {
|
||||
Channel proxyChannel = channel.attr(Constants.NEXT_CHANNEL).get();
|
||||
String visitorId = ProxyUtil.getVisitorIdBySocketAddress(datagramPacket.sender());
|
||||
if (StrUtil.isBlank(visitorId)) {
|
||||
return;
|
||||
}
|
||||
Channel proxyChannel = ProxyUtil.getTunnelChannelByVisitorId(visitorId);
|
||||
// Channel proxyChannel = channel.attr(Constants.NEXT_CHANNEL).get();
|
||||
|
||||
if (null == proxyChannel) {
|
||||
// // 该端口还没有代理客户端
|
||||
@@ -50,7 +55,6 @@ public class UdpVisitorChannelHandler extends SimpleChannelInboundHandler<Datagr
|
||||
Long proxyTimeoutMs = proxyChannel.attr(Constants.PROXY_TIMEOUT_MS).get();
|
||||
|
||||
// 转发代理数据
|
||||
String visitorId = ProxyUtil.getVisitorIdByChannel(channel);
|
||||
proxyChannel.writeAndFlush(ProxyMessage.buildUdpTransferMessage(new ProxyMessage.UdpBaseInfo()
|
||||
.setVisitorId(visitorId)
|
||||
.setVisitorIp(datagramPacket.sender().getAddress().getHostAddress())
|
||||
@@ -66,8 +70,9 @@ public class UdpVisitorChannelHandler extends SimpleChannelInboundHandler<Datagr
|
||||
Solon.context().getBean(FlowReportService.class).addWriteByte(visitorChannelAttachInfo.getLicenseId(), bytes.length);
|
||||
});
|
||||
|
||||
Channel proxyChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
|
||||
if (null != proxyChannel && proxyChannel.isActive()) {
|
||||
String visitorId = ProxyUtil.getVisitorIdBySocketAddress(datagramPacket.sender());
|
||||
Channel proxyChannel = ProxyUtil.getTunnelChannelByVisitorId(visitorId);
|
||||
if (StrUtil.isNotBlank(visitorId) && null != proxyChannel && proxyChannel.isActive()) {
|
||||
// UDP代理隧道已就绪,直接转发
|
||||
proxyAttachment.execute();
|
||||
return;
|
||||
@@ -96,8 +101,10 @@ public class UdpVisitorChannelHandler extends SimpleChannelInboundHandler<Datagr
|
||||
// // 用户连接到代理服务器时,设置用户连接不可读,等待代理后端服务器连接成功后再改变为可读状态
|
||||
// visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);
|
||||
|
||||
// TODO UDP此处叫visitor似有不妥,与TCP不同,2.x重构思考
|
||||
String visitorId = ProxyUtil.newVisitorId();
|
||||
// UDP场景下,一个visitorId并不对应一个visitorChannel,所有visitor共用一个visitorChannel
|
||||
visitorId = ProxyUtil.newVisitorId();
|
||||
// 设置udp发送方的地址
|
||||
ProxyUtil.setVisitorIdToSocketAddressMap(visitorId, datagramPacket.sender());
|
||||
// 此处需要和tcp分开
|
||||
ProxyUtil.addVisitorChannelToCmdChannel(NetworkProtocolEnum.UDP, cmdChannel, visitorId, visitorChannel, sa.getPort());
|
||||
ProxyUtil.addProxyConnectAttachment(visitorId, proxyAttachment);
|
||||
|
||||
+3
-1
@@ -87,7 +87,9 @@ public class UdpProxyMessageConnectHandler implements ProxyMessageHandler {
|
||||
ctx.channel().attr(Constants.TARGET_PORT).set(portMappingDO.getClientPort());
|
||||
ctx.channel().attr(Constants.PROXY_RESPONSES).set(portMappingDO.getProxyResponses());
|
||||
ctx.channel().attr(Constants.PROXY_TIMEOUT_MS).set(portMappingDO.getProxyTimeoutMs());
|
||||
visitorChannel.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
|
||||
// 所有udb visitor共用一个visitorChannel,设置这个没啥用
|
||||
// visitorChannel.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
|
||||
ProxyUtil.setVisitorIdToTunnelChannelMap(udpBaseInfo.getVisitorId(), ctx.channel());
|
||||
visitorChannel.attr(Constants.IS_UDP_KEY).set(Boolean.TRUE);
|
||||
// // 代理客户端与后端服务器连接成功,修改用户连接为可读状态
|
||||
// visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);
|
||||
|
||||
+21
-23
@@ -31,33 +31,31 @@ public class UdpProxyMessageTransferHandler implements ProxyMessageHandler {
|
||||
log.debug("[UDP transfer]info:{} data:{}", proxyMessage.getInfo(), new String(proxyMessage.getData()));
|
||||
|
||||
Channel visitorChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
|
||||
if (null != visitorChannel) {
|
||||
if (null == visitorChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!visitorChannel.isWritable()) {
|
||||
//自己不可写,通道可以读,让通道关闭读
|
||||
//自己可写,通道不可以读,让通道打开读
|
||||
if (ctx.channel().config().isAutoRead()) {
|
||||
ctx.channel().config().setAutoRead(false);
|
||||
}
|
||||
} else {
|
||||
if (ctx.channel().config().isAutoRead()) {
|
||||
ctx.channel().config().setAutoRead(true);
|
||||
}
|
||||
if (!visitorChannel.isWritable()) {
|
||||
//自己不可写,通道可以读,让通道关闭读
|
||||
//自己可写,通道不可以读,让通道打开读
|
||||
if (ctx.channel().config().isAutoRead()) {
|
||||
ctx.channel().config().setAutoRead(false);
|
||||
}
|
||||
} else {
|
||||
if (ctx.channel().config().isAutoRead()) {
|
||||
ctx.channel().config().setAutoRead(true);
|
||||
}
|
||||
}
|
||||
|
||||
// InetSocketAddress address = new InetSocketAddress(udpBaseInfo.getVisitorIp(), udpBaseInfo.getVisitorPort());
|
||||
// ByteBuf byteBuf = Unpooled.copiedBuffer(proxyMessage.getData());
|
||||
// visitorChannel.writeAndFlush(new DatagramPacket(byteBuf, address));
|
||||
InetSocketAddress address = ctx.channel().attr(Constants.SENDER).get();
|
||||
if (null != address) {
|
||||
visitorChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(proxyMessage.getData()), address));
|
||||
}
|
||||
InetSocketAddress address = ctx.channel().attr(Constants.SENDER).get();
|
||||
if (null != address) {
|
||||
visitorChannel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(proxyMessage.getData()), address));
|
||||
}
|
||||
|
||||
// 增加流量计数(TODO 如果UDP映射服务端端口修改,这个似乎不准)
|
||||
Integer licenseId = visitorChannel.attr(Constants.LICENSE_ID).get();
|
||||
if (null != licenseId) {
|
||||
Solon.context().getBean(FlowReportService.class).addReadByte(licenseId, proxyMessage.getData().length);
|
||||
}
|
||||
// 增加流量计数(TODO 如果UDP映射服务端端口修改,这个似乎不准)
|
||||
Integer licenseId = visitorChannel.attr(Constants.LICENSE_ID).get();
|
||||
if (null != licenseId) {
|
||||
Solon.context().getBean(FlowReportService.class).addReadByte(licenseId, proxyMessage.getData().length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
@@ -13,6 +13,7 @@ import io.netty.channel.Channel;
|
||||
import io.netty.util.AttributeKey;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -72,6 +73,18 @@ public class ProxyUtil {
|
||||
* licenseId - 客户端Id映射
|
||||
*/
|
||||
private static Map<Integer, String> licenseIdToClientIdMap = new HashMap<>();
|
||||
/**
|
||||
* visitorId - SocketAddress映射
|
||||
*/
|
||||
private static Map<String, SocketAddress> visitorIdToSocketAddressMap = new HashMap<>();
|
||||
/**
|
||||
* SocketAddress - visitorId 映射
|
||||
*/
|
||||
private static Map<SocketAddress, String> socketAddressToVisitorIdMap = new HashMap<>();
|
||||
/**
|
||||
* visitorId - tunnelChannel 映射
|
||||
*/
|
||||
private static Map<String, Channel> visitorIdToTunnelChannelMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 初始化代理信息
|
||||
@@ -479,4 +492,34 @@ public class ProxyUtil {
|
||||
public static void removeClientIdByLicenseId(Integer licenseId) {
|
||||
licenseIdToClientIdMap.remove(licenseId);
|
||||
}
|
||||
|
||||
public static void setVisitorIdToSocketAddressMap(String visitorId, SocketAddress socketAddress) {
|
||||
visitorIdToSocketAddressMap.put(visitorId, socketAddress);
|
||||
socketAddressToVisitorIdMap.put(socketAddress, visitorId);
|
||||
}
|
||||
|
||||
public static SocketAddress getSocketAddressByVisitorId(String visitorId) {
|
||||
return visitorIdToSocketAddressMap.get(visitorId);
|
||||
}
|
||||
|
||||
public static void removeSocketAddressByVisitorId(String visitorId) {
|
||||
SocketAddress socketAddress = visitorIdToSocketAddressMap.get(visitorId);
|
||||
visitorIdToSocketAddressMap.remove(visitorId);
|
||||
socketAddressToVisitorIdMap.remove(socketAddress);
|
||||
|
||||
visitorIdToTunnelChannelMap.remove(visitorId);
|
||||
}
|
||||
|
||||
public static String getVisitorIdBySocketAddress(SocketAddress socketAddress) {
|
||||
return socketAddressToVisitorIdMap.get(socketAddress);
|
||||
}
|
||||
|
||||
public static void setVisitorIdToTunnelChannelMap(String visitorId, Channel tunnelChannel) {
|
||||
visitorIdToTunnelChannelMap.put(visitorId, tunnelChannel);
|
||||
}
|
||||
|
||||
public static Channel getTunnelChannelByVisitorId(String visitorId) {
|
||||
return visitorIdToTunnelChannelMap.get(visitorId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user