[skycastle-commits] SF.net SVN: skycastle: [434] trunk/skycastle/modules

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Thu, 03 Apr 2008 14:04:36 -0700

Revision: 434
          http://skycastle.svn.sourceforge.net/skycastle/?rev=434&view=rev
Author:   zzorn
Date:     2008-04-03 14:04:36 -0700 (Thu, 03 Apr 2008)

Log Message:
-----------
The client connection handling part of the server starts to take form.  A lot 
of open questions (and uncompiling code), but the basic message handling is 
sketched out.

Modified Paths:
--------------
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/messaging/MessageListener.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ClientSideProtocolNegotiator.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ProtocolNegotiator.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ServerSideProtocolNegotiator.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistry.java
    
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistryImpl.java
    
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
    
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleServer.java

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/core/DefaultGameObject.java
        2008-04-03 21:04:36 UTC (rev 434)
@@ -48,6 +48,16 @@
     // Public Methods
 
     //----------------------------------------------------------------------
+    // Constructors
+
+    public DefaultGameObject()
+    {
+        myPropertyFacade = new PropertyFacadeImpl( this, 
getGameObjectContext() );
+        myActionFacade = new ActionFacadeImpl( this, getGameObjectContext() );
+        myMessagingFacade = new MessagingFacadeImpl( this, 
getGameObjectContext() );
+    }
+
+    //----------------------------------------------------------------------
     // ActionFacade Implementation
 
     public void startAction( final InvokeActionMessage invokeActionMessage )
@@ -62,7 +72,9 @@
     }
 
 
-    public long startAction( final GameObjectId callerId, final String 
actionIdentifier, final Object... parameters )
+    public long startAction( final GameObjectId callerId,
+                             final String actionIdentifier,
+                             final Object... parameters )
     {
         return myActionFacade.startAction( callerId, actionIdentifier, 
parameters );
     }
@@ -200,7 +212,9 @@
     }
 
 
-    public void addProperty( final String propertyIdentifier, final 
Serializable initialValue, final ParameterMetadata propertyMetadata )
+    public void addProperty( final String propertyIdentifier,
+                             final Serializable initialValue,
+                             final ParameterMetadata propertyMetadata )
             throws ParameterValidationException
     {
         myPropertyFacade.addProperty( propertyIdentifier, initialValue, 
propertyMetadata );
@@ -208,7 +222,9 @@
 
 
     public void addProperty( final String propertyIdentifier,
-                             final Serializable initialValue, final String 
description, final ParameterValidator... validators )
+                             final Serializable initialValue,
+                             final String description,
+                             final ParameterValidator... validators )
             throws ParameterValidationException
     {
         myPropertyFacade.addProperty( propertyIdentifier, initialValue, 
description, validators );
@@ -275,17 +291,6 @@
     //======================================================================
     // Protected Methods
 
-    //----------------------------------------------------------------------
-    // Protected Constructors
-
-    protected DefaultGameObject()
-    {
-        myPropertyFacade = new PropertyFacadeImpl( this, 
getGameObjectContext() );
-        myActionFacade = new ActionFacadeImpl( this, getGameObjectContext() );
-        myMessagingFacade = new MessagingFacadeImpl( this, 
getGameObjectContext() );
-    }
-
-
     protected final void setId( final GameObjectId id )
     {
         ParameterChecker.checkNotNull( id, "id" );

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/messaging/MessageListener.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/messaging/MessageListener.java
     2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/messaging/MessageListener.java
     2008-04-03 21:04:36 UTC (rev 434)
@@ -2,14 +2,14 @@
 
 
 /**
- * A listener that recieves {@link AbstractMessage}s.
+ * A listener that recieves {@link Message}s.
  *
  * @author Hans Häggström
  */
 public interface MessageListener
 {
     /**
-     * @param message a new {@link AbstractMessage} to handle.
+     * @param message a new {@link Message} to handle.
      */
     void onMessage( Message message );
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ClientSideProtocolNegotiator.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ClientSideProtocolNegotiator.java
     2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ClientSideProtocolNegotiator.java
     2008-04-03 21:04:36 UTC (rev 434)
@@ -24,9 +24,6 @@
     private int myStep = 0;
 
     //======================================================================
-    // Private Constants
-
-    //======================================================================
     // Public Methods
 
     //----------------------------------------------------------------------
@@ -37,7 +34,9 @@
      * @param clientType       the type / name of the client.
      * @param version          the version of the client.
      */
-    public ClientSideProtocolNegotiator( final ProtocolRegistry 
protocolRegistry, String clientType, String version )
+    public ClientSideProtocolNegotiator( final ProtocolRegistry 
protocolRegistry,
+                                         String clientType,
+                                         String version )
     {
         super( protocolRegistry );
         myClientType = clientType;
@@ -45,6 +44,14 @@
     }
 
     //----------------------------------------------------------------------
+    // ProtocolNegotiator Implementation
+
+    public boolean startsNegotiations()
+    {
+        return false;
+    }
+
+    //----------------------------------------------------------------------
     // Other Public Methods
 
     /**

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ProtocolNegotiator.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ProtocolNegotiator.java
       2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ProtocolNegotiator.java
       2008-04-03 21:04:36 UTC (rev 434)
@@ -33,4 +33,9 @@
      */
     Protocol getProtocol();
 
+    /**
+     * @return true if this party starts the protocol negotiation, false if it 
should wait for a message from
+     *         the other party.
+     */
+    boolean startsNegotiations();
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ServerSideProtocolNegotiator.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ServerSideProtocolNegotiator.java
     2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/negotiation/ServerSideProtocolNegotiator.java
     2008-04-03 21:04:36 UTC (rev 434)
@@ -51,6 +51,15 @@
     }
 
     //----------------------------------------------------------------------
+    // ProtocolNegotiator Implementation
+
+
+    public boolean startsNegotiations()
+    {
+        return true;
+    }
+
+    //----------------------------------------------------------------------
     // Other Public Methods
 
     /**
@@ -95,7 +104,8 @@
                 myClientType = parameters.get( CLIENT_KEY );
                 myClientVersion = parameters.get( VERSION_KEY );
 
-                final String selectedProtocol = 
findBestCommonSupportedProtocol( parameters.get( KNOWN_PROTOCOLS_KEY ) );
+                final String selectedProtocol = 
findBestCommonSupportedProtocol( parameters.get(
+                        KNOWN_PROTOCOLS_KEY ) );
                 setProtocol( selectedProtocol );
                 if ( selectedProtocol.length() > 0 )
                 {
@@ -122,8 +132,9 @@
     {
         if ( spaceSeparatedClientProtocols != null )
         {
-            final Set<String> clientKnownProtocols = new HashSet<String>( 
Arrays.asList( spaceSeparatedClientProtocols.split(
-                    " " ) ) );
+            final Set<String> clientKnownProtocols = new HashSet<String>( 
Arrays.asList(
+                    spaceSeparatedClientProtocols.split(
+                            " " ) ) );
             for ( String supportedProtocol : getAvailableProtocolsIds() )
             {
                 if ( clientKnownProtocols.contains( supportedProtocol ) )

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistry.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistry.java
    2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistry.java
    2008-04-03 21:04:36 UTC (rev 434)
@@ -1,7 +1,9 @@
 package org.skycastle.protocol.registry;
 
+import com.sun.sgs.app.ManagedObject;
 import org.skycastle.protocol.Protocol;
 
+import java.io.Serializable;
 import java.util.Set;
 
 /**
@@ -10,6 +12,7 @@
  * @author Hans Haggstrom
  */
 public interface ProtocolRegistry
+        extends ManagedObject, Serializable
 {
     /**
      * @return the id:s for the protocols that are currently available.
@@ -17,7 +20,8 @@
     Set<String> getAvailableProtocolIds();
 
     /**
-     * @return the {@link org.skycastle.protocol.Protocol} with the specified 
protocol id, or null if not found.
+     * @return the {@link org.skycastle.protocol.Protocol} with the specified 
protocol id, or null if not
+     *         found.
      */
     Protocol getProtocol( String protocolId );
 }

Modified: 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistryImpl.java
===================================================================
--- 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistryImpl.java
        2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/core/src/main/java/org/skycastle/protocol/registry/ProtocolRegistryImpl.java
        2008-04-03 21:04:36 UTC (rev 434)
@@ -25,14 +25,19 @@
     private final Map<String, Protocol> myProtocols = new 
LinkedHashMap<String, Protocol>();
 
     //======================================================================
+    // Private Constants
+
+    private static final long serialVersionUID = 1L;
+
+    //======================================================================
     // Public Methods
 
     //----------------------------------------------------------------------
     // Constructors
 
     /**
-     * Creates a new {@link ProtocolRegistryImpl} with the known protocols 
alreay registered, using a default set of
-     * allowed data types for transfer.
+     * Creates a new {@link ProtocolRegistryImpl} with the known protocols 
alreay registered, using a default
+     * set of allowed data types for transfer.
      */
     public ProtocolRegistryImpl()
     {
@@ -75,8 +80,8 @@
 
 
     /**
-     * Removes all registered protocols.  Can be used to remove the default 
protocols, if they are not desired (e.g. in
-     * unit tests).
+     * Removes all registered protocols.  Can be used to remove the default 
protocols, if they are not desired
+     * (e.g. in unit tests).
      */
     public void removeAllProtocols()
     {

Modified: 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
===================================================================
--- 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
        2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleClientSessionHandler.java
        2008-04-03 21:04:36 UTC (rev 434)
@@ -1,15 +1,20 @@
 package org.skycastle.server;
 
 import com.sun.sgs.app.*;
-import org.skycastle.server.hardcoded.SkycastleServerListener;
+import org.skycastle.core.DefaultGameObject;
+import org.skycastle.core.GameObject;
+import org.skycastle.messaging.Message;
+import org.skycastle.messaging.modifications.ModificationMessage;
+import org.skycastle.protocol.ProtocolException;
+import org.skycastle.protocol.negotiation.ProtocolNegotiator;
+import org.skycastle.protocol.negotiation.ServerSideProtocolNegotiator;
 
 import java.io.Serializable;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
- * Initializes a client session and listens to messages (commands) and session
- * events from the client.
+ * Initializes a client session and listens to messages (commands) and session 
events from the client.
  */
 public class SkycastleClientSessionHandler
         implements Serializable, ClientSessionListener
@@ -22,8 +27,20 @@
      * The session this {@code ClientSessionListener} is listening to.
      */
     private final ClientSession mySession;
+    private final ProtocolNegotiator myProtocolNegotiator;
 
+    private ManagedReference myProtocolRegistryReferenceReference;
+    private ManagedReference myClientAccountReference;
+
     //======================================================================
+    // Non-Private Fields
+
+    /**
+     * The server listener. This is used for querying connected users etc.
+     */
+    protected ManagedReference serverListener;
+
+    //======================================================================
     // Private Constants
 
     /**
@@ -36,14 +53,9 @@
      */
     private static final Logger LOGGER =
             Logger.getLogger( SkycastleClientSessionHandler.class.getName() );
+    private static final String SERVER_TYPE = "SkycastleServer";
+    private static final String SERVER_VERSION = "0.1";
 
-
-    /**
-     * The server listener.
-     * This is used for querying connected users etc.
-     */
-    protected ManagedReference serverListener;
-
     //======================================================================
     // Public Methods
 
@@ -51,35 +63,104 @@
     // Constructors
 
     /**
-     * Creates a new {@code HelloChannelsSessionListener} for the given
-     * session, and joins it to the given channels.
+     * Creates a new {@code HelloChannelsSessionListener} for the given 
session, and joins it to the given
+     * channels.
      *
-     * @param session the session this listener is associated with
+     * @param clientSession the session this listener is associated with
+     * @param protocolRegistryReferenceReference
+     *
      */
-    public SkycastleClientSessionHandler( ClientSession session,
-                                          SkycastleServer initServerListener )
+    // TODO: Implement our own generic version of ManagedReference that just 
wraps a ManagedReference
+    public SkycastleClientSessionHandler( ClientSession clientSession,
+                                          SkycastleServer initServerListener,
+                                          final ManagedReference 
protocolRegistryReferenceReference )
     {
-        mySession = session;
+        mySession = clientSession;
+        myProtocolRegistryReferenceReference = 
protocolRegistryReferenceReference;
 
         final DataManager dataManager = AppContext.getDataManager();
         serverListener = dataManager.createReference( initServerListener );
+
+        // TODO: We need to pass in a reference instead of a concrete class, 
because we store the protocol negotiator in this object....
+        myProtocolNegotiator = new ServerSideProtocolNegotiator( 
myProtocolRegistryReferenceReference,
+                                                                 SERVER_TYPE,
+                                                                 
SERVER_VERSION );
+
+
+        if ( myProtocolNegotiator.startsNegotiations() )
+        {
+            final byte[] firstMessage = myProtocolNegotiator.handleMessage( 
null );
+            clientSession.send( firstMessage );
+        }
+
+        // Get users account.  The account will typically contain actions for 
resuming some existing avatars
+        // or creating new avatars, and doing general account management and 
maybe out-of-game chat.
+        // TODO: If the ClientSession is already authenticated, we can find 
the current account for the client,
+        // otherwise we need to add authentication before or during or after 
protocol negotiation
+        GameObject clientAccount = dataManager.getBinding( "account_" + 
clientSession.getName(),
+                                                           GameObject.class );
+
+        // If client doesn't yet have any account, create a new one
+        if ( clientAccount == null )
+        {
+            clientAccount = new DefaultGameObject();
+        }
+
+        myClientAccountReference = dataManager.createReference( clientAccount 
);
+
+        // TODO: Notify the users account that the user connected
     }
 
     //----------------------------------------------------------------------
     // ClientSessionListener Implementation
 
-
     /**
      * {@inheritDoc}
      * <p/>
      * Logs when data arrives from the client, and echoes the message back.
      */
-    public void receivedMessage( byte[] message )
+    public void receivedMessage( final byte[] message )
     {
-        // DEBUG:
-        LOGGER.log( Level.INFO, "Direct message from {0}", mySession.getName() 
);
+        if ( myProtocolNegotiator.getStatus().isFinished() )
+        {
+            try
+            {
+                // Decode incoming message
+                final Message decodedMessage = 
myProtocolNegotiator.getProtocol().decode( message );
+
+                // TODO: Set the messages sender and such so that the client 
is not claiming to be someone else...
+
+                // TODO: Should we validate the message here also?
+                //decodedMessage.validate(  )
+
+                // Send the incoming message to the clients account for 
processing
+                final GameObject clientAvatar = myClientAccountReference.get( 
GameObject.class );
+                clientAvatar.onMessage( decodedMessage );
+
+                // TODO: Or should we send it directly to the target game 
object??
+                // If the message is a ModificationMessage it has a target.
+                // The client should anyway send only modification messages, 
update messages don't make that much sense.
+                ModificationMessage modificationMessage = 
(ModificationMessage) decodedMessage;
+                // TODO: Get game object for specific gameObjectId, using e.g. 
the GameContext - we could build this functionality into the GameObjectId now!  
Maybe even support generics?
+                GameObject target = 
modificationMessage.getTargetId().getGameObjectForModification();
+                target.onMessage( modificationMessage );
+            }
+            catch ( ProtocolException e )
+            {
+                // TODO: Log exception with client somehow?  Enable fast 
detection of errorneous or flooding DoS:in clients
+                e.printStackTrace();
+            }
+        }
+        else
+        {
+            // Continue protocol negotiation
+            final byte[] reply = myProtocolNegotiator.handleMessage( message );
+
+            mySession.send( reply );
+        }
     }
 
+
     /**
      * {@inheritDoc}
      * <p/>
@@ -87,6 +168,8 @@
      */
     public void disconnected( boolean graceful )
     {
+        // TODO: Notify the users account that the user disconnected (the 
avatars can go into off-line mode, etc).
+
         // DEBUG:
         final String grace = graceful ? "graceful" : "forced";
         LOGGER.log( Level.INFO,
@@ -95,5 +178,4 @@
         );
     }
 
-
 }
\ No newline at end of file

Modified: 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleServer.java
===================================================================
--- 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleServer.java
      2008-04-03 18:15:38 UTC (rev 433)
+++ 
trunk/skycastle/modules/server/src/main/java/org/skycastle/server/SkycastleServer.java
      2008-04-03 21:04:36 UTC (rev 434)
@@ -1,19 +1,13 @@
 package org.skycastle.server;
 
-import com.sun.sgs.app.AppListener;
-import com.sun.sgs.app.ClientSession;
-import com.sun.sgs.app.ClientSessionListener;
-import com.sun.sgs.app.AppContext;
+import com.sun.sgs.app.*;
+import org.skycastle.protocol.registry.ProtocolRegistryImpl;
 
 import java.io.Serializable;
 import java.util.Properties;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.skycastle.protocol.negotiation.ServerSideProtocolNegotiator;
-import org.skycastle.protocol.registry.ProtocolRegistry;
-import org.skycastle.protocol.registry.ProtocolRegistryImpl;
-
 /**
  * The Skycastle Server, running inside Darkstar. Recieves events when the 
server is started the first time,
  * and when a client logs in.
@@ -32,9 +26,8 @@
      */
     private static final Logger LOGGER =
             Logger.getLogger( SkycastleServer.class.getName() );
+    private ManagedReference myProtocolRegistryReferenceReference;
 
-
-
     //======================================================================
     // Public Methods
 
@@ -44,10 +37,7 @@
     public void initialize( final Properties properties )
     {
         // Create protocol registry
-        ProtocolRegistry protocolRegistry = new ProtocolRegistryImpl();
-        AppContext.getDataManager().createReference( protocolRegistry );
-
-
+        myProtocolRegistryReferenceReference = 
AppContext.getDataManager().createReference( new ProtocolRegistryImpl() );
     }
 
 
@@ -56,8 +46,7 @@
         // DEBUG:
         LOGGER.log( Level.INFO, "User {0} has logged in", 
clientSession.getName() );
 
-
-        return new SkycastleClientSessionHandler( clientSession, this );
+        return new SkycastleClientSessionHandler( clientSession, this, 
myProtocolRegistryReferenceReference );
     }
 
 }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [434] trunk/skycastle/modules