/*
* MegaMek - Copyright (C) 2003,2004 Ben Mazur (bmazur@sev.org)
*
* This program 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 2 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.
*/
package megamek.test;
import java.awt.Button;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.SwingUtilities;
import megamek.common.Board;
import megamek.common.net.ConnectionFactory;
import megamek.common.net.ConnectionListenerAdapter;
import megamek.common.net.DisconnectedEvent;
import megamek.common.net.IConnection;
import megamek.common.net.Packet;
import megamek.common.net.PacketReceivedEvent;
/**
* This class provides an AWT GUI for testing the transmission and reception of
* <code>Packet</code>s.
*
* @author James Damour <suvarov454@users.sourceforge.net>
*/
public class PacketTool extends Frame implements Runnable {
/**
*
*/
private static final long serialVersionUID = 3249150110009720658L;
/**
* The currently-loaded <code>Board</code>. May be <code>null</code>.
*/
private Board board = null;
/**
* The panel containing the connection controls.
*/
private Panel panConnect = null;
/**
* The panel containing the transimission controls.
*/
private Panel panXmit = null;
/**
* The text control where the host name is entered.
*/
private TextField hostName = null;
/**
* The text control where the host port is entered.
*/
private TextField hostPort = null;
/**
* The label where the board name is displayed.
*/
private Label boardName = null;
/**
* The button that sends the loaded board.
*/
private Button butSend = null;
/**
* The connection to the other peer.
*/
private IConnection conn = null;
/**
* Display a window for testing the transmission of boards.
*/
public static void main(String[] args) {
Frame frame = new PacketTool();
// set visible on middle of screen
Dimension screenSize = frame.getToolkit().getScreenSize();
frame.pack();
frame.setLocation(screenSize.width / 2 - frame.getSize().width / 2,
screenSize.height / 2 - frame.getSize().height / 2);
// Show the window.
frame.setVisible(true);
}
/**
* Create a window for testing the transmission of boards. The window will
* <em>not</em> be displayed by this constructor; calling functions should
* call <code>setVisible(true)</code>.
*/
public PacketTool() {
super("Board Transmition");
Button button = null;
Panel main = null;
// Handle the frame stuff.
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
quit();
}
});
// Create the panels.
main = new Panel();
main.setLayout(new GridLayout(0, 1));
panConnect = new Panel();
panConnect.setLayout(new GridLayout(0, 2));
main.add(panConnect);
panXmit = new Panel();
panXmit.setLayout(new GridLayout(0, 1));
panXmit.setEnabled(false);
main.add(panXmit);
this.add(main);
// Populate the connection panel.
panConnect.add(new Label(" Connect To:"));
hostName = new TextField("localhost", 10);
panConnect.add(hostName);
panConnect.add(new Label("Port Number:"));
hostPort = new TextField("2346", 10);
panConnect.add(hostPort);
button = new Button("Listen");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
(new Thread(PacketTool.this, "Packet Reader")).start();
}
});
panConnect.add(button);
button = new Button("Connect");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
connect();
}
});
panConnect.add(button);
// Populate the transmission panel.
button = new Button("Load Board");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boardLoad();
}
});
panXmit.add(button);
boardName = new Label();
boardName.setAlignment(Label.CENTER);
panXmit.add(boardName);
butSend = new Button("Send");
butSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send();
}
});
butSend.setEnabled(false);
panXmit.add(butSend);
}
/**
* Close this window.
*/
public synchronized void quit() {
if (null != this.conn) {
conn.close();
}
System.exit(0);
}
/**
* Connect to the specified host.
*/
public void connect() {
String host = hostName.getText();
int port = 0;
try {
port = Integer.parseInt(hostPort.getText());
conn = ConnectionFactory.getInstance().createServerConnection(
new Socket(host, port), 1);
Timer t = new Timer(true);
final Runnable packetUpdate = new Runnable() {
public void run() {
IConnection connection = PacketTool.this.conn;
if (connection != null)
connection.update();
}
};
final TimerTask packetUpdate2 = new TimerTask() {
public void run() {
try {
SwingUtilities.invokeAndWait(packetUpdate);
} catch (Exception ie) {
}
}
};
t.schedule(packetUpdate2, 500, 150);
// conn = new XmlConnection( this, new Socket(host, port), 1 );
System.out.println("Connected to peer.");
conn.addConnectionListener(connectionListener);
board = new Board();
panConnect.setEnabled(false);
panXmit.setEnabled(true);
} catch (Throwable err) {
err.printStackTrace();
}
}
/**
* Load a board from a file.
*/
public void boardLoad() {
FileDialog fd = new FileDialog(this, "Load Board...", FileDialog.LOAD);
fd.setDirectory("data" + File.separator + "boards");
if (boardName.getText().length() > 0) {
fd.setFile(boardName.getText());
}
fd.setLocation(this.getLocation().x + 150, this.getLocation().y + 100);
fd.setVisible(true);
if (fd.getFile() == null) {
// I want a file, y'know!
return;
}
String curpath = fd.getDirectory();
String curfile = fd.getFile();
// load!
try {
InputStream is = new FileInputStream(new File(curpath, curfile));
board.load(is);
// okay, done!
is.close();
// Record the file's name.
boardName.setText(curfile);
// Enable the send button.
butSend.setEnabled(true);
} catch (IOException ex) {
System.err.println("error opening file to save!");
System.err.println(ex);
}
}
/**
* Send the loaded board to the peer.
*/
public void send() {
long start = conn.bytesSent();
Packet packet = new Packet(Packet.COMMAND_SENDING_BOARD, board);
/*
* 2003-12-21 : prove connectivity first, then add refinements * like
* data compression. packet.zipData();
*/
conn.send(packet);
System.out.print("Bytes sent: ");
System.out.print(conn.bytesSent() - start);
System.out.print(", total sent: ");
System.out.println(conn.bytesSent());
}
/**
* Listen for incoming clients.
*/
public void run() {
int port = 0;
try {
port = Integer.parseInt(hostPort.getText());
ServerSocket serverSocket = new ServerSocket(port);
Socket s = serverSocket.accept();
serverSocket.close();
System.out.println("Accepted peer connection.");
conn = ConnectionFactory.getInstance().createServerConnection(s, 0);
// conn = new XmlConnection(this, s, 0);
conn.addConnectionListener(connectionListener);
board = new Board();
panConnect.setEnabled(false);
panXmit.setEnabled(true);
} catch (Throwable err) {
err.printStackTrace();
}
}
/**
* Process a packet from a connection. <p/> Implements
* <code>ConnectionHandler</code>.
*
* @param id - the <code>int</code> ID the connection that received the
* packet.
* @param packet - the <code>Packet</code> to be processed.
*/
public synchronized void handle(int id, Packet packet) {
System.out.print("Connection #");
System.out.print(id);
System.out.print(", received a ");
if (null == packet) {
System.out.print("null");
} else {
switch (packet.getCommand()) {
case Packet.COMMAND_SERVER_GREETING:
System.out.print("COMMAND_SERVER_GREETING");
break;
case Packet.COMMAND_CLIENT_NAME:
System.out.print("COMMAND_CLIENT_NAME");
break;
case Packet.COMMAND_LOCAL_PN:
System.out.print("COMMAND_LOCAL_PN");
break;
case Packet.COMMAND_PLAYER_ADD:
System.out.print("COMMAND_PLAYER_ADD");
break;
case Packet.COMMAND_PLAYER_REMOVE:
System.out.print("COMMAND_PLAYER_REMOVE");
break;
case Packet.COMMAND_PLAYER_UPDATE:
System.out.print("COMMAND_PLAYER_UPDATE");
break;
case Packet.COMMAND_PLAYER_READY:
System.out.print("COMMAND_PLAYER_READY");
break;
case Packet.COMMAND_CHAT:
System.out.print("COMMAND_CHAT");
break;
case Packet.COMMAND_ENTITY_ADD:
System.out.print("COMMAND_ENTITY_ADD");
break;
case Packet.COMMAND_ENTITY_REMOVE:
System.out.print("COMMAND_ENTITY_REMOVE");
break;
case Packet.COMMAND_ENTITY_MOVE:
System.out.print("COMMAND_ENTITY_MOVE");
break;
case Packet.COMMAND_ENTITY_DEPLOY:
System.out.print("COMMAND_ENTITY_DEPLOY");
break;
case Packet.COMMAND_ENTITY_ATTACK:
System.out.print("COMMAND_ENTITY_ATTACK");
break;
case Packet.COMMAND_ENTITY_UPDATE:
System.out.print("COMMAND_ENTITY_UPDATE");
break;
case Packet.COMMAND_ENTITY_MODECHANGE:
System.out.print("COMMAND_ENTITY_MODECHANGE");
break;
case Packet.COMMAND_ENTITY_AMMOCHANGE:
System.out.print("COMMAND_ENTITY_AMMOCHANGE");
break;
case Packet.COMMAND_ENTITY_VISIBILITY_INDICATOR:
System.out.print("COMMAND_ENTITY_VISIBILITY_INDICATOR");
break;
case Packet.COMMAND_CHANGE_HEX:
System.out.print("COMMAND_CHANGE_HEX");
break;
case Packet.COMMAND_BLDG_ADD:
System.out.print("COMMAND_BLDG_ADD");
break;
case Packet.COMMAND_BLDG_REMOVE:
System.out.print("COMMAND_BLDG_REMOVE");
break;
case Packet.COMMAND_BLDG_UPDATE_CF:
System.out.print("COMMAND_BLDG_UPDATE_CF");
break;
case Packet.COMMAND_BLDG_COLLAPSE:
System.out.print("COMMAND_BLDG_COLLAPSE");
break;
case Packet.COMMAND_PHASE_CHANGE:
System.out.print("COMMAND_PHASE_CHANGE");
break;
case Packet.COMMAND_TURN:
System.out.print("COMMAND_TURN");
break;
case Packet.COMMAND_ROUND_UPDATE:
System.out.print("COMMAND_ROUND_UPDATE");
break;
case Packet.COMMAND_SENDING_BOARD:
System.out.print("COMMAND_SENDING_BOARD");
/*
* * Save the board here.
*/
Board recvBoard = (Board) packet.getObject(0);
try {
recvBoard.save(new FileOutputStream("xmit.board"));
} catch (IOException ioErr) {
ioErr.printStackTrace();
}
break;
case Packet.COMMAND_SENDING_ENTITIES:
System.out.print("COMMAND_SENDING_ENTITIES");
break;
case Packet.COMMAND_SENDING_PLAYERS:
System.out.print("COMMAND_SENDING_PLAYERS");
break;
case Packet.COMMAND_SENDING_TURNS:
System.out.print("COMMAND_SENDING_TURNS");
break;
case Packet.COMMAND_SENDING_REPORTS:
System.out.print("COMMAND_SENDING_REPORTS");
break;
case Packet.COMMAND_SENDING_GAME_SETTINGS:
System.out.print("COMMAND_SENDING_GAME_SETTINGS");
break;
case Packet.COMMAND_SENDING_MAP_SETTINGS:
System.out.print("COMMAND_SENDING_MAP_SETTINGS");
break;
case Packet.COMMAND_QUERY_MAP_SETTINGS:
System.out.print("COMMAND_QUERY_MAP_SETTINGS");
break;
case Packet.COMMAND_END_OF_GAME:
System.out.print("COMMAND_END_OF_GAME");
break;
case Packet.COMMAND_DEPLOY_MINEFIELDS:
System.out.print("COMMAND_DEPLOY_MINEFIELDS");
break;
case Packet.COMMAND_REVEAL_MINEFIELD:
System.out.print("COMMAND_REVEAL_MINEFIELD");
break;
case Packet.COMMAND_REMOVE_MINEFIELD:
System.out.print("COMMAND_REMOVE_MINEFIELD");
break;
case Packet.COMMAND_SENDING_MINEFIELDS:
System.out.print("COMMAND_SENDING_MINEFIELDS");
break;
case Packet.COMMAND_REROLL_INITIATIVE:
System.out.print("COMMAND_REROLL_INITIATIVE");
break;
case Packet.COMMAND_SET_ARTYAUTOHITHEXES:
System.out.print("COMMAND_SET_ARTYAUTOHITHEXES");
break;
default:
System.out.print("unknown");
break;
}
}
System.out.println(" packet.");
}
/**
* Called when it is sensed that a connection has terminated. <p/>
* Implements <code>ConnectionHandler</code>.
*
* @param conn - the <code>Connection</code> that has terminated.
*/
public synchronized void disconnected(IConnection conn) {
// write something in the log
System.out.println("s: connection " + conn.getId() + " disconnected");
// kill the connection and remove it from any lists it might be on
panXmit.setEnabled(false);
butSend.setEnabled(false);
boardName.setText("");
board = null;
conn = null;
panConnect.setEnabled(true);
}
private ConnectionListenerAdapter connectionListener = new ConnectionListenerAdapter() {
/**
* Called when it is sensed that a connection has terminated.
*/
public void disconnected(DisconnectedEvent e) {
PacketTool.this.disconnected(e.getConnection());
}
public void packetReceived(PacketReceivedEvent e) {
PacketTool.this.handle(e.getConnection().getId(), e.getPacket());
}
};
}