/* * Copyright 2017 ZhangJiupeng * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cc.agentx.server.net.nio; import cc.agentx.protocol.request.XRequest; import cc.agentx.protocol.request.XRequestResolver; import cc.agentx.wrapper.Wrapper; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.socket.DatagramPacket; import io.netty.util.ReferenceCountUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.net.InetSocketAddress; public class Udp2TcpHandler extends ChannelInboundHandlerAdapter { private static final InternalLogger log; static { log = InternalLoggerFactory.getInstance(Udp2TcpHandler.class); } private final XRequestResolver requestResolver; private final Wrapper wrapper; public Udp2TcpHandler(XRequestResolver requestResolver, Wrapper wrapper) { this.requestResolver = requestResolver; this.wrapper = wrapper; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { DatagramPacket datagram = (DatagramPacket) msg; InetSocketAddress sender = datagram.sender(); Channel tcpChannel = XChannelMapper.getTcpChannel(sender); if (tcpChannel == null) { // udpSource not registered, actively discard this packet // without register, an udp channel cannot relate to any tcp channel, so remove the map XChannelMapper.removeUdpMapping(sender); log.warn("Bad Connection! (unexpected udp datagram from {})", sender); } else if (tcpChannel.isActive()) { ByteBuf byteBuf = datagram.content(); try { if (!byteBuf.hasArray()) { byte[] bytes = new byte[byteBuf.readableBytes()]; byteBuf.getBytes(0, bytes); log.info("\t Proxy << Target \tFrom {}:{}", sender.getHostString(), sender.getPort()); // write udp payload via tcp channel tcpChannel.writeAndFlush(Unpooled.wrappedBuffer(wrapper.wrap(requestResolver.wrap(XRequest.Channel.UDP, bytes)))); log.info("\tClient << Proxy \tGet [{} bytes]", bytes.length); } } finally { ReferenceCountUtil.release(msg); } } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.warn("\tBad Connection! ({})", cause.getMessage()); XChannelMapper.closeChannelGracefullyByUdpChannel(ctx.channel()); } }