git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@580 72836036-5685-4462-b002-a69064685172
804 lines
21 KiB
Java
804 lines
21 KiB
Java
package jrummikub.control.network;
|
|
|
|
import java.awt.Color;
|
|
import java.io.Serializable;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
|
import javax.swing.SwingUtilities;
|
|
|
|
import jrummikub.control.RoundControl.InvalidTurnInfo;
|
|
import jrummikub.model.GameSettings;
|
|
import jrummikub.model.IRoundState;
|
|
import jrummikub.model.ITable;
|
|
import jrummikub.model.PlayerSettings;
|
|
import jrummikub.util.Event;
|
|
import jrummikub.util.Event1;
|
|
import jrummikub.util.Event2;
|
|
import jrummikub.util.GameData;
|
|
import jrummikub.util.IEvent;
|
|
import jrummikub.util.IEvent1;
|
|
import jrummikub.util.IEvent2;
|
|
import jrummikub.util.LoginData;
|
|
import jrummikub.view.LoginError;
|
|
|
|
import org.jivesoftware.smack.Connection;
|
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
|
import org.jivesoftware.smack.PacketListener;
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
import org.jivesoftware.smack.XMPPException;
|
|
import org.jivesoftware.smack.filter.AndFilter;
|
|
import org.jivesoftware.smack.filter.PacketExtensionFilter;
|
|
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
|
import org.jivesoftware.smack.packet.DefaultPacketExtension;
|
|
import org.jivesoftware.smack.packet.Message;
|
|
import org.jivesoftware.smack.packet.Packet;
|
|
import org.jivesoftware.smack.packet.PacketExtension;
|
|
import org.jivesoftware.smack.packet.XMPPError;
|
|
import org.jivesoftware.smack.packet.XMPPError.Type;
|
|
import org.jivesoftware.smack.util.Base64;
|
|
import org.jivesoftware.smack.util.StringUtils;
|
|
import org.jivesoftware.smackx.muc.DiscussionHistory;
|
|
import org.jivesoftware.smackx.muc.MultiUserChat;
|
|
import org.jivesoftware.smackx.muc.ParticipantStatusListener;
|
|
|
|
/**
|
|
* Connection control managing network connections, messages and events
|
|
*/
|
|
public class ConnectionControl implements IConnectionControl {
|
|
private static class TurnEndData implements Serializable {
|
|
private static final long serialVersionUID = -3800572117130220737L;
|
|
|
|
private IRoundState roundState;
|
|
private InvalidTurnInfo invalidTurnInfo;
|
|
|
|
TurnEndData(IRoundState roundState, InvalidTurnInfo invalidTurnInfo) {
|
|
this.roundState = roundState;
|
|
this.invalidTurnInfo = invalidTurnInfo;
|
|
}
|
|
|
|
IRoundState getRoundState() {
|
|
return roundState;
|
|
}
|
|
|
|
InvalidTurnInfo getInvalidTurnInfo() {
|
|
return invalidTurnInfo;
|
|
}
|
|
}
|
|
|
|
private final static String ELEMENT_NAME = "rummikub";
|
|
private final static String NAMESPACE = "http://home.universe-factory.net/rummikub/";
|
|
|
|
private final static Runnable STOP_ACTION = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
}
|
|
};
|
|
|
|
private void fixGameSettings(GameSettings settings) {
|
|
for (PlayerSettings player : settings.getPlayerList()) {
|
|
if (player.getType() == PlayerSettings.Type.HUMAN) {
|
|
player.setType(PlayerSettings.Type.NETWORK);
|
|
}
|
|
|
|
if (player.getType() == PlayerSettings.Type.NETWORK
|
|
&& player.getName().equals(getNickname())) {
|
|
player.setType(PlayerSettings.Type.HUMAN);
|
|
}
|
|
}
|
|
}
|
|
|
|
private LoginData loginData;
|
|
private volatile Connection connection;
|
|
private volatile MultiUserChat muc;
|
|
|
|
private Event connectedEvent = new Event();
|
|
private Event1<LoginError> connectionFailedEvent = new Event1<LoginError>();
|
|
|
|
private Event1<GameData> gameOfferEvent = new Event1<GameData>();
|
|
private Event1<UUID> gameWithdrawalEvent = new Event1<UUID>();
|
|
|
|
private Event1<String> gameJoinEvent = new Event1<String>();
|
|
private Event1<String> gameLeaveEvent = new Event1<String>();
|
|
|
|
private Event1<Boolean> gameJoinAckEvent = new Event1<Boolean>();
|
|
|
|
private Event2<String, Color> changeColorEvent = new Event2<String, Color>();
|
|
|
|
private Event gameStartEvent = new Event();
|
|
private Event roundStartEvent = new Event();
|
|
private Event redealEvent = new Event();
|
|
private Event1<IRoundState> roundStateUpdateEvent = new Event1<IRoundState>();
|
|
|
|
private Event1<ITable> tableUpdateEvent = new Event1<ITable>();
|
|
private Event2<IRoundState, InvalidTurnInfo> turnEndEvent = new Event2<IRoundState, InvalidTurnInfo>();
|
|
private Event nextPlayerEvent = new Event();
|
|
private Event turnStartEvent = new Event();
|
|
|
|
private Event1<String> participantLeftEvent = new Event1<String>();
|
|
|
|
private GameData currentGame;
|
|
|
|
private BlockingQueue<Runnable> actionQueue = new LinkedBlockingQueue<Runnable>();
|
|
|
|
private volatile GameData offeredGame;
|
|
|
|
/**
|
|
* Creates new connection control
|
|
*
|
|
* @param loginData
|
|
* player's login data
|
|
*/
|
|
public ConnectionControl(LoginData loginData) {
|
|
this.loginData = loginData;
|
|
}
|
|
|
|
@Override
|
|
public String getNickname() {
|
|
return muc.getNickname();
|
|
}
|
|
|
|
@Override
|
|
public void connect() {
|
|
new Thread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Runnable runner = null;
|
|
do {
|
|
try {
|
|
runner = actionQueue.take();
|
|
runner.run();
|
|
} catch (InterruptedException e) {
|
|
}
|
|
} while (runner != STOP_ACTION);
|
|
}
|
|
}).start();
|
|
|
|
run(new ConnectRunner());
|
|
}
|
|
|
|
@Override
|
|
public void disconnect() {
|
|
final Connection theConnection = connection;
|
|
connection = null;
|
|
|
|
connectedEvent = new Event();
|
|
connectionFailedEvent = new Event1<LoginError>();
|
|
run(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (theConnection != null) {
|
|
theConnection.disconnect();
|
|
}
|
|
ConnectionControl.this.run(STOP_ACTION);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public IEvent getConnectedEvent() {
|
|
return connectedEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<LoginError> getConnectionFailedEvent() {
|
|
return connectionFailedEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<GameData> getGameOfferEvent() {
|
|
return gameOfferEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<UUID> getGameWithdrawalEvent() {
|
|
return gameWithdrawalEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<String> getGameJoinEvent() {
|
|
return gameJoinEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<String> getGameLeaveEvent() {
|
|
return gameLeaveEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<Boolean> getGameJoinAckEvent() {
|
|
return gameJoinAckEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent2<String, Color> getChangeColorEvent() {
|
|
return changeColorEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent getGameStartEvent() {
|
|
return gameStartEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent getRoundStartEvent() {
|
|
return roundStartEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent getRedealEvent() {
|
|
return redealEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<IRoundState> getRoundStateUpdateEvent() {
|
|
return roundStateUpdateEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<ITable> getTableUpdateEvent() {
|
|
return tableUpdateEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent2<IRoundState, InvalidTurnInfo> getTurnEndEvent() {
|
|
return turnEndEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent getNextPlayerEvent() {
|
|
return nextPlayerEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent getTurnStartEvent() {
|
|
return turnStartEvent;
|
|
}
|
|
|
|
@Override
|
|
public IEvent1<String> getParticipantLeftEvent() {
|
|
return participantLeftEvent;
|
|
}
|
|
|
|
@Override
|
|
public void offerGame(GameData data) {
|
|
offeredGame = data;
|
|
currentGame = data;
|
|
sendGameOffer();
|
|
}
|
|
|
|
@Override
|
|
public void withdrawGame() {
|
|
offeredGame = null;
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_withdrawal");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public GameData getCurrentGame() {
|
|
return currentGame;
|
|
}
|
|
|
|
@Override
|
|
public void setCurrentGame(GameData game) {
|
|
this.currentGame = game;
|
|
}
|
|
|
|
private void run(Runnable runner) {
|
|
while (true) {
|
|
try {
|
|
actionQueue.put(runner);
|
|
return;
|
|
} catch (InterruptedException e) {
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void joinGame(final GameData game) {
|
|
setCurrentGame(game);
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_join");
|
|
extension.setValue("uuid", game.getGameID().toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void leaveGame() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
currentGame = null;
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_leave");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void ackJoinGame(final String recipient, final boolean ack) {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_join_ack");
|
|
extension.setValue("uuid", uuid.toString());
|
|
extension.setValue("ack", Boolean.toString(ack));
|
|
}
|
|
|
|
@Override
|
|
protected void modifyMessage(Message message) {
|
|
message.setType(Message.Type.normal);
|
|
message.setTo(muc.getRoom() + "/" + recipient);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void changeColor(final Color color) {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "change_color");
|
|
extension.setValue("uuid", uuid.toString());
|
|
extension.setValue("color", Base64.encodeObject(color, Base64.GZIP));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void startGame() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_start");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void startRound() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "round_start");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void redeal() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "redeal");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void updateRoundState(final IRoundState roundState) {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "round_state_update");
|
|
extension.setValue("uuid", uuid.toString());
|
|
extension.setValue("state",
|
|
Base64.encodeObject(roundState, Base64.GZIP));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void updateTable(final ITable table) {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "table_update");
|
|
extension.setValue("uuid", uuid.toString());
|
|
extension.setValue("table", Base64.encodeObject(table, Base64.GZIP));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void endTurn(final IRoundState state,
|
|
final InvalidTurnInfo invalidTurnInfo) {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "turn_end");
|
|
extension.setValue("uuid", uuid.toString());
|
|
extension.setValue("data", Base64.encodeObject(new TurnEndData(state,
|
|
invalidTurnInfo), Base64.GZIP));
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void nextPlayer() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "next_player");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void startTurn() {
|
|
final UUID uuid = currentGame.getGameID();
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "turn_start");
|
|
extension.setValue("uuid", uuid.toString());
|
|
}
|
|
});
|
|
}
|
|
|
|
private void sendGameOffer() {
|
|
final GameData data = offeredGame;
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_offer");
|
|
extension.setValue("uuid", data.getGameID().toString());
|
|
extension.setValue("gameSettings",
|
|
Base64.encodeObject(data.getGameSettings(), Base64.GZIP));
|
|
}
|
|
});
|
|
}
|
|
|
|
private void requestGames() {
|
|
run(new SendRunner() {
|
|
@Override
|
|
protected void addData(DefaultPacketExtension extension) {
|
|
extension.setValue("messageType", "game_request");
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void emitLater(final Event event) {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
event.emit();
|
|
}
|
|
});
|
|
}
|
|
|
|
private static <T> void emitLater(final Event1<T> event, final T arg) {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
event.emit(arg);
|
|
}
|
|
});
|
|
}
|
|
|
|
private Message createMessage(PacketExtension extension) {
|
|
Message message = muc.createMessage();
|
|
message.addExtension(extension);
|
|
return message;
|
|
}
|
|
|
|
private static DefaultPacketExtension createJRummikubExtension() {
|
|
return new DefaultPacketExtension(ELEMENT_NAME, NAMESPACE);
|
|
}
|
|
|
|
private void processPacket(Packet packet) {
|
|
if (connection == null) {
|
|
return;
|
|
}
|
|
|
|
DefaultPacketExtension extension = (DefaultPacketExtension) packet
|
|
.getExtension(ELEMENT_NAME, NAMESPACE);
|
|
|
|
if (((Message) packet).getType() == Message.Type.error) {
|
|
System.err.println("Received error message from '" + packet.getFrom()
|
|
+ "'");
|
|
return;
|
|
}
|
|
|
|
String sender = packet.getFrom();
|
|
sender = sender.substring(sender.indexOf('/') + 1);
|
|
|
|
String messageType = extension.getValue("messageType");
|
|
|
|
handleMessageTypes(extension, sender, messageType);
|
|
}
|
|
|
|
private void handleMessageTypes(DefaultPacketExtension extension,
|
|
String sender, String messageType) {
|
|
if (messageType.equals("game_offer")) {
|
|
UUID uuid = UUID.fromString(extension.getValue("uuid"));
|
|
GameSettings settings = (GameSettings) Base64.decodeToObject(extension
|
|
.getValue("gameSettings"));
|
|
fixGameSettings(settings);
|
|
|
|
GameData gameData = new GameData(uuid, settings, sender);
|
|
gameOfferEvent.emit(gameData);
|
|
} else if (messageType.equals("game_withdrawal")) {
|
|
gameWithdrawalEvent.emit(UUID.fromString(extension.getValue("uuid")));
|
|
} else if (messageType.equals("game_request")) {
|
|
if (offeredGame != null) {
|
|
sendGameOffer();
|
|
}
|
|
} else if (currentGame != null) {
|
|
UUID uuid = UUID.fromString(extension.getValue("uuid"));
|
|
if (!currentGame.getGameID().equals(uuid)) {
|
|
return;
|
|
}
|
|
messagesDuringGame(extension, sender, messageType);
|
|
}
|
|
}
|
|
|
|
private void messagesDuringGame(DefaultPacketExtension extension,
|
|
String sender, String messageType) {
|
|
if (messageType.equals("game_join")) {
|
|
gameJoinEvent.emit(sender);
|
|
} else if (messageType.equals("game_leave")) {
|
|
gameLeaveEvent.emit(sender);
|
|
} else if (messageType.equals("game_join_ack")) {
|
|
gameJoinAckEvent.emit(Boolean.valueOf(extension.getValue("ack")));
|
|
} else if (messageType.equals("change_color")) {
|
|
changeColorEvent.emit(sender,
|
|
(Color) Base64.decodeToObject(extension.getValue("color")));
|
|
} else if (messageType.equals("game_start")) {
|
|
gameStartEvent.emit();
|
|
} else if (messageType.equals("round_start")) {
|
|
roundStartEvent.emit();
|
|
} else if (messageType.equals("redeal")) {
|
|
redealEvent.emit();
|
|
} else {
|
|
messagesDuringRound(extension, messageType);
|
|
}
|
|
}
|
|
|
|
private void messagesDuringRound(DefaultPacketExtension extension,
|
|
String messageType) {
|
|
if (messageType.equals("round_state_update")) {
|
|
IRoundState state = (IRoundState) Base64.decodeToObject(extension
|
|
.getValue("state"));
|
|
fixGameSettings(state.getGameSettings());
|
|
roundStateUpdateEvent.emit(state);
|
|
} else if (messageType.equals("table_update")) {
|
|
tableUpdateEvent.emit((ITable) Base64.decodeToObject(extension
|
|
.getValue("table")));
|
|
} else if (messageType.equals("turn_end")) {
|
|
TurnEndData data = (TurnEndData) Base64.decodeToObject(extension
|
|
.getValue("data"));
|
|
fixGameSettings(data.getRoundState().getGameSettings());
|
|
turnEndEvent.emit(data.getRoundState(), data.getInvalidTurnInfo());
|
|
} else if (messageType.equals("next_player")) {
|
|
nextPlayerEvent.emit();
|
|
} else if (messageType.equals("turn_start")) {
|
|
turnStartEvent.emit();
|
|
} else {
|
|
System.err.println("Received unrecognized message of type '"
|
|
+ messageType + "'");
|
|
}
|
|
}
|
|
|
|
private class ConnectRunner implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
ConnectionConfiguration config = new ConnectionConfiguration(
|
|
loginData.getServerName());
|
|
config.setSendPresence(false);
|
|
config.setRosterLoadedAtLogin(false);
|
|
config.setCompressionEnabled(true);
|
|
|
|
connection = new XMPPConnection(config);
|
|
|
|
connection.addPacketListener(new PacketListener() {
|
|
@Override
|
|
public void processPacket(final Packet packet) {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
ConnectionControl.this.processPacket(packet);
|
|
}
|
|
});
|
|
|
|
}
|
|
}, new AndFilter(new PacketTypeFilter(Message.class),
|
|
new PacketExtensionFilter(ELEMENT_NAME, NAMESPACE)));
|
|
|
|
LoginError error = doConnect();
|
|
if (error == null) {
|
|
error = doLogin();
|
|
}
|
|
if (error == null) {
|
|
error = doJoin();
|
|
}
|
|
|
|
if (error == null) {
|
|
requestGames();
|
|
emitLater(connectedEvent);
|
|
} else {
|
|
connection.disconnect();
|
|
connection = null;
|
|
|
|
emitLater(connectionFailedEvent, error);
|
|
}
|
|
}
|
|
|
|
private LoginError doConnect() {
|
|
try {
|
|
connection.connect();
|
|
return null;
|
|
} catch (XMPPException e) {
|
|
XMPPError xmppError = e.getXMPPError();
|
|
|
|
if (xmppError != null) {
|
|
if (xmppError.getType() == Type.WAIT && xmppError.getCode() == 504) {
|
|
return LoginError.UNKNOWN_HOST;
|
|
}
|
|
}
|
|
|
|
e.printStackTrace();
|
|
return LoginError.UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
private LoginError doLogin() {
|
|
try {
|
|
connection.login(loginData.getUserName(), loginData.getPassword(),
|
|
"JRummikub-" + StringUtils.randomString(8));
|
|
return null;
|
|
} catch (XMPPException e) {
|
|
return LoginError.AUTHENTICATION_FAILED;
|
|
}
|
|
}
|
|
|
|
private LoginError doJoin() {
|
|
muc = new MultiUserChat(connection, loginData.getChannelName());
|
|
DiscussionHistory history = new DiscussionHistory();
|
|
history.setMaxStanzas(0);
|
|
|
|
String nickname = loginData.getUserName();
|
|
// Loop until a unused nickname is found
|
|
while (true) {
|
|
try {
|
|
muc.join(nickname, null, history, 10000);
|
|
break; // Join was successful, break the loop
|
|
} catch (XMPPException e) {
|
|
XMPPError xmppError = e.getXMPPError();
|
|
|
|
if (xmppError != null && xmppError.getType() == Type.CANCEL
|
|
&& xmppError.getCode() == 409) {
|
|
// There was a conflict, try again with another
|
|
// nickname
|
|
nickname += "_";
|
|
continue;
|
|
} else {
|
|
// An unknown error has occurred, cancel connect
|
|
if (xmppError != null && xmppError.getType() == Type.CANCEL
|
|
&& xmppError.getCode() == 404) {
|
|
return LoginError.UNKNOWN_CHANNEL;
|
|
}
|
|
|
|
e.printStackTrace();
|
|
return LoginError.UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
muc.addParticipantStatusListener(new LeaveListener());
|
|
|
|
return null;
|
|
}
|
|
|
|
private class LeaveListener implements ParticipantStatusListener {
|
|
@Override
|
|
public void voiceRevoked(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void voiceGranted(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void ownershipRevoked(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void ownershipGranted(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void nicknameChanged(String arg0, String arg1) {
|
|
}
|
|
|
|
@Override
|
|
public void moderatorRevoked(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void moderatorGranted(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void membershipRevoked(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void membershipGranted(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void left(String participant) {
|
|
participant = participant.substring(participant.indexOf('/') + 1);
|
|
emitLater(participantLeftEvent, participant);
|
|
}
|
|
|
|
@Override
|
|
public void kicked(String participant, String actor, String reason) {
|
|
left(participant);
|
|
}
|
|
|
|
@Override
|
|
public void joined(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void banned(String participant, String arg1, String arg2) {
|
|
left(participant);
|
|
}
|
|
|
|
@Override
|
|
public void adminRevoked(String arg0) {
|
|
}
|
|
|
|
@Override
|
|
public void adminGranted(String arg0) {
|
|
}
|
|
}
|
|
}
|
|
|
|
private abstract class SendRunner implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
// For thread safety
|
|
Connection theConnection = connection;
|
|
|
|
if (theConnection != null) {
|
|
DefaultPacketExtension extension = createJRummikubExtension();
|
|
addData(extension);
|
|
Message message = createMessage(extension);
|
|
modifyMessage(message);
|
|
theConnection.sendPacket(message);
|
|
}
|
|
}
|
|
|
|
abstract protected void addData(DefaultPacketExtension extension);
|
|
|
|
protected void modifyMessage(Message message) {
|
|
}
|
|
}
|
|
}
|