/*
Copyright (C) 2011 monte
This file is part of PSP NetParty.
PSP NetParty is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package pspnetparty.lib.engine;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import pspnetparty.lib.CountDownSynchronizer;
import pspnetparty.lib.Utility;
import pspnetparty.lib.constants.ProtocolConstants;
import pspnetparty.lib.socket.AsyncTcpServer;
import pspnetparty.lib.socket.AsyncUdpServer;
import pspnetparty.lib.socket.IProtocol;
import pspnetparty.lib.socket.IProtocolDriver;
import pspnetparty.lib.socket.IProtocolMessageHandler;
import pspnetparty.lib.socket.IServerListener;
import pspnetparty.lib.socket.ISocketConnection;
import pspnetparty.lib.socket.PacketData;
import pspnetparty.lib.socket.TextProtocolDriver;
public class MyRoomEngine {
private ConcurrentSkipListMap<String, RoomProtocolDriver> playersByName;
private HashMap<String, TunnelProtocolDriver> tunnelsByMacAddress;
private HashMap<String, Object> masterMacAddresses;
private final Object placeHolderValueObject = new Object();
private ConcurrentHashMap<InetSocketAddress, TunnelProtocolDriver> notYetLinkedTunnels;
private String masterName;
private String masterSsid = "";
private IMyRoomMasterHandler myRoomMasterHandler;
private long createdTime;
private int maxPlayers = 4;
private String title;
private String password = "";
private String description = "";
private String remarks = "";
private boolean isMacAdressBlackListEnabled = false;
private HashSet<String> macAddressWhiteList = new HashSet<String>();
private boolean isMacAdressWhiteListEnabled = false;
private HashSet<String> macAddressBlackList = new HashSet<String>();
private String roomMasterAuthCode;
private boolean allowEmptyMasterNameLogin = true;
private AsyncTcpServer tcpServer;
private AsyncUdpServer udpServer;
private boolean isStarted = false;
private CountDownSynchronizer countDownSynchronizer;
public MyRoomEngine(IMyRoomMasterHandler masterHandler) {
this.myRoomMasterHandler = masterHandler;
playersByName = new ConcurrentSkipListMap<String, MyRoomEngine.RoomProtocolDriver>();
tunnelsByMacAddress = new HashMap<String, TunnelProtocolDriver>();
masterMacAddresses = new HashMap<String, Object>();
notYetLinkedTunnels = new ConcurrentHashMap<InetSocketAddress, TunnelProtocolDriver>(16, 0.75f, 2);
IServerListener listener = new IServerListener() {
@Override
public void serverStartupFinished() {
if (countDownSynchronizer.countDown() == 0) {
isStarted = true;
roomMasterAuthCode = Utility.makeAuthCode();
createdTime = System.currentTimeMillis();
myRoomMasterHandler.roomOpened();
}
}
@Override
public void serverShutdownFinished() {
if (countDownSynchronizer.countDown() == 0) {
isStarted = false;
myRoomMasterHandler.roomClosed();
}
}
@Override
public void log(String message) {
myRoomMasterHandler.log(message);
}
};
tcpServer = new AsyncTcpServer(40000);
tcpServer.addServerListener(listener);
tcpServer.addProtocol(new RoomProtocol());
TunnelProtocol tunnelProtocol = new TunnelProtocol();
tcpServer.addProtocol(tunnelProtocol);
udpServer = new AsyncUdpServer();
udpServer.addServerListener(listener);
udpServer.addProtocol(tunnelProtocol);
}
public boolean isStarted() {
return isStarted;
}
public void openRoom(int port, String masterName) throws IOException {
if (isStarted())
throw new IOException();
if (Utility.isEmpty(masterName) || Utility.isEmpty(title))
throw new IOException();
this.masterName = masterName;
playersByName.clear();
notYetLinkedTunnels.clear();
tunnelsByMacAddress.clear();
masterMacAddresses.clear();
macAddressWhiteList.clear();
macAddressBlackList.clear();
countDownSynchronizer = new CountDownSynchronizer(2);
InetSocketAddress bindAddress = new InetSocketAddress(port);
tcpServer.startListening(bindAddress);
udpServer.startListening(bindAddress);
}
public void closeRoom() {
if (!isStarted())
return;
for (Entry<String, RoomProtocolDriver> e : playersByName.entrySet()) {
RoomProtocolDriver d = e.getValue();
d.getConnection().disconnect();
}
countDownSynchronizer = new CountDownSynchronizer(2);
tcpServer.stopListening();
udpServer.stopListening();
}
public void enableMacAddressWhiteList(boolean enable) {
isMacAdressWhiteListEnabled = enable;
}
public void addMacAddressToWhiteList(String macAddress) {
macAddressWhiteList.add(macAddress);
}
public void removeMacAddressFromWhiteList(String macAddress) {
macAddressWhiteList.remove(macAddress);
}
public void enableMacAddressBlackList(boolean enable) {
isMacAdressBlackListEnabled = enable;
}
public void addMacAddressToBlackList(String macAddress) {
macAddressBlackList.add(macAddress);
}
public void removeMacAddressFromBlackList(String macAddress) {
macAddressBlackList.remove(macAddress);
}
private void appendRoomInfo(StringBuilder sb) {
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(masterName);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(maxPlayers);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(title);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(password);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(createdTime);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(description);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(remarks);
}
private void appendNotifyUserList(StringBuilder sb) {
sb.append(ProtocolConstants.Room.NOTIFY_USER_LIST);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(masterName);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(masterSsid);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(p.name);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(p.ssid);
}
}
public void updateRoom() {
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.NOTIFY_ROOM_UPDATED);
appendRoomInfo(sb);
ByteBuffer buffer = Utility.encode(sb);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
buffer.position(0);
p.getConnection().send(buffer);
}
}
public void kickPlayer(String name) {
RoomProtocolDriver kickedPlayer = playersByName.remove(name);
if (kickedPlayer == null)
return;
ByteBuffer buffer = Utility.encode(ProtocolConstants.Room.NOTIFY_ROOM_PLAYER_KICKED + TextProtocolDriver.ARGUMENT_SEPARATOR + name);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
buffer.position(0);
p.getConnection().send(buffer);
}
if (kickedPlayer.tunnel != null)
notYetLinkedTunnels.remove(kickedPlayer.tunnel.getConnection().getRemoteAddress());
buffer = Utility.encode(ProtocolConstants.Room.NOTIFY_ROOM_PLAYER_KICKED + TextProtocolDriver.ARGUMENT_SEPARATOR + name);
kickedPlayer.getConnection().send(buffer);
kickedPlayer.getConnection().disconnect();
}
public void sendChat(String text) {
processChat(masterName, text);
}
public void informSSID(String ssid) {
masterSsid = ssid != null ? ssid : "";
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.NOTIFY_SSID_CHANGED);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(masterName);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(masterSsid);
ByteBuffer buffer = Utility.encode(sb);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
buffer.position(0);
p.getConnection().send(buffer);
}
}
private void processChat(String player, String chat) {
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.COMMAND_CHAT);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(player);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(chat);
ByteBuffer buffer = Utility.encode(sb);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
buffer.position(0);
p.getConnection().send(buffer);
}
myRoomMasterHandler.chatReceived(player, chat);
}
public String getAuthCode() {
return roomMasterAuthCode;
}
public int getMaxPlayers() {
return maxPlayers;
}
public void setMaxPlayers(int maxPlayers) {
if (maxPlayers < 2)
throw new IllegalArgumentException();
this.maxPlayers = maxPlayers;
}
public long getCreatedTime() {
return createdTime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
if (Utility.isEmpty(title))
throw new IllegalArgumentException();
this.title = title;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
if (Utility.isEmpty(password))
password = "";
this.password = password;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
if (Utility.isEmpty(description))
description = "";
this.description = description;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
if (Utility.isEmpty(remarks))
remarks = "";
this.remarks = remarks;
}
public boolean isAllowEmptyMasterNameLogin() {
return allowEmptyMasterNameLogin;
}
public void setAllowEmptyMasterNameLogin(boolean allowEmptyMasterNameLogin) {
this.allowEmptyMasterNameLogin = allowEmptyMasterNameLogin;
}
private class RoomProtocol implements IProtocol {
@Override
public String getProtocol() {
return ProtocolConstants.PROTOCOL_ROOM;
}
@Override
public IProtocolDriver createDriver(ISocketConnection connection) {
RoomProtocolDriver driver = new RoomProtocolDriver(connection);
return driver;
}
@Override
public void log(String message) {
myRoomMasterHandler.log(message);
}
}
private class RoomProtocolDriver extends TextProtocolDriver {
private String name;
private TunnelProtocolDriver tunnel;
private String ssid = "";
private RoomProtocolDriver(ISocketConnection connection) {
super(connection, loginHandlers);
}
@Override
public void log(String message) {
myRoomMasterHandler.log(message);
}
@Override
public void connectionDisconnected() {
if (tunnel != null) {
tunnel = null;
}
if (!Utility.isEmpty(name)) {
playersByName.remove(name);
ByteBuffer buffer = Utility
.encode(ProtocolConstants.Room.NOTIFY_USER_EXITED + TextProtocolDriver.ARGUMENT_SEPARATOR + name);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
buffer.position(0);
p.getConnection().send(buffer);
}
myRoomMasterHandler.playerExited(name);
}
}
@Override
public void errorProtocolNumber(String number) {
}
}
private HashMap<String, IProtocolMessageHandler> loginHandlers = new HashMap<String, IProtocolMessageHandler>();
private HashMap<String, IProtocolMessageHandler> sessionHandlers = new HashMap<String, IProtocolMessageHandler>();
{
loginHandlers.put(ProtocolConstants.Room.COMMAND_LOGIN, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
RoomProtocolDriver player = (RoomProtocolDriver) driver;
// LI loginName "masterName" password
String[] tokens = argument.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1);
String loginName = tokens[0];
if (loginName.length() == 0) {
return false;
}
String loginRoomMasterName = tokens[1];
if (loginRoomMasterName.length() == 0) {
if (!allowEmptyMasterNameLogin) {
return false;
}
} else if (!loginRoomMasterName.equals(masterName)) {
return false;
}
String sentPassword = tokens.length == 2 ? null : tokens[2];
if (!Utility.isEmpty(MyRoomEngine.this.password)) {
if (sentPassword == null) {
player.getConnection().send(Utility.encode(ProtocolConstants.Room.NOTIFY_ROOM_PASSWORD_REQUIRED));
return true;
}
if (!MyRoomEngine.this.password.equals(sentPassword)) {
player.getConnection().send(Utility.encode(ProtocolConstants.Room.ERROR_LOGIN_PASSWORD_FAIL));
return true;
}
}
if (masterName.equals(loginName)) {
player.getConnection().send(Utility.encode(ProtocolConstants.Room.ERROR_LOGIN_DUPLICATED_NAME));
return false;
}
if (playersByName.size() >= maxPlayers - 1) {
// 最大人数を超えたので接続を拒否します
player.getConnection().send(Utility.encode(ProtocolConstants.Room.ERROR_LOGIN_BEYOND_CAPACITY));
return false;
}
if (playersByName.putIfAbsent(loginName, player) != null) {
// 同名のユーザーが存在するので接続を拒否します
player.getConnection().send(Utility.encode(ProtocolConstants.Room.ERROR_LOGIN_DUPLICATED_NAME));
return false;
}
player.setMessageHandlers(sessionHandlers);
player.name = loginName;
ByteBuffer buffer = Utility.encode(ProtocolConstants.Room.NOTIFY_USER_ENTERED + TextProtocolDriver.ARGUMENT_SEPARATOR
+ loginName);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
if (p != player) {
buffer.position(0);
p.getConnection().send(buffer);
}
}
myRoomMasterHandler.playerEntered(loginName);
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.COMMAND_LOGIN);
appendRoomInfo(sb);
sb.append(TextProtocolDriver.MESSAGE_SEPARATOR);
appendNotifyUserList(sb);
player.getConnection().send(Utility.encode(sb));
return true;
}
});
loginHandlers.put(ProtocolConstants.Room.COMMAND_CONFIRM_AUTH_CODE, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
// CAC masterName authCode
String[] tokens = argument.split(TextProtocolDriver.ARGUMENT_SEPARATOR, -1);
if (tokens.length != 2)
return false;
String masterName = tokens[0];
String authCode = tokens[1];
if (masterName.equals(MyRoomEngine.this.masterName) && authCode.equals(roomMasterAuthCode)) {
driver.getConnection().send(Utility.encode(ProtocolConstants.Room.COMMAND_CONFIRM_AUTH_CODE));
} else {
driver.getConnection().send(Utility.encode(ProtocolConstants.Room.ERROR_CONFIRM_INVALID_AUTH_CODE));
}
return false;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_CHAT, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
RoomProtocolDriver player = (RoomProtocolDriver) driver;
processChat(player.name, argument);
return true;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_PING, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
driver.getConnection().send(
Utility.encode(ProtocolConstants.Room.COMMAND_PINGBACK + TextProtocolDriver.ARGUMENT_SEPARATOR + argument));
return true;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_INFORM_PING, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
RoomProtocolDriver state = (RoomProtocolDriver) driver;
try {
int ping = Integer.parseInt(argument);
ByteBuffer buffer = Utility.encode(ProtocolConstants.Room.COMMAND_INFORM_PING + TextProtocolDriver.ARGUMENT_SEPARATOR
+ state.name + TextProtocolDriver.ARGUMENT_SEPARATOR + argument);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
if (p != state) {
buffer.position(0);
p.getConnection().send(buffer);
}
}
myRoomMasterHandler.pingInformed(state.name, ping);
} catch (NumberFormatException e) {
}
return true;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_INFORM_TUNNEL_PORT, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
RoomProtocolDriver player = (RoomProtocolDriver) driver;
try {
int port = Integer.parseInt(argument);
InetSocketAddress remoteEP = new InetSocketAddress(player.getConnection().getRemoteAddress().getAddress(), port);
TunnelProtocolDriver tunnel = notYetLinkedTunnels.remove(remoteEP);
player.tunnel = tunnel;
if (tunnel != null) {
player.getConnection().send(Utility.encode(ProtocolConstants.Room.COMMAND_INFORM_TUNNEL_PORT));
tunnel.player = player;
}
} catch (NumberFormatException e) {
}
return true;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_MAC_ADDRESS_PLAYER, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String macAddress) {
String playerName;
if (masterMacAddresses.containsKey(macAddress)) {
playerName = masterName;
} else {
TunnelProtocolDriver tunnel = tunnelsByMacAddress.get(macAddress);
if (tunnel == null)
return true;
RoomProtocolDriver player = tunnel.player;
if (player == null)
return true;
playerName = player.name;
}
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.COMMAND_MAC_ADDRESS_PLAYER);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(macAddress);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(playerName);
driver.getConnection().send(Utility.encode(sb));
return true;
}
});
sessionHandlers.put(ProtocolConstants.Room.COMMAND_INFORM_SSID, new IProtocolMessageHandler() {
@Override
public boolean process(IProtocolDriver driver, String argument) {
RoomProtocolDriver player = (RoomProtocolDriver) driver;
player.ssid = argument;
myRoomMasterHandler.ssidInformed(player.name, player.ssid);
StringBuilder sb = new StringBuilder();
sb.append(ProtocolConstants.Room.NOTIFY_SSID_CHANGED);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(player.name);
sb.append(TextProtocolDriver.ARGUMENT_SEPARATOR);
sb.append(player.ssid);
ByteBuffer buffer = Utility.encode(sb);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver p = entry.getValue();
if (p != player) {
buffer.position(0);
p.getConnection().send(buffer);
}
}
return true;
}
});
}
private class TunnelProtocol implements IProtocol {
@Override
public String getProtocol() {
return ProtocolConstants.PROTOCOL_TUNNEL;
}
@Override
public IProtocolDriver createDriver(ISocketConnection connection) {
TunnelProtocolDriver driver = new TunnelProtocolDriver();
driver.connection = connection;
notYetLinkedTunnels.put(connection.getRemoteAddress(), driver);
return driver;
}
@Override
public void log(String message) {
myRoomMasterHandler.log(message);
}
}
private boolean checkMacAddressFiltering(String mac) {
if (isMacAdressWhiteListEnabled && !macAddressWhiteList.isEmpty() && !macAddressWhiteList.contains(mac))
return true;
else if (isMacAdressBlackListEnabled && macAddressBlackList.contains(mac))
return true;
return false;
}
private class TunnelProtocolDriver implements IProtocolDriver {
private ISocketConnection connection;
private RoomProtocolDriver player;
@Override
public ISocketConnection getConnection() {
return connection;
}
@Override
public boolean process(PacketData data) {
ByteBuffer packet = data.getBuffer();
if (!Utility.isPspPacket(packet)) {
InetSocketAddress remoteAddress = connection.getRemoteAddress();
if (notYetLinkedTunnels.containsKey(remoteAddress)) {
connection.send(Utility.encode(Integer.toString(remoteAddress.getPort())));
}
return true;
}
RoomProtocolDriver srcPlayer = player;
if (srcPlayer == null)
return true;
boolean srcPlayerSsidIsEmpty = Utility.isEmpty(srcPlayer.ssid);
String destMac = Utility.macAddressToString(packet, 0, false);
String srcMac = Utility.macAddressToString(packet, 6, false);
tunnelsByMacAddress.put(srcMac, this);
// myRoomMasterHandler.log("[" + srcPlayer.name + "] (" +
// srcPlayer.ssid + ") src: " + srcMac + " dest: " + destMac);
if (checkMacAddressFiltering(srcMac))
return true;
if (Utility.isMacBroadCastAddress(destMac)) {
if (Utility.isEmpty(masterSsid) || srcPlayerSsidIsEmpty || masterSsid.equals(srcPlayer.ssid))
myRoomMasterHandler.tunnelPacketReceived(packet, srcPlayer.name);
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver destPlayer = entry.getValue();
if (srcPlayer == destPlayer)
continue;
TunnelProtocolDriver destTunnel = destPlayer.tunnel;
if (destTunnel == null)
continue;
// myRoomMasterHandler.log("Broadcast: [" + destPlayer.name
// + "] (" + destPlayer.ssid + ")");
if (srcPlayerSsidIsEmpty || Utility.isEmpty(destPlayer.ssid) || srcPlayer.ssid.equals(destPlayer.ssid)) {
packet.position(0);
destTunnel.connection.send(packet);
}
}
} else {
if (masterMacAddresses.containsKey(destMac)) {
// myRoomMasterHandler.log("master (" + masterSsid + ")");
if (srcPlayerSsidIsEmpty || Utility.isEmpty(masterSsid) || masterSsid.equals(srcPlayer.ssid))
myRoomMasterHandler.tunnelPacketReceived(packet, srcPlayer.name);
}
TunnelProtocolDriver destTunnel = tunnelsByMacAddress.get(destMac);
if (destTunnel == null)
return true;
RoomProtocolDriver destPlayer = destTunnel.player;
if (destPlayer == null)
return true;
masterMacAddresses.remove(destMac);
if (checkMacAddressFiltering(destMac))
return true;
// myRoomMasterHandler.log("[" + destPlayer.name + "] (" +
// destPlayer.ssid + ")");
if (srcPlayerSsidIsEmpty || Utility.isEmpty(destPlayer.ssid) || srcPlayer.ssid.equals(destPlayer.ssid)) {
packet.position(0);
destTunnel.connection.send(packet);
}
}
return true;
}
@Override
public void connectionDisconnected() {
try {
player.tunnel = null;
player = null;
} catch (NullPointerException e) {
InetSocketAddress address = connection.getRemoteAddress();
if (address != null)
notYetLinkedTunnels.remove(address);
}
}
@Override
public void errorProtocolNumber(String number) {
}
}
public void sendTunnelPacketToParticipants(ByteBuffer packet, String srcMac, String destMac) {
masterMacAddresses.put(srcMac, placeHolderValueObject);
if (checkMacAddressFiltering(destMac))
return;
// System.out.print("src: " + srcMac + " dest: " + destMac);
// System.out.println();
boolean masterSsidIsNotEmpty = !Utility.isEmpty(masterSsid);
if (Utility.isMacBroadCastAddress(destMac)) {
for (Entry<String, RoomProtocolDriver> entry : playersByName.entrySet()) {
RoomProtocolDriver destPlayer = entry.getValue();
TunnelProtocolDriver destTunnel = destPlayer.tunnel;
if (destTunnel == null)
continue;
if (masterSsidIsNotEmpty && !Utility.isEmpty(destPlayer.ssid))
if (!masterSsid.equals(destPlayer.ssid))
continue;
packet.position(0);
destTunnel.getConnection().send(packet);
}
} else {
TunnelProtocolDriver destTunnel = tunnelsByMacAddress.get(destMac);
if (destTunnel == null)
return;
RoomProtocolDriver destPlayer = destTunnel.player;
if (destPlayer == null)
return;
if (masterSsidIsNotEmpty && !Utility.isEmpty(destPlayer.ssid))
if (!masterSsid.equals(destPlayer.ssid))
return;
destTunnel.getConnection().send(packet);
}
}
}