net.sf.colossus.webserver
Class WebServer

java.lang.Object
  extended by net.sf.colossus.webserver.WebServer
All Implemented Interfaces:
IRunWebServer, IWebServer

public class WebServer
extends java.lang.Object
implements IWebServer, IRunWebServer

The main class for the WebServer - brings up the WebServer GUI - starts the ServerSocket and listens there for WebClients - based on actions coming from clients, keeps book of "instant" and "running" games (both GameInfo objects), and tell the GameInfo objects when to start the game.

Author:
Clemens Katzer

Nested Class Summary
(package private)  class WebServer.GameThreadReaper
          Check whether any game executed in an own process has been finished.
private static class WebServer.NullWebServerGUI
          A Null Object for the web server GUI interface.
 
Field Summary
private  java.io.PrintWriter dumpInfoFile
           
private  java.util.ArrayList<GameInfo> endingGames
           
private  ChatChannel generalChat
           
private  IWebServerGUI gui
           
private static java.util.logging.Logger LOGGER
           
private static java.util.ArrayList<java.lang.String> loginMessage
           
private  IColossusMail mailObject
           
private  int maxClients
           
private static int MIN_FREE_GAME_PORTS
           
private  WebServerOptions options
           
private  PortBookKeeper portBookKeeper
           
private  java.util.HashMap<java.lang.String,GameInfo> proposedGames
           
private  java.lang.String proposedGamesFilename
           
private  boolean proposedGamesListModified
           
private  boolean runGUI
          Controls whether the GUI is shown or not.
private  java.util.ArrayList<GameInfo> runningGames
           
private static java.lang.String sep
           
private  int serverPort
          Server port where we listen for WebClient connections
private  java.net.ServerSocket serverSocket
          Server actual socket where we listen for WebClient connections
private  boolean shutdownRequested
           
private  ClientWatchDog watchDog
           
private  FormatWhen whenFormatter
           
 
Fields inherited from interface net.sf.colossus.webcommon.IWebServer
Cancel, ChangePassword, ChatSubmit, ConfirmCommand, ConfirmRegistration, DumpInfo, Echo, Enroll, generalChatName, LocallyGameOver, Login, Logout, PingResponse, Propose, RegisterUser, RequestUserAttention, RereadLoginMessage, ShutdownServer, Start, StartAtPlayer, StartedByPlayer, Unenroll, WebProtocolSeparator
 
Constructor Summary
WebServer(java.lang.String optionsFile)
           
 
Method Summary
 void allTellGameInfo(GameInfo gi)
           
 void allTellUserCounts()
           
private  void attemptStartOnServer(GameInfo gi, User byUser)
           
 void cancelGame(java.lang.String gameId, java.lang.String byUser)
           
 void cancelIfNecessary(User user)
           
 java.lang.String changeProperties(java.lang.String username, java.lang.String oldPW, java.lang.String newPW, java.lang.String email, java.lang.Boolean isAdminObj)
           
 void chatSubmit(java.lang.String chatId, java.lang.String sender, java.lang.String message)
           
private  void closeAllWebServerClientSocketThreads()
           
 java.lang.String confirmRegistration(java.lang.String username, java.lang.String confirmationCode)
           
private  int countProposedGames(boolean shallBeScheduled)
           
private  void doReadGamesFromFile()
           
private  void doReadLoginMessage()
           
private  void doReadUsersFromFile()
           
 void dumpInfo()
          Dump server state info into a static file, at the moment dump-info.txt
 void dumpInfo(java.io.PrintWriter pw)
          Dump info into given PrintWriter
 void enrollUserToGame(java.lang.String gameId, java.lang.String username)
           
private  GameInfo findByGameId(java.lang.String gameId)
           
private  GameInfo findFromRunningGames(java.lang.String gameId)
           
 void gameFailed(GameInfo gi, java.lang.String reason)
           
 void gameStarted(GameInfo gi)
           
private  IGameRunner getGameOnServer(GameInfo gi)
           
private  int getMaximumGameIdFromFiles()
          Searches the game directory tree for highest game number for which a game directory had been earlier created.
(package private)  java.lang.String getPlayerName()
          Each user server thread's name is set to it user's name.
 PortBookKeeper getPortBookKeeper()
           
 IPortProvider getPortProvider()
           
 java.lang.String getStringOption(java.lang.String key)
           
private  void handlePing(java.lang.String sender, java.lang.String pingCommand)
           
private  void handlePingQuotedName(java.lang.String sender, java.lang.String pingCommand)
           
 void informAllEnrolledAbout(GameInfo gi, java.lang.String message)
           
 void informAllEnrolledThatStartFailed(GameInfo gi, java.lang.String reason, User byUser)
           
 void informLocallyGameOver(java.lang.String gameId)
           
private  void informPingFailed(java.lang.String sender, java.lang.String failMessage)
           
 void informStartedByPlayer(java.lang.String gameId)
           
 void initiateShutdown(java.lang.String byUserName)
           
private  GameInfo isInvolvedInInstantGame(java.lang.String initiatorName)
           
 void logout()
           
static void main(java.lang.String[] args)
           
 void makeDummyConnection()
           
 GameInfo proposeGame(java.lang.String initiator, java.lang.String variant, java.lang.String viewmode, long startAt, int duration, java.lang.String summary, java.lang.String expire, boolean unlimitedMulligans, boolean balancedTowers, int min, int target, int max)
           
private  void readGamesFromFile(java.lang.String filename, java.util.HashMap<java.lang.String,GameInfo> proposedGames)
           
private  void readLoginMessageFromFile(java.lang.String filename)
           
 void reEnrollIfNecessary(WebServerClient newclient)
           
 java.lang.String registerUser(java.lang.String username, java.lang.String password, java.lang.String email)
           
private  void reject(java.net.Socket socket)
           
 void requestUserAttention(long when, java.lang.String sender, boolean isAdmin, java.lang.String recipient, java.lang.String message, int beepCount, long beepInterval, boolean windows)
           
 void rereadLoginMessage()
          Triggered by remode admin connection
(package private)  void runSocketServer()
           
 void saveGamesIfNeeded()
           
 void sendMessageOfTheDayToOne(WebServerClient client, java.lang.String chatId)
           
 void sendOldVersionWarningToOne(WebServerClient client, java.lang.String userName, java.lang.String chatId)
           
 void shutdownServer()
           
 void startGame(java.lang.String gameId, User byUser)
           
 void startGameOnPlayerHost(java.lang.String gameId, java.lang.String hostingPlayer, java.lang.String playerHost, int port)
          A game was started by a WebClient user locally on his computer and is ready to accept the other players as remote client; so we notify them and tell them host and port to where to connect.
private  java.lang.String startOneGame(GameInfo gi)
           
private  void storeGamesToFile(java.lang.String filename)
           
 void systemMessageToAll(java.lang.String message)
           
 void tellAllGamesFromListToOne(WebServerClient client, java.util.ArrayList<GameInfo> games)
           
 void tellAllProposedGamesToOne(WebServerClient client)
           
 void tellAllRunningGamesToOne(WebServerClient client)
           
 void tellEnrolledGameStartsNow(GameInfo gi, java.lang.String host, int port)
           
 void tellEnrolledGameStartsSoon(GameInfo gi)
           
 void tellLastChatMessagesToOne(WebServerClient client, java.lang.String chatId)
           
 void unenrollUserFromGame(java.lang.String gameId, java.lang.String username)
           
 void unregisterGame(GameInfo gi, int port)
          unregister a game from runningGames (or proposedGames), and keep in endingGames until it's reaped
 void unregisterGamePlayerPC(GameInfo gi)
          unregister a game (run on player's PC) from runningGames, keep in endingGames until it's reaped
 void updateGUI()
           
 void updateUserCounts()
           
private  boolean waitForUser()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LOGGER

private static final java.util.logging.Logger LOGGER

options

private WebServerOptions options

portBookKeeper

private PortBookKeeper portBookKeeper

gui

private IWebServerGUI gui

mailObject

private final IColossusMail mailObject

MIN_FREE_GAME_PORTS

private static final int MIN_FREE_GAME_PORTS
See Also:
Constant Field Values

loginMessage

private static final java.util.ArrayList<java.lang.String> loginMessage

runGUI

private final boolean runGUI
Controls whether the GUI is shown or not. At the moment this is configured only by the possibility of doing so: if the environment supports running a GUI, we will, if not, we won't. It could be combined with a command line option to suppress the GUI even if it would be possible to show one.


shutdownRequested

private boolean shutdownRequested

proposedGamesFilename

private java.lang.String proposedGamesFilename

proposedGamesListModified

private boolean proposedGamesListModified

maxClients

private final int maxClients

proposedGames

private final java.util.HashMap<java.lang.String,GameInfo> proposedGames

runningGames

private final java.util.ArrayList<GameInfo> runningGames

endingGames

private final java.util.ArrayList<GameInfo> endingGames

sep

private static final java.lang.String sep
See Also:
Constant Field Values

serverPort

private final int serverPort
Server port where we listen for WebClient connections


serverSocket

private java.net.ServerSocket serverSocket
Server actual socket where we listen for WebClient connections


generalChat

private final ChatChannel generalChat

watchDog

private final ClientWatchDog watchDog

whenFormatter

private final FormatWhen whenFormatter

dumpInfoFile

private java.io.PrintWriter dumpInfoFile
Constructor Detail

WebServer

public WebServer(java.lang.String optionsFile)
Method Detail

main

public static void main(java.lang.String[] args)

doReadGamesFromFile

private void doReadGamesFromFile()

doReadUsersFromFile

private void doReadUsersFromFile()

doReadLoginMessage

private void doReadLoginMessage()

rereadLoginMessage

public void rereadLoginMessage()
Triggered by remode admin connection


runSocketServer

void runSocketServer()

initiateShutdown

public void initiateShutdown(java.lang.String byUserName)

shutdownServer

public void shutdownServer()
Specified by:
shutdownServer in interface IWebServer

makeDummyConnection

public void makeDummyConnection()

waitForUser

private boolean waitForUser()

reject

private void reject(java.net.Socket socket)

closeAllWebServerClientSocketThreads

private void closeAllWebServerClientSocketThreads()

getPlayerName

java.lang.String getPlayerName()
Each user server thread's name is set to it user's name.


getPortBookKeeper

public PortBookKeeper getPortBookKeeper()

getPortProvider

public IPortProvider getPortProvider()
Specified by:
getPortProvider in interface IRunWebServer

updateGUI

public void updateGUI()

dumpInfo

public void dumpInfo()
Dump server state info into a static file, at the moment dump-info.txt

Specified by:
dumpInfo in interface IWebServer

dumpInfo

public void dumpInfo(java.io.PrintWriter pw)
Dump info into given PrintWriter

Parameters:
pw - PrintWriter for the file to print dump to

isInvolvedInInstantGame

private GameInfo isInvolvedInInstantGame(java.lang.String initiatorName)

proposeGame

public GameInfo proposeGame(java.lang.String initiator,
                            java.lang.String variant,
                            java.lang.String viewmode,
                            long startAt,
                            int duration,
                            java.lang.String summary,
                            java.lang.String expire,
                            boolean unlimitedMulligans,
                            boolean balancedTowers,
                            int min,
                            int target,
                            int max)
Specified by:
proposeGame in interface IWebServer

cancelIfNecessary

public void cancelIfNecessary(User user)

reEnrollIfNecessary

public void reEnrollIfNecessary(WebServerClient newclient)

tellAllGamesFromListToOne

public void tellAllGamesFromListToOne(WebServerClient client,
                                      java.util.ArrayList<GameInfo> games)

tellAllProposedGamesToOne

public void tellAllProposedGamesToOne(WebServerClient client)

tellAllRunningGamesToOne

public void tellAllRunningGamesToOne(WebServerClient client)

allTellGameInfo

public void allTellGameInfo(GameInfo gi)
Specified by:
allTellGameInfo in interface IRunWebServer

tellEnrolledGameStartsSoon

public void tellEnrolledGameStartsSoon(GameInfo gi)
Specified by:
tellEnrolledGameStartsSoon in interface IRunWebServer

tellEnrolledGameStartsNow

public void tellEnrolledGameStartsNow(GameInfo gi,
                                      java.lang.String host,
                                      int port)
Specified by:
tellEnrolledGameStartsNow in interface IRunWebServer

gameStarted

public void gameStarted(GameInfo gi)
Specified by:
gameStarted in interface IRunWebServer

gameFailed

public void gameFailed(GameInfo gi,
                       java.lang.String reason)
Specified by:
gameFailed in interface IRunWebServer

enrollUserToGame

public void enrollUserToGame(java.lang.String gameId,
                             java.lang.String username)
Specified by:
enrollUserToGame in interface IWebServer

unenrollUserFromGame

public void unenrollUserFromGame(java.lang.String gameId,
                                 java.lang.String username)
Specified by:
unenrollUserFromGame in interface IWebServer

cancelGame

public void cancelGame(java.lang.String gameId,
                       java.lang.String byUser)
Specified by:
cancelGame in interface IWebServer

startGame

public void startGame(java.lang.String gameId,
                      User byUser)
Specified by:
startGame in interface IWebServer

attemptStartOnServer

private void attemptStartOnServer(GameInfo gi,
                                  User byUser)

startGameOnPlayerHost

public void startGameOnPlayerHost(java.lang.String gameId,
                                  java.lang.String hostingPlayer,
                                  java.lang.String playerHost,
                                  int port)
A game was started by a WebClient user locally on his computer and is ready to accept the other players as remote client; so we notify them and tell them host and port to where to connect.

Specified by:
startGameOnPlayerHost in interface IWebServer

informStartedByPlayer

public void informStartedByPlayer(java.lang.String gameId)
Specified by:
informStartedByPlayer in interface IWebServer

informAllEnrolledAbout

public void informAllEnrolledAbout(GameInfo gi,
                                   java.lang.String message)
Specified by:
informAllEnrolledAbout in interface IRunWebServer

systemMessageToAll

public void systemMessageToAll(java.lang.String message)

informAllEnrolledThatStartFailed

public void informAllEnrolledThatStartFailed(GameInfo gi,
                                             java.lang.String reason,
                                             User byUser)

requestUserAttention

public void requestUserAttention(long when,
                                 java.lang.String sender,
                                 boolean isAdmin,
                                 java.lang.String recipient,
                                 java.lang.String message,
                                 int beepCount,
                                 long beepInterval,
                                 boolean windows)
Specified by:
requestUserAttention in interface IWebServer

informPingFailed

private void informPingFailed(java.lang.String sender,
                              java.lang.String failMessage)

informLocallyGameOver

public void informLocallyGameOver(java.lang.String gameId)
Specified by:
informLocallyGameOver in interface IWebServer

updateUserCounts

public void updateUserCounts()

allTellUserCounts

public void allTellUserCounts()

chatSubmit

public void chatSubmit(java.lang.String chatId,
                       java.lang.String sender,
                       java.lang.String message)
Specified by:
chatSubmit in interface IWebServer

handlePingQuotedName

private void handlePingQuotedName(java.lang.String sender,
                                  java.lang.String pingCommand)

handlePing

private void handlePing(java.lang.String sender,
                        java.lang.String pingCommand)

tellLastChatMessagesToOne

public void tellLastChatMessagesToOne(WebServerClient client,
                                      java.lang.String chatId)

sendMessageOfTheDayToOne

public void sendMessageOfTheDayToOne(WebServerClient client,
                                     java.lang.String chatId)

sendOldVersionWarningToOne

public void sendOldVersionWarningToOne(WebServerClient client,
                                       java.lang.String userName,
                                       java.lang.String chatId)

readLoginMessageFromFile

private void readLoginMessageFromFile(java.lang.String filename)

logout

public void logout()
Specified by:
logout in interface IWebServer

registerUser

public java.lang.String registerUser(java.lang.String username,
                                     java.lang.String password,
                                     java.lang.String email)

confirmRegistration

public java.lang.String confirmRegistration(java.lang.String username,
                                            java.lang.String confirmationCode)

changeProperties

public java.lang.String changeProperties(java.lang.String username,
                                         java.lang.String oldPW,
                                         java.lang.String newPW,
                                         java.lang.String email,
                                         java.lang.Boolean isAdminObj)
Specified by:
changeProperties in interface IWebServer

countProposedGames

private int countProposedGames(boolean shallBeScheduled)

findByGameId

private GameInfo findByGameId(java.lang.String gameId)

findFromRunningGames

private GameInfo findFromRunningGames(java.lang.String gameId)

getGameOnServer

private IGameRunner getGameOnServer(GameInfo gi)

startOneGame

private java.lang.String startOneGame(GameInfo gi)

unregisterGame

public void unregisterGame(GameInfo gi,
                           int port)
unregister a game from runningGames (or proposedGames), and keep in endingGames until it's reaped

Specified by:
unregisterGame in interface IRunWebServer

unregisterGamePlayerPC

public void unregisterGamePlayerPC(GameInfo gi)
unregister a game (run on player's PC) from runningGames, keep in endingGames until it's reaped


readGamesFromFile

private void readGamesFromFile(java.lang.String filename,
                               java.util.HashMap<java.lang.String,GameInfo> proposedGames)

saveGamesIfNeeded

public void saveGamesIfNeeded()

storeGamesToFile

private void storeGamesToFile(java.lang.String filename)

getStringOption

public java.lang.String getStringOption(java.lang.String key)

getMaximumGameIdFromFiles

private int getMaximumGameIdFromFiles()
Searches the game directory tree for highest game number for which a game directory had been earlier created. Tree is expected to have groups per each 100 games; example: base base/nn00-nn99 base/nn00-nn99/nn00 base/nn00-nn99/nn04 base/nn00-nn99/nn98 base/mm00-mm99/mm12 base/mm00-mm99/mm87 Eventually, when we reach gameId 10000+, groupdirs will have the form base/kkk00-kkk99 base/kkk00-kkk99/kkk02 base/kkk00-kkk99/kkk87 Example, if last created game dir was 6789 ( "base/6700-6799/6789" ), this returns 6789.

Returns:
The highest game number for which a directory already exists, (otherwise 0 if therre is no dir at all)