Cleanup permissions and disconnect sequences

This commit is contained in:
md_5 2013-03-07 21:04:03 +11:00
parent 0f9cc76633
commit b6e76f4054
4 changed files with 104 additions and 84 deletions

View File

@ -16,4 +16,14 @@ public interface Connection
* @return the remote address * @return the remote address
*/ */
public InetSocketAddress getAddress(); public InetSocketAddress getAddress();
/**
* Disconnects this end of the connection for the specified reason. If this
* is an {@link ProxiedPlayer} the respective server connection will be
* closed too.
*
* @param reason the reason shown to the player / sent to the server on
* disconnect
*/
public void disconnect(String reason);
} }

View File

@ -34,6 +34,11 @@
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId>
<version>3.0.3</version>
</dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>

View File

@ -8,6 +8,7 @@ import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet1Login;
import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFAPluginMessage;
import net.md_5.bungee.packet.PacketFFKick;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ServerConnection implements Server public class ServerConnection implements Server
@ -25,6 +26,16 @@ public class ServerConnection implements Server
ch.write( new PacketFAPluginMessage( channel, data ) ); ch.write( new PacketFAPluginMessage( channel, data ) );
} }
@Override
public synchronized void disconnect(String reason)
{
if ( ch.isActive() )
{
ch.write( new PacketFFKick( reason ) );
ch.close();
}
}
@Override @Override
public InetSocketAddress getAddress() public InetSocketAddress getAddress()
{ {

View File

@ -1,13 +1,13 @@
package net.md_5.bungee; package net.md_5.bungee;
import gnu.trove.set.hash.THashSet;
import io.netty.channel.Channel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Getter; import lombok.Getter;
@ -20,12 +20,15 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.connection.DownstreamBridge;
import net.md_5.bungee.connection.UpstreamBridge;
import net.md_5.bungee.packet.*; import net.md_5.bungee.packet.*;
public final class UserConnection extends GenericConnection implements ProxiedPlayer public final class UserConnection implements ProxiedPlayer
{ {
public final Packet2Handshake handshake; public final Packet2Handshake handshake;
private final ProxyServer bungee;
private final Channel ch;
final Packet1Login forgeLogin; final Packet1Login forgeLogin;
final List<PacketFAPluginMessage> loginMessages; final List<PacketFAPluginMessage> loginMessages;
public Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>(); public Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
@ -36,7 +39,6 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
// reconnect stuff // reconnect stuff
private int clientEntityId; private int clientEntityId;
private int serverEntityId; private int serverEntityId;
private volatile boolean reconnecting;
// ping stuff // ping stuff
public int trackingPingId; public int trackingPingId;
public long pingTime; public long pingTime;
@ -44,12 +46,9 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
@Setter @Setter
private int ping = 1000; private int ping = 1000;
// Permissions // Permissions
private final Collection<String> groups = new HashSet<>(); private final Collection<String> playerGroups = new HashSet<>();
private final Map<String, Boolean> permissions = new HashMap<>(); private final THashSet<String> permissions = new THashSet<>();
private final Object permMutex = new Object(); private final Object permMutex = new Object();
// Hack for connect timings
private ServerInfo nextServer;
private volatile boolean clientConnected = true;
public UserConnection(Socket socket, PendingConnection pendingConnection, PacketStream stream, Packet2Handshake handshake, Packet1Login forgeLogin, List<PacketFAPluginMessage> loginMessages) public UserConnection(Socket socket, PendingConnection pendingConnection, PacketStream stream, Packet2Handshake handshake, Packet1Login forgeLogin, List<PacketFAPluginMessage> loginMessages)
{ {
@ -97,86 +96,76 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
target = event.getTarget(); // Update in case the event changed target target = event.getTarget(); // Update in case the event changed target
ProxyServer.getInstance().getTabListHandler().onServerChange( this ); ProxyServer.getInstance().getTabListHandler().onServerChange( this );
try
reconnecting = true;
if ( server != null )
{ {
reconnecting = true; stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
if ( server != null )
{
stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
}
ServerConnection newServer = ServerConnector.connect( this, target, true );
if ( server == null )
{
// Once again, first connection
clientEntityId = newServer.loginPacket.entityId;
serverEntityId = newServer.loginPacket.entityId;
// Set tab list size
Packet1Login s = newServer.loginPacket;
Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() );
stream.write( login );
stream.write( BungeeCord.getInstance().registerChannels() );
upBridge = new UpstreamBridge();
upBridge.start();
} else
{
try
{
downBridge.interrupt();
downBridge.join();
} catch ( InterruptedException ie )
{
}
server.disconnect( "Quitting" );
server.getInfo().removePlayer( this );
Packet1Login login = newServer.loginPacket;
serverEntityId = login.entityId;
stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) );
}
// Reconnect process has finished, lets get the player moving again
reconnecting = false;
// Add to new
target.addPlayer( this );
// Start the bridges and move on
server = newServer;
downBridge = new DownstreamBridge();
downBridge.start();
} catch ( KickException ex )
{
disconnect( ex.getMessage() );
} catch ( Exception ex )
{
disconnect( "Could not connect to server - " + Util.exception( ex ) );
} }
ServerConnection newServer = ServerConnector.connect( this, target, true );
if ( server == null )
{
// Once again, first connection
clientEntityId = newServer.loginPacket.entityId;
serverEntityId = newServer.loginPacket.entityId;
// Set tab list size
Packet1Login s = newServer.loginPacket;
Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() );
stream.write( login );
stream.write( BungeeCord.getInstance().registerChannels() );
upBridge = new UpstreamBridge();
upBridge.start();
} else
{
try
{
downBridge.interrupt();
downBridge.join();
} catch ( InterruptedException ie )
{
}
server.disconnect( "Quitting" );
server.getInfo().removePlayer( this );
Packet1Login login = newServer.loginPacket;
serverEntityId = login.entityId;
stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) );
}
// Reconnect process has finished, lets get the player moving again
reconnecting = false;
// Add to new
target.addPlayer( this );
// Start the bridges and move on
server = newServer;
} }
@Override @Override
public synchronized void disconnect(String reason) public synchronized void disconnect(String reason)
{ {
if ( clientConnected ) if ( ch.isActive() )
{ {
PlayerDisconnectEvent event = new PlayerDisconnectEvent( this ); PlayerDisconnectEvent event = new PlayerDisconnectEvent( this );
ProxyServer.getInstance().getPluginManager().callEvent( event ); bungee.getPluginManager().callEvent( event );
ProxyServer.getInstance().getTabListHandler().onDisconnect( this ); bungee.getTabListHandler().onDisconnect( this );
ProxyServer.getInstance().getPlayers().remove( this ); bungee.getPlayers().remove( this );
ch.write( new PacketFFKick( reason ) );
ch.close();
super.disconnect( reason );
if ( server != null ) if ( server != null )
{ {
server.getInfo().removePlayer( this ); server.getInfo().removePlayer( this );
server.disconnect( "Quitting" ); server.disconnect( "Quitting" );
ProxyServer.getInstance().getReconnectHandler().setServer( this ); bungee.getReconnectHandler().setServer( this );
} }
clientConnected = false;
} }
} }
@ -189,20 +178,20 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
@Override @Override
public void sendData(String channel, byte[] data) public void sendData(String channel, byte[] data)
{ {
server.packetQueue.add( new PacketFAPluginMessage( channel, data ) ); ch.write( new PacketFAPluginMessage( channel, data ) );
} }
@Override @Override
public InetSocketAddress getAddress() public InetSocketAddress getAddress()
{ {
return (InetSocketAddress) socket.getRemoteSocketAddress(); return (InetSocketAddress) ch.remoteAddress();
} }
@Override @Override
@Synchronized("permMutex") @Synchronized("permMutex")
public Collection<String> getGroups() public Collection<String> getGroups()
{ {
return Collections.unmodifiableCollection( groups ); return Collections.unmodifiableCollection( playerGroups );
} }
@Override @Override
@ -211,8 +200,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
{ {
for ( String group : groups ) for ( String group : groups )
{ {
this.groups.add( group ); playerGroups.add( group );
for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) ) for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) )
{ {
setPermission( permission, true ); setPermission( permission, true );
} }
@ -225,8 +214,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
{ {
for ( String group : groups ) for ( String group : groups )
{ {
this.groups.remove( group ); playerGroups.remove( group );
for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) ) for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) )
{ {
setPermission( permission, false ); setPermission( permission, false );
} }
@ -237,14 +226,19 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
@Synchronized("permMutex") @Synchronized("permMutex")
public boolean hasPermission(String permission) public boolean hasPermission(String permission)
{ {
Boolean val = permissions.get( permission ); return permissions.contains( permission );
return ( val == null ) ? false : val;
} }
@Override @Override
@Synchronized("permMutex") @Synchronized("permMutex")
public void setPermission(String permission, boolean value) public void setPermission(String permission, boolean value)
{ {
permissions.put( permission, value ); if ( value )
{
permissions.add( permission );
} else
{
permissions.remove( permission );
}
} }
} }