Skip to content

Commit

Permalink
Fix double release in http proxy;
Browse files Browse the repository at this point in the history
Add test code
  • Loading branch information
selcarpa committed Aug 1, 2023
1 parent 09c7de5 commit 2499e25
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 51 deletions.
12 changes: 7 additions & 5 deletions src/main/kotlin/inbounds/Http.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.handler.codec.http.*
import io.netty.util.ReferenceCountUtil
import model.config.Inbound
import model.protocol.Odor
import model.protocol.Protocol
Expand All @@ -16,13 +17,13 @@ import stream.relayAndOutbound
import java.net.URI


class HttpProxyServerHandler(private val inbound: Inbound) : SimpleChannelInboundHandler<HttpRequest>() {
class HttpProxyServerHandler(private val inbound: Inbound) : SimpleChannelInboundHandler<HttpRequest>(false) {
companion object {
private val logger = KotlinLogging.logger {}
}

override fun channelInactive(ctx: ChannelHandlerContext) {
logger.warn { "[${ctx.channel().id().asShortText()}] channel inactive"}
logger.warn { "[${ctx.channel().id().asShortText()}] channel inactive" }
super.channelInactive(ctx)
}

Expand Down Expand Up @@ -83,7 +84,6 @@ class HttpProxyServerHandler(private val inbound: Inbound) : SimpleChannelInboun
}
}
)
// ReferenceCountUtil.release(encoded)
}

}
Expand All @@ -107,8 +107,10 @@ class HttpProxyServerHandler(private val inbound: Inbound) : SimpleChannelInboun
desProtocol = Protocol.TCP,
fromChannel = originCTX.channel().id().asShortText()
)
val version = request.protocolVersion()
ReferenceCountUtil.release(request)

val resolveOutbound = resolveOutbound(inbound,odor)
val resolveOutbound = resolveOutbound(inbound, odor)
resolveOutbound.ifPresent { outbound ->
relayAndOutbound(
RelayAndOutboundOp(
Expand All @@ -120,7 +122,7 @@ class HttpProxyServerHandler(private val inbound: Inbound) : SimpleChannelInboun
//write Connection Established
originCTX.writeAndFlush(
DefaultHttpResponse(
request.protocolVersion(),
version,
HttpResponseStatus(HttpResponseStatus.OK.code(), "Connection established"),
)
).also {
Expand Down
146 changes: 100 additions & 46 deletions src/test/kotlin/ProtocolTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,120 @@ import io.netty.handler.logging.LoggingHandler
import io.netty.util.CharsetUtil
import model.config.Config
import netty.NettyServer
import java.net.ServerSocket
import kotlin.test.Test
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.io.IOException
import java.net.*
import java.net.http.HttpClient
import java.net.http.HttpResponse


class ProtocolTest {
var port: Int = 0

@Test
fun mainTest() {
choosePort()
startMainServer()
Thread{
startDestinationServer()

companion object {
var httpSnoopServerPort: Int = 0

@BeforeAll
@JvmStatic
fun choosePort() {
val serverSocket = ServerSocket(0)

val port = serverSocket.getLocalPort()

serverSocket.close()

httpSnoopServerPort = port
}
}

private fun choosePort() {
val serverSocket = ServerSocket(0)
@BeforeAll
@JvmStatic
fun startDestinationServer() {
Thread{
// Configure the server.
val bossGroup: EventLoopGroup = NioEventLoopGroup(1)
val workerGroup: EventLoopGroup = NioEventLoopGroup()
try {
val b = ServerBootstrap()
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel::class.java)
.handler(LoggingHandler(LogLevel.INFO)).childHandler(object : ChannelInitializer<SocketChannel>() {
override fun initChannel(ch: SocketChannel) {
val p = ch.pipeline()
p.addLast(HttpRequestDecoder())
p.addLast(HttpResponseEncoder())
p.addLast(HttpSnoopServerHandler())
}

val port = serverSocket.getLocalPort()
});
val ch: Channel = b.bind(httpSnoopServerPort).sync().channel()
Runtime.getRuntime().addShutdownHook(Thread({
bossGroup.shutdownGracefully()
workerGroup.shutdownGracefully()
}, "Server Shutdown Thread"))
ch.closeFuture().sync()
} finally {
bossGroup.shutdownGracefully()
workerGroup.shutdownGracefully()
}
}.start()
}

serverSocket.close()
@BeforeAll
@JvmStatic
fun startMainServer() {
Config.ConfigurationUrl = "classpath:/MainTest.json5"
NettyServer.start()
}

this.port = port
}

private fun startDestinationServer() {
// Configure the server.
@Test
fun baseRequest(){
httpRequest(null)
}

// Configure the server.
val bossGroup: EventLoopGroup = NioEventLoopGroup(1)
val workerGroup: EventLoopGroup = NioEventLoopGroup()
try {
val b = ServerBootstrap()
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel::class.java)
.handler(LoggingHandler(LogLevel.INFO))
.childHandler(object : ChannelInitializer<SocketChannel>() {
override fun initChannel(ch: SocketChannel) {
val p = ch.pipeline()
p.addLast(HttpRequestDecoder())
p.addLast(HttpResponseEncoder())
p.addLast(HttpSnoopServerHandler())
}
@Test
fun viaHttpProxy() {
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("127.0.0.1", 14272))
httpRequest(proxy)
}

});
val ch: Channel = b.bind(port).sync().channel()
Runtime.getRuntime().addShutdownHook(Thread({
bossGroup.shutdownGracefully()
workerGroup.shutdownGracefully()
}, "Server Shutdown Thread"))
ch.closeFuture().sync()
} finally {
bossGroup.shutdownGracefully()
workerGroup.shutdownGracefully()
}
@Test
fun viaSocks5Proxy() {
val proxy = Proxy(Proxy.Type.SOCKS, InetSocketAddress("127.0.0.1", 14270))
httpRequest(proxy)
}

private fun startMainServer() {
Config.ConfigurationUrl = "classpath:/MainTest.json5"
NettyServer.start()
private fun httpRequest(proxy: Proxy?) {
val httpClient = if (proxy!=null){
HttpClient.newBuilder().proxy(object : ProxySelector() {
override fun select(uri: URI?): MutableList<Proxy> {
return mutableListOf(proxy)
}

override fun connectFailed(uri: URI?, sa: SocketAddress?, ioe: IOException?) {
throw ioe!!
}
}).build()
}else{
HttpClient.newBuilder().build()
}
val url = "http://127.0.0.1:${httpSnoopServerPort}"

val request: java.net.http.HttpRequest? =
java.net.http.HttpRequest.newBuilder().uri(URI.create(url)).GET().build()

try {
val response = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
val statusCode: Int = response.statusCode()
val responseBody: String = response.body()
println("Status Code: $statusCode")
println("Response Body: $responseBody")
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InterruptedException) {
e.printStackTrace()
}
}

}
Expand Down Expand Up @@ -187,6 +240,7 @@ class HttpSnoopServerHandler : SimpleChannelInboundHandler<Any?>() {
return keepAlive
}

@Suppress("OVERRIDE_DEPRECATION")
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
cause.printStackTrace()
ctx.close()
Expand Down

0 comments on commit 2499e25

Please sign in to comment.