diff --git a/api/pom.xml b/api/pom.xml
index 0a8ea1954..4d1e24d19 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -25,12 +25,6 @@
14.0.1
compile
-
- com.ning
- async-http-client
- 1.7.17
- compile
-
net.md-5
bungeecord-event
diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java
index f74645719..9c4720adc 100644
--- a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java
+++ b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java
@@ -2,7 +2,6 @@ package net.md_5.bungee.api;
import net.md_5.bungee.api.plugin.PluginManager;
import com.google.common.base.Preconditions;
-import com.ning.http.client.AsyncHttpClient;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.Collection;
@@ -218,15 +217,6 @@ public abstract class ProxyServer
*/
public abstract TaskScheduler getScheduler();
- /**
- * Gets the the web client used by this proxy to facilitate making web
- * requests. Care should be taken to ensure that all operations are non
- * blocking where applicable.
- *
- * @return the server's {@link AsyncHttpClient} instance
- */
- public abstract AsyncHttpClient getHttpClient();
-
/**
* Get the current number of connected users. The default implementation is
* more efficient than {@link #getPlayers()} as it does not take a lock or
diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
index 66380ff02..22bcd4a3a 100644
--- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
+++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
@@ -6,10 +6,6 @@ import net.md_5.bungee.reconnect.SQLReconnectHandler;
import net.md_5.bungee.scheduler.BungeeScheduler;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gson.Gson;
-import com.ning.http.client.AsyncHttpClient;
-import com.ning.http.client.AsyncHttpClientConfig;
-import com.ning.http.client.providers.netty.NettyAsyncHttpProvider;
-import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
@@ -123,11 +119,6 @@ public class BungeeCord extends ProxyServer
@Getter
private final TaskScheduler scheduler = new BungeeScheduler();
@Getter
- private final AsyncHttpClient httpClient = new AsyncHttpClient(
- new NettyAsyncHttpProvider(
- new AsyncHttpClientConfig.Builder().setAsyncHttpClientProviderConfig(
- new NettyAsyncHttpProviderConfig().addProperty( NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE, executors ) ).setExecutorService( executors ).build() ) );
- @Getter
private ConsoleReader consoleReader;
@Getter
private final Logger logger;
@@ -302,7 +293,6 @@ public class BungeeCord extends ProxyServer
{
BungeeCord.this.isRunning = false;
- httpClient.close();
executors.shutdown();
stopListeners();
diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
index 21e258d54..fab717f62 100644
--- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
+++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
@@ -1,14 +1,11 @@
package net.md_5.bungee.connection;
import com.google.common.base.Preconditions;
-import com.ning.http.client.AsyncCompletionHandler;
-import com.ning.http.client.Response;
import io.netty.util.concurrent.ScheduledFuture;
import java.io.DataInput;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.net.URLEncoder;
-import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
@@ -33,6 +30,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.LoginEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.event.ProxyPingEvent;
+import net.md_5.bungee.http.HttpClient;
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.netty.CipherDecoder;
@@ -258,35 +256,37 @@ public class InitialHandler extends PacketHandler implements PendingConnection
String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash;
- bungee.getHttpClient().prepareGet( authURL ).execute( new AsyncCompletionHandler()
+
+ Callback handler = new Callback()
{
@Override
- public Response onCompleted(Response response) throws Exception
+ public void done(String result, Throwable error)
{
- if ( "YES".equals( response.getResponseBody() ) )
+ if ( error == null )
{
- finish();
+ if ( "YES".equals( result ) )
+ {
+ finish();
+ } else
+ {
+ disconnect( "Not authenticated with Minecraft.net" );
+ }
} else
{
- disconnect( "Not authenticated with Minecraft.net" );
+ disconnect( bungee.getTranslation( "mojang_fail" ) );
+ bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error );
}
- return response;
}
+ };
- @Override
- public void onThrowable(Throwable t)
- {
- disconnect( bungee.getTranslation( "mojang_fail" ) );
- bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", t );
- }
- } );
+ HttpClient.get( authURL, ch.getHandle().eventLoop(), handler );
} else
{
finish();
}
}
- private void finish() throws GeneralSecurityException
+ private void finish()
{
// Check for multiple connections
ProxiedPlayer old = bungee.getPlayer( handshake.getUsername() );
diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java
index 65d3c246c..c4ffc5390 100644
--- a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java
+++ b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java
@@ -4,7 +4,8 @@ import com.google.common.base.Preconditions;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.EventLoopGroup;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
@@ -13,21 +14,22 @@ import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import java.net.URI;
-import lombok.RequiredArgsConstructor;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import net.md_5.bungee.api.Callback;
-@RequiredArgsConstructor
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class HttpClient
{
- private final EventLoopGroup eventLoop;
+ public static int TIMEOUT = 5000;
- public static void main(String[] args)
+ public static void get(String url, EventLoop eventLoop, final Callback callback)
{
- new HttpClient( new NioEventLoopGroup( 1 ) ).get( "https://session.minecraft.net/" );
- }
+ Preconditions.checkNotNull( url, "url" );
+ Preconditions.checkNotNull( eventLoop, "eventLoop" );
+ Preconditions.checkNotNull( callback, "callBack" );
- public void get(String url)
- {
final URI uri = URI.create( url );
Preconditions.checkNotNull( uri.getScheme(), "scheme" );
@@ -56,16 +58,20 @@ public class HttpClient
{
if ( future.isSuccess() )
{
- HttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath() );
+ String path = uri.getRawPath() + ( ( uri.getRawQuery() == null ) ? "" : "?" + uri.getRawQuery() );
+
+ HttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, path );
request.headers().set( HttpHeaders.Names.HOST, uri.getHost() );
future.channel().write( request );
} else
{
+ callback.done( null, future.cause() );
}
}
};
- new Bootstrap().channel( NioSocketChannel.class ).group( eventLoop ).handler( new HttpInitializer( ssl ) ).remoteAddress( uri.getHost(), port ).connect().addListener( future );
+ new Bootstrap().channel( NioSocketChannel.class ).group( eventLoop ).handler( new HttpInitializer( callback, ssl ) ).
+ option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( uri.getHost(), port ).connect().addListener( future );
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java b/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java
index dba073b43..c7e4dcfc1 100644
--- a/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java
+++ b/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java
@@ -8,28 +8,53 @@ import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.LastHttpContent;
import java.nio.charset.Charset;
+import lombok.RequiredArgsConstructor;
+import net.md_5.bungee.api.Callback;
+@RequiredArgsConstructor
public class HttpHandler extends SimpleChannelInboundHandler
{
+ private final Callback callback;
+ private final StringBuilder buffer = new StringBuilder();
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
+ {
+ try
+ {
+ callback.done( null, cause );
+ } finally
+ {
+ ctx.channel().close();
+ }
+ }
+
@Override
protected void messageReceived(ChannelHandlerContext ctx, HttpObject msg) throws Exception
{
if ( msg instanceof HttpResponse )
{
HttpResponse response = (HttpResponse) msg;
- if ( response.getStatus() != HttpResponseStatus.OK )
+ if ( response.getStatus().code() != 200 )
{
+ throw new IllegalStateException( "Expected HTTP response 200 OK, got " + response.getStatus() );
}
}
if ( msg instanceof HttpContent )
{
HttpContent content = (HttpContent) msg;
- String s = content.content().toString( Charset.forName( "UTF-8" ) );
+ buffer.append( content.content().toString( Charset.forName( "UTF-8" ) ) );
if ( msg instanceof LastHttpContent )
{
- ctx.channel().close();
+ try
+ {
+ callback.done( buffer.toString(), null );
+ } finally
+ {
+ ctx.channel().close();
+ }
}
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpInitializer.java b/proxy/src/main/java/net/md_5/bungee/http/HttpInitializer.java
index 196791077..327bf89d3 100644
--- a/proxy/src/main/java/net/md_5/bungee/http/HttpInitializer.java
+++ b/proxy/src/main/java/net/md_5/bungee/http/HttpInitializer.java
@@ -4,20 +4,25 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import lombok.RequiredArgsConstructor;
+import net.md_5.bungee.api.Callback;
@RequiredArgsConstructor
public class HttpInitializer extends ChannelInitializer
{
+ private final Callback callback;
private final boolean ssl;
@Override
protected void initChannel(Channel ch) throws Exception
{
+ ch.pipeline().addLast( "timeout", new ReadTimeoutHandler( HttpClient.TIMEOUT, TimeUnit.MILLISECONDS ) );
if ( ssl )
{
SSLContext context = SSLContext.getInstance( "TLS" );
@@ -32,6 +37,6 @@ public class HttpInitializer extends ChannelInitializer
ch.pipeline().addLast( "ssl", new SslHandler( engine ) );
}
ch.pipeline().addLast( "http", new HttpClientCodec() );
- ch.pipeline().addLast( "handler", new HttpHandler() );
+ ch.pipeline().addLast( "handler", new HttpHandler( callback ) );
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/log/LogDispatcher.java b/proxy/src/main/java/net/md_5/bungee/log/LogDispatcher.java
index 2ff69b2f9..f1ccd4f6d 100644
--- a/proxy/src/main/java/net/md_5/bungee/log/LogDispatcher.java
+++ b/proxy/src/main/java/net/md_5/bungee/log/LogDispatcher.java
@@ -12,7 +12,7 @@ public class LogDispatcher extends Thread
public LogDispatcher(BungeeLogger logger)
{
- super( "BungeeCord Logger Thread - " + logger );
+ super( "BungeeCord Logger Thread" );
this.logger = logger;
}