|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.safs.sockets.SocketServer
public class SocketServer
This class is the "local" controller side of the TCP Socket Server. The class provides the TCP protocol implementation needed by SAFS engines running on Windows, *nix, or Mac that need to control a remote engine that cannot communicate via STAF, but must use a SAFS TCP Sockets protocol instead.
Normal instantiation and usage sequence is as follows:
tcpServer = new SocketServer(SocketServerListener);
tcpServer.setServerName(process_name);
tcpServerThread = new Thread(tcpServer);
tcpServerThread.start();
...
tcpServer.shutdownThread(); // if and when appropriate
Of course, there may be other activities performed between the different calls above.
Currently, this server expects remote TCP services to be accepting connections on port 2410. Currently, this server uses port 2411 to contact and attempt a connection to those remote TCP services. Both sides eventually need to be able to use a broader range of ports to prevent conflicts with other system resources.
When using the Android Emulator, the emulator must be configured to "see" Socket requests on its local port 2410 coming from the controller on port 2411. Do this with the adb forwarding command to the running emulator as follows:
adb forward tcp:2411 tcp:2410
There is an initial handshake or verification that occurs between this remote controller server and the on-device Service to confirm the device port owner is a SAFS TCP Messenger Service.
MSG_SERVER_VERSION_QUERY
,
SocketServerListener
,
org.safs.android.messenger.MessengerService
,
org.safs.android.engine.DroidEngine
Field Summary | |
---|---|
static int |
DEFAULT_PORT
|
static java.lang.String |
DEFAULT_SERVER
|
protected java.lang.String |
EOM
"[_EOM_]" End-Of-Message marker for all String messages exchanged between local and remote TCP services. Normally, this is never changed. |
static java.lang.String |
MSG_ENGINE_COMMENT
"comment" Prefix sent by remote client to set a comment message to be logged following the processing of a command. |
static java.lang.String |
MSG_ENGINE_DEBUG
"debug" Prefix sent by remote client to route message to SAFS Debug Log. Example message: "debug:Ran into a problem!" The full message must be terminated by the EOM marker. Once received, the message will be routed to any registered SocketServerListener, but without the prefix or the EOM marker. |
static java.lang.String |
MSG_ENGINE_DETAIL
"detail" Prefix sent by remote client to set a detail message to be logged following the processing of a command. |
static java.lang.String |
MSG_ENGINE_EVENT
"event" Prefix sent by remote client to indicate a particular event or state has occurred: |
static java.lang.String |
MSG_ENGINE_MESSAGE
"message" Prefix sent by remote client to route arbitrary/custom messages. These are generally engine implementation specific allowing the remote client engine to send arbitrary information to the local counterpart without interference from SAFS. Example message: "message:Funky Chicken" The full message must be terminated by the EOM marker. Once received, the message will be routed to any registered SocketServerListener, but without the prefix or the EOM marker. Any response to the received message is engine-specific and undefined here. |
static java.lang.String |
MSG_ENGINE_SPCMAP
"spcmap" Prefix sent by remote client to route message to Process Container App Map File. Example message: "spcmap:Class=android.os.SuperDuperCheckBox" The full message must be terminated by the EOM marker. Once received, the message will be routed to any registered SocketServerListener, but without the prefix or the EOM marker. |
static java.lang.String |
MSG_ENGINE_SPCOUT
"spcout" Prefix sent by remote client to route message to Process Container Object Info/File. Example message: "spcout:Text=Text in the Box" The full message must be terminated by the EOM marker. Once received, the message will be routed to any registered SocketServerListener, but without the prefix or the EOM marker. |
static java.lang.String |
MSG_EVENT_READY
"ready" Event name sent by remote client to indicate it is ready to receive a new command. Example:"event:ready" The full message must be terminated by the EOM marker. Once received, the message will be routed to any registered SocketServerListener. |
static java.lang.String |
MSG_EVENT_RESULT
"result" Event name sent by remote client to indicate it is finished processing a command and is returning the result in a statuscode:statusinfo format. |
static java.lang.String |
MSG_EVENT_RESULTPROPS
"resultprops" Event name sent by remote client to indicate it is finished processing a command and is returning the result in a Java Properties format. |
static java.lang.String |
MSG_EVENT_RUNNING
"running" Event name sent by remote client to indicate it is processing a command. Example:"event:running" The full message must be terminated by the EOM marker. Once received, the event will be routed to any registered SocketServerListener. |
static java.lang.String |
MSG_EVENT_SHUTDOWN
"shutdown" Event name sent by remote client to indicate it is shutting down and will not be available for further communication. Example:"event:shutdown" The full message must be terminated by the EOM marker. Once received, the event will be routed to any registered SocketServerListener. |
static java.lang.String |
MSG_SERVER_DISPATCHFILE
"dispatchfile" Prefix sent by local server to remote client to dispatch a command for processing. |
static java.lang.String |
MSG_SERVER_DISPATCHPROPS
"dispatchprops" Prefix sent by local server to remote client to dispatch a command for processing. |
static java.lang.String |
MSG_SERVER_MESSAGE
"message" Prefix sent by local server to remote client to route arbitrary/custom messages. These are generally engine implementation specific allowing the local (custom) engine to send arbitrary information to their remote counterpart without interference from SAFS. Example message: "message:Funky Chicken" The full message must be terminated by the EOM marker. Any response to the sent message is engine-specific and undefined here. |
static java.lang.String |
MSG_SERVER_SHUTDOWN
"shutdown_hook" Command sent by local server to remote client to commence shutdown. Example:"shutdown_hook" The full message must be terminated by the EOM marker. |
static java.lang.String |
MSG_SERVER_VERSION_QUERY
"SERVERVERSION" Prompt and partial response for initial handshake between this local server and a remote TCP Server. |
static int |
STATUS_THREAD_SHUTDOWN_NORMAL
Indicates the SocketServer sockets thread is being shutdown normally. |
static int |
STATUS_THREAD_SHUTDOWN_REMOTE_PORT_CLIENT
Indicates the SocketServer sockets thread is being shutdown abnormally because no remote client connection will be possible. |
Constructor Summary | |
---|---|
SocketServer()
Default no-op constructor setting Server to use all defaults. |
|
SocketServer(SocketServerListener listener)
Constructor setting Server to use all defaults while registering a SocketServerListener. |
Method Summary | |
---|---|
boolean |
addSocketServerListener(SocketServerListener listener)
|
protected void |
closeSocket()
Closes the remote Socket (if any) and sets references to the socket and communication streams to null. |
protected boolean |
createClientConnection(int sTimeout)
Attempt to connect to a remote Sockets client. |
int |
getClientConnectTimeout()
Default is set at 60 seconds. |
int |
getConnectedProtocol()
|
java.lang.String |
getEOM()
|
boolean |
getKeepAlive()
By default keepAlive is TRUE unless changed. |
java.lang.String |
getProtocolMessageSeparator()
|
java.lang.String |
getRemoteHostname()
The default hostname is typically the "localhost". |
int |
getRemotePort()
The default port currently used for remote client connections is 2410. |
java.lang.String |
getServerName()
Retrieve this SocketServer's unique name. |
boolean |
isConnected()
|
protected java.lang.String |
receiveClient(long msTimeout)
Listen for content from the remote client and return it to the caller if it is deemed valid. String content is not considered valid unless/until the End-Of-Message marker is received. |
boolean |
removeSocketServerListener(SocketServerListener listener)
|
void |
run()
Runnable Interface for Thread execution. |
protected boolean |
sendClient(java.lang.String message)
Send a message to the remote client, if any. |
boolean |
sendDispatch(java.util.Properties trd)
Send the remote client a DISPATCHPROPS event immediately followed by a Serialized Properties object containing all the testRecordData and other data needed for the execution of the Dispatch. |
boolean |
sendDispatch(java.lang.String filepath)
Send the remote client a DISPATCHFILE event with the filepath to a file suitable for Properties and/or INI file processing. |
boolean |
sendListenerDebug(java.lang.String message)
Send a registered SocketServerListener a SAFS Debug message received from the remote client. |
boolean |
sendMessage(java.lang.String message)
Send the remote client arbitrary MESSAGE content. |
boolean |
sendShutdown()
Send the remote client a shutdown command |
void |
setClientConnectTimeout(int clientConnectTimeout)
Default is set at 60 seconds. |
void |
setEOM(java.lang.String marker)
|
void |
setKeepAlive(boolean keepAlive)
By default keepAlive is TRUE unless changed. |
void |
setProtocolMessageSeparator(java.lang.String charSeparator)
|
void |
setRemoteHostname(java.lang.String hostname)
The default hostname is typically the "localhost". |
void |
setRemotePort(int port)
Provide an alternate port on which the remote client is accepting connections. |
void |
setServerName(java.lang.String name)
Provide this SocketServer with a uniquely identifyable name. |
void |
shutdownThread()
Command the SocketServer thread to shutdown. |
protected boolean |
verifySAFSClient(int sTimeout)
verify the connected remote socket is controlled by a SAFS client knowing the handshake. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final java.lang.String DEFAULT_SERVER
public static final int DEFAULT_PORT
public static final java.lang.String MSG_SERVER_VERSION_QUERY
public static final int STATUS_THREAD_SHUTDOWN_NORMAL
shutdownThread
,
shutdownCause
,
Constant Field Valuespublic static final int STATUS_THREAD_SHUTDOWN_REMOTE_PORT_CLIENT
shutdownThread
,
shutdownCause
,
Constant Field Valuesprotected java.lang.String EOM
public static final java.lang.String MSG_ENGINE_DEBUG
SocketServerListener.onReceiveDebug(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_SPCOUT
SocketServerListener.onReceiveSPCOut(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_SPCMAP
SocketServerListener.onReceiveSPCMap(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_MESSAGE
SocketServerListener.onReceiveMessage(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_COMMENT
SocketServerListener.onReceiveComment(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_DETAIL
SocketServerListener.onReceiveDetail(String)
,
Constant Field Valuespublic static final java.lang.String MSG_ENGINE_EVENT
Examples:
The full message must be terminated by the EOM marker.
Once received, the event will be routed to any registered SocketServerListener.
SocketServerListener.onReceiveReady()
,
SocketServerListener.onReceiveRunning()
,
SocketServerListener.onReceiveResult(int, String)
,
SocketServerListener.onReceiveResultProperties(Properties)
,
SocketServerListener.onReceiveShutdown()
,
Constant Field Valuespublic static final java.lang.String MSG_EVENT_READY
SocketServerListener.onReceiveReady()
,
Constant Field Valuespublic static final java.lang.String MSG_EVENT_RUNNING
SocketServerListener.onReceiveRunning()
,
Constant Field Valuespublic static final java.lang.String MSG_EVENT_RESULT
This is one of two possible results formats supported by the protocol. This format is defined for remote clients that cannot "load" or "store" Java Properties. Instead of transferring Java Properties, this format allows for the separate transmission of a log comment String, a log details String, and the command result statuscode:statusinfo. The log comment and log detail, if any, should be sent by the remote client before issuing this result.
Example:"event:result:statuscode:statusinfo"
The statuscode must be a String representation of an integer statuscode suitable for the Integer.parse(String) routine. The statusinfo is optional, and need not be present at all. If the message separator (colon) exists after the statuscode, then statusinfo will be sought and returned as an empty String if it is not present. If the message separator (colon) is NOT present after the statuscode then statusinfo is NOT present and null will be assumed.
The full event message must be terminated by the EOM marker.
Once received, the event will be routed to any registered SocketServerListener.
MSG_ENGINE_COMMENT
,
MSG_ENGINE_DETAIL
,
MSG_EVENT_RESULTPROPS
,
SocketServerListener.onReceiveResult(int, String)
,
Constant Field Valuespublic static final java.lang.String MSG_EVENT_RESULTPROPS
This is one of two possible results formats supported by the protocol. This format is defined for remote clients that CAN "load" and "store" Java Properties. The log comment and log detail, if any, should be sent by the remote client before issuing this result.
Example:"event:resultprops:"
The event message above must be terminated by the EOM marker.
The remote client is expected to transmit the message above following immediately by the invocation of the Properties.store algorithm. Upon receiving the EOM this server will immediately invoke the execution of the Properties.load algorithm. The Properties load and store algorithms do not require any additional EOM marker.
Once received, the retrieved Properties will be routed to any registered SocketServerListener.
MSG_ENGINE_COMMENT
,
MSG_ENGINE_DETAIL
,
MSG_EVENT_RESULT
,
Properties.load(InputStream)
,
Properties.store(OutputStream, String)
,
SocketServerListener.onReceiveResultProperties(Properties)
,
Constant Field Valuespublic static final java.lang.String MSG_EVENT_SHUTDOWN
SocketServerListener.onReceiveShutdown()
,
Constant Field Valuespublic static final java.lang.String MSG_SERVER_DISPATCHFILE
This is one of two possible dispatch formats supported by the protocol. This format is defined for remote clients that cannot "load" or "store" Java Properties.
This filepath format allows the local server/engine to place command contents in an accessible file/URI location to be handled by the remote client.
Example message: "dispatchfile:filepath"
The full message will be sent terminated by the EOM marker.
Following a successful dispatch, a local engine implementation should normally expect to
receive a Running event from the remote client.
SocketServerListener.onReceiveRunning()
,
Constant Field Valuespublic static final java.lang.String MSG_SERVER_DISPATCHPROPS
This is one of two possible dispatch formats supported by the protocol. This format is
defined for remote clients that CAN "load" and "store" Java Properties.
Example message: "dispatchprops:"
The event message above must be terminated by the EOM marker.
The local server will transmit the message and EOM above following immediately by the invocation of the Properties.store algorithm. Upon receiving the EOM the remote client is expected to immediately invoke the execution of the Properties.load algorithm. The Properties load and store algorithms do not require any additional EOM marker.
Following a successful dispatch, a local engine implementation should normally expect to receive a Running event from the remote client.
SocketServerListener.onReceiveRunning()
,
Constant Field Valuespublic static final java.lang.String MSG_SERVER_SHUTDOWN
SocketServerListener.onReceiveShutdown()
,
Constant Field Valuespublic static final java.lang.String MSG_SERVER_MESSAGE
MSG_ENGINE_MESSAGE
,
SocketServerListener.onReceiveMessage(String)
,
Constant Field ValuesConstructor Detail |
---|
public SocketServer()
public SocketServer(SocketServerListener listener)
listener
- SocketServerListener to register with the new instance.Method Detail |
---|
public java.lang.String getProtocolMessageSeparator()
public void setProtocolMessageSeparator(java.lang.String charSeparator) throws java.lang.IllegalArgumentException
the
- single String separator character to use between the message prefix and content
in the SAFS TCP protocol.
Normally, this is never changed. The local SAFS engine and remote client implementations--coded
together--share in an implied contract of what this separator shall be since both ends of
the TCP protocol must use it.
java.lang.IllegalArgumentException
- if the String argument is null or length() <> 1.public java.lang.String getEOM()
public void setEOM(java.lang.String marker) throws java.lang.IllegalArgumentException
marker
- String to use for terminating all String messages in the SAFS TCP protocol.
Normally, this is never changed. The local SAFS engine and remote client implementations--coded
together--share in an implied contract of what this marker shall be since both ends of
the TCP protocol must use it.
java.lang.IllegalArgumentException
- if the supplied marker argument is null or zero-length.public void setServerName(java.lang.String name)
serverName
- to provide for this SocketServerpublic java.lang.String getServerName()
public boolean addSocketServerListener(SocketServerListener listener)
listener
-
public boolean removeSocketServerListener(SocketServerListener listener)
listener
-
protected boolean createClientConnection(int sTimeout)
sTimeout
- in seconds to keep trying to make the connection
public boolean isConnected()
protected boolean verifySAFSClient(int sTimeout)
sTimeout
- in seconds to wait for proper client response.
MSG_SERVER_VERSION_QUERY
protected void closeSocket()
protected java.lang.String receiveClient(long msTimeout) throws java.io.InvalidObjectException
msTimeout
- timeout in milliseconds
java.io.InvalidObjectException
- if we have no InputStream connected.EOM
protected boolean sendClient(java.lang.String message) throws java.io.InvalidObjectException
message
-
java.io.InvalidObjectException
EOM
public boolean sendDispatch(java.util.Properties trd)
"dispatchprops:" immediately followed by a Properties serialization stream.
The remote client is expected to receive the Dispatch and immediately commence loading the Serialized Properties stream and attempt to pass the Properties along to the actual remote engine.
Properties
- trd to Serialize over the connection.
MSG_SERVER_DISPATCHPROPS
,
Properties.store(OutputStream, String)
,
Properties.load(InputStream)
public boolean sendDispatch(java.lang.String filepath)
"dispatchfile:filpath"
The remote client is expected to receive the Dispatch and forward the filepath info to the actual remote engine.
trd
- filepath
MSG_SERVER_DISPATCHFILE
public boolean sendMessage(java.lang.String message)
The remote client is expected to forward the message to the remote engine with the "message:" prefix stripped off. These messages are NOT part of the standard SAFS protocol and it is up to the local and remote engines to know what to do with them.
message
-
MSG_ENGINE_MESSAGE
,
sendClient(String)
public boolean sendShutdown()
MSG_SERVER_SHUTDOWN
,
sendClient(String)
public boolean sendListenerDebug(java.lang.String message)
message
-
MSG_ENGINE_DEBUG
,
sendClient(String)
public void run()
Typcial instantiation and usage sequence is as follows:
tcpServer = new SocketServer(SocketServerListener);
tcpServer.setServerName(process_name);
tcpServerThread = new Thread(tcpServer);
tcpServerThread.start();
...
tcpServer.shutdownThread(); // if and when appropriate
The thread constantly loops performing the following tasks:
Note that local engine to remote client communication is NOT handled in this thread. Once the remote connection is made, the local engine (SocketServerListener) is notified via onReceiveConnected(). Subsequent messages sent from the local engine to the remote client are sent via the local engine's thread using the "send" methods of the SocketServer instance. Consequently, the two-way communication should be considered asynchronous. Though it is expected the local and remote clients will attempt to maintain whatever synchronous communication is appropriate for their shared implementation.
run
in interface java.lang.Runnable
SocketServerListener
,
JavaSocketsHook
public boolean getKeepAlive()
public void setKeepAlive(boolean keepAlive)
keepAlive
- the keepAlive to setpublic java.lang.String getRemoteHostname()
public void setRemoteHostname(java.lang.String hostname)
the
- server hostname on which we expect remote clients to accept connections.public int getRemotePort()
public void setRemotePort(int port)
remote
- server port on which the remote client is accepting connections.public int getConnectedProtocol() throws java.io.InvalidObjectException
java.io.InvalidObjectException
- if we have not successfully connected to a remote client.public int getClientConnectTimeout()
public void setClientConnectTimeout(int clientConnectTimeout)
clientConnectTimeout
- in secondspublic void shutdownThread()
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |