Cyclops Protocol Documentation

Protocol Version 1 (prototype)

This document is rendered from an XML source which contains all of the protocol information. Click here to see the XML Source document.


Phases

This protocol is divided into three separate phases: the initial connection phase, the standby/robot selection phase, and the final robot-and-client connected phase. Phases are modes of operation to synchronize actions of a client, robot, and the state of the server thread hosting them. By default, a newly started client or robot should be in phase ONE (the initial phase). This phase remains so until they connect to a server, and the server declares a phase shift (phase number will be provided by the server). If a client or robot disconnect from the server or shut down, they should leap back to phase TWO and reset all variables associated with their previous interactions. See below for a description of the phases.

Phase 1: Initial connection phase. All clients and robots start at this phase. This phase covers the process of a robot or client initially connecting to the server, authentication of said client or robot, and a switch into phase 2. If an error or disconnect occurs during this phase, the server should drop the connection.
Phase 2: This is the phase where a client user selects which robot he/she wants to control. The server is responsible for updating the list of available robots to the client whenever necessary, and the client to display those changes to the user. In this phase, the robot awaits further instructions from the server while maintaining a connection. Once a client chooses a robot, and that robot is confirmed available, phase 3 starts. If at any time in phase 2 an error occurs, all still-active parties must be reset to the beginning of phase 2 and await instructions (again) from the server.
Phase 3: During this phase, the robot and client communicate with each other (robot sends UDP media data directly to client, client sends TCP commands to the robot through the server). During this process, the server must listen to both the client and robot, and inform the other party of any disconnects, errors, and so fourth. If an error occurs from either side, a party disconnects, or the client wishes to reset (stop using the robot and choose again), all still-active parties must be reset to the beginning of phase 2.

See below for detailed definitions of the protocols on a per-application basis and for information on handling phase transitions.


Server

The server is responsible for administrating the initial connections of a client or robot into the network, and then ensuring the link between a robot and a client. During the initial connection of a robot or client, a server must authenticate them using the given username/id and password, and decide whether or not that particular user or robot is allowed into the network. Once connected, a client must be ensured the option to select from a list of available robots to that account (this can be all of them). Once a client selects a robot, a link must be established between the client and its chosen robot. Once a link is established, the server is responsible for handling TCP messages between the client and robot, as well as informing each if the other disconnects or receives an error. The server is also responsible for informing either end to reset back into phase 2, or to disconnect completely. The server maintains administrative power to remove any client or robot from the network, and to override control of any robot connected to it. The server may or may not have authorization to change the authentication database (implementer's choice). The server should be able to host multiple robots and multiple clients (as well as multiple links of them) at any given time, though the number of allowed connections may be restricted.

When receiving any connection:
Spawn a new thread, and wait to differentiate between a connecting robot or client (each type may have sub-types). If it is neither, or the protocol is mismatched, automatically send a REJECT message, close the connection and end the thread. If it is determined to be a valid client or robot, continue with the procedures noted below as necessary. The below procedures are divided into phases. This is the beginning of phase 1.

When a Client connects - PHASE 1:
*** If a client disconnects at any time during this phase, close the connection and end the thread. ***
1) Client sends a CONNECTION_REQUEST header. If protocol and type are correct (and all checks out), continue, else send REJECT message (as noted above) and close the connection.
2) Send a REQUEST_LOGIN_INFO message and wait for authentication data.
3) Receive a LOGIN_INFO message and receive the data after. Collect the username and password from it, and run it through an authentication function (authenticate based on type of user, too). If authentication is NOT confirmed (not accepted), send a REJECT message and close the connection. Otherwise continue.
4) Send a PHASE_CHANGE to the client (changing to PHASE 2 [two]), and continue with phase 2 as described below. NOTE: This may be a good reset point - phase two may need to be restarted. See code samples/help for more information.

When a Client connects - PHASE 2:
*** If a client disconnects at any time during this phase, close the connection and end the thread. ***
5) Collect a list of available robots (connected and ready for use, and authorized for use by this connecting client), and send a ROBOT_LIST message followed by the appropriate data containing the names of all available robots.
6) Wait for a ROBOT_SELECTION message from the client indicating which robot the user chose to control. During this time, if new robots connect to the server, all clients waiting in this step should be sent the updated version of the robot list. The client should be added to a list of waiting clients to who all refreshed robot lists are sent. See code samples/help for more information - this should be done along multiple, mutex-protected threads.
7) Once a robot selection is made by the client, remove the client from any waiting lists. Collect the chosen robot and remove it from the robot list (see below - When a Robot connects). Check to ensure that the robot is still connected and available. If it is, send a REQUEST_STREAM_SOCKET_INFO message to the client.
*** Note: if the client disconnects at this point, re-list the robot in the available robots list before closing the connection. ***
8) Receive a STREAM_SOCKET_INFO response from the client, and collect all the data from this buffer (IP address and port for client's UDP socket).
9) Now send the received data in another STREAM_SOCKET_INFO to the robot as it came from the client (same information). At this point, the robot will expect to receive a phase change, or another stream socket info package. Until receiving a phase change to phase 3, the robot will remain in phase 2.
10) Finally, send the PHASE_CHANGE message to both (client first, then the robot) to switch to PHASE 3 (three). Now run phase 3: since phase 3 involves both the client and robot, see "When a session (robot + client) is established" below.

When a Robot connects - PHASE 1:
1-4) Follow the steps of "When a Client connects - PHASE 1" until phase 2 is reached. The steps to connecting a client and a robot are identical, except for the authentication (the robot's id and type is different from that of a client). After steps 1-4 are complete, see below for phase 2.

When a Robot connects - PHASE 2:
*** If the robot disconnects upon any of these data transfers listed below, send a RESET message to the client which chose it, indicating that the client should reset to phase 2, and then close this robot's connection. ***
5-8) During these steps of "When a Client connects - PHASE 2" do only the following: add this robot to a list of all connected robots waiting in these steps. The connection between robot and server must be kept open, but the thread can be ended. The robot now listens for a message from the server (see step 9). The server may, at this time, choose to disconnect the robot for any reason by sending a DISCONNECT message. The server may also, optionally, check the robot's connection state periodically and remove it from the list and close the socket if the connection died.
9) See step 9 of "When a Client connects - PHASE 2" and follow the instructions there (these instructions are only executed when a client completes its part of the protocol). Step 9 may be repeated as many times as necessary (if client disconnects, or fails in some other way) - the robot waits for new STREAM_SOCKET_INFO messages until a phase change message (see step 10).
10) Refer to step 10 of "When a Client connects - PHASE 2".

When a session (robot + client) is established - PHASE 3:
11) At this time the robot and client are expected to have established their own UDP communication. The server must now spawn two threads: one will listen for messages from the client, and the other will listen for messages from the robot. If either thread returns, stop the other thread and proceed as necessary. See step 12A for how to handle messages from the client, and see step 12B for how to handle messages from the robot. Threads must notify a return type of the following conditions: continue (the client will be reset to phase 2) or break (the client socket is to be closed and disconnected).
If a read from or write to the client fails (client disconnected) at any time, send a RESET message to the robot, add the robot back into the robot list and return from the thread. Thread return should indicate "break" - client is disconnected. The robot should return to step 5 of "When a Robot connects - PHASE 2", where it will wait once more for a client to choose it, while this thread may be ended.
If a read from or write to a robot fails (robot disconnected) at any time, close the robot socket and return from the thread. The thread return should indicate "continue" - client will be reset to phase 2. In this case, send a RESET to the client, and return to step 5 of "When a Client connects - PHASE 2".
12A) MESSAGES FROM CLIENT:: listen to messages from the client on a thread. Use the following list as a guide on how to deal with receiving different messages:
12A - 1) COMMAND: read the command data, and send it to the robot as a forwarded command package.
12A - 2) DISCONNECT: send a RESET message to the robot, add the robot back to the robot list, and return from the thread with a "break" - that is, the client socket should be closed and thread ended.
12A - 3) RESET: send a RESET message to the robot, add the robot back to the robot list, and return from the thread with a "continue" - that is, the client should be reset back to step 5 of "When a Client connects - PHASE 2".
12A - 4) SHUTDOWN: At the moment, this header should be ignored. Do nothing upon receiving this, and continue listening for more messages. Later on, it is intended to actually shut down the robot program (exit()).
12A - 5) ERROR: This is handled with the error protocol. At this time, the error protocol is mostly undefined. Thus, upon receiving this message, collect the error data, and do nothing, and continue listening for more messages.
12B) MESSAGES FROM ROBOT:: listen to messages from the robot on a thread. Use the following list as a guide on how to deal with receiving different messages:
12A - 1) DISCONNECT: this header should not really be received. However, in the case it does, treat this like a regular robot disconnect (see above - "If a read from or write to a robot fails...").
12A - 2) ERROR: This is handled with the error protocol. At this time, the error protocol is mostly undefined. At this time, upon collecting this data, simply forward it in an error message package to the client. The client may have ways of dealing with it (i.e. if no camera is detected, the error would provide a reason as to why the connection was cut off).
If the server dies, the client and robot should both be disconnected and reset to phase 1. The client may have the user prompt for a reconnection, and the robot may have an automatic reconnection attempt system set on a timer, but none of these features are vital to the protocol.

Uh, I'm so lost... what?
It's complicated... The CLIENT and ROBOT perspectives of the protocol description may give better insight on how the protocol works. Please note that this describes the protocol, and now the means of implementing it - as that is completely up to the program's creator.


Client

A client provides the end-user with means to authenticate him/herself, and to gain access to a robot selected from an availability list. Once a robot is selected, the client must provide a means for the user to control the robot's basic functions, and (recommended) features allowing the control of all other legal functions as well. Throughout this transaction, the server retains administrative control and can selectively force both the client and robot to terminate the session. The client must remain connected to the server at all times, even when speaking directly to a robot. A client may have the ability to connect directly to a robot via UDP, directly via TCP, or it can use the server for forwarding a robot's communications between the UDP and/or TCP connections when necessary.

PART I - When connecting to a server (PHASE 1):
1) Collect login information from the user (a username, 25 characters or less), and a password (MD5 encrypted, or 32 or less characters).
2) Send a CONNECTION_REQUEST header to the server. Expect a reply with either a REJECT message - in which case the client should close the connections - or a REQUEST_LOGIN_INFO message - in which case, continue.
3) After receiving the request for login information, add the user's given info into a correctly-formatted data buffer, and send the LOGIN_INFO message followed by the data. See the header information on how to format data. Usertype MUST be a type of client. See TCP Protocol Definitions for more information on user types.
4) Await response from server. If information was not authenticated, a REJECT message will be sent. In this case, inform the user that login was unsuccessful (rejected) and close the connection. Otherwise, a PHASE_CHANGE message should be received, indicating a phase change to PHASE 2 (two). Right after, receive a ROBOT_LIST message containing a list of all available robots the user may choose to connect to. Continue immediately with phase two instructions below.

PART II - Selecting a robot (PHASE 2):
5) Display the contents of the robot list received to the user, and await selection. Expect to receive a ROBOT_LIST message from the server at any time during this phase containing an updated robot list, which may remove or add robots. The list should be re-displayed each time.
6) Once the user selects (and confirms, should you choose to add a confirmation dialog) a robot from the most recent list, send a ROBOT_SELECTION message to the robot containing the name/id of the robot that the user has chosen. The client MAY NOT send the name/id of a robot that has been removed from (or never existed on) the list. If the server's response is a new list of robots, repeat step 5. Otherwise continue.
7) Receive a REQUEST_STREAM_SOCKET_INFO message from the server. NOTE: Other types of clients may have different actions on this step.
8) Create a UDP Client (protocol-implementing class) on any available PORT number and address. Collect the address and port information from the client, and send it to the server with a STREAM_SOCKET_INFO message. This will be the socket that the client receives video and audio data on. NOTE: Other types of clients may have different actions on this step.
9) Receive a PHASE_CHANGE message from the server indicating to go to PHASE 3 (three). Maintain a connection to the server, and continue with phase three instructions below.

PART III - Controlling the robot and receiving video/audio (PHASE 3):
10) Listen for video and audio messages (see UDP Audio/Video Header Definitions for information on receiving UDP data) on the UDP client created in step 7. Display/play the data as it arrives. Use a separate listening thread for this. On the main thread, listen for user's commands; that is, keyboard press-and-release commands as well as any other action/input available for controlling the robot. Refer to TCP Protocol Definitions for command references on how to assign values to each action. Once a command/action is collected, immediately send it to the server (which will by default forward it to the robot) - more information coming soon. NOTE: Other types of clients may have different actions on this step.


Robot

A robot program provides the robot (machine) with networking and ability to be controlled through a server-authenticated client. It also uses this software to automatically look to the server for a connection, diagnostic updates, and software updates.


TCP Protocol Definitions

This section provides details on lengths and types of data. See below (message headers) for details on headers.

PROTOCOL VERSION:
PROTOCOL_VERSION 1

USERTYPE:
USERTYPE_ROBOT 1
USERTYPE_CLIENT 2

CONNECTION INFORMATION SIZE:
USERNAME_SIZE 25
PASSWORD_SIZE 32

COMMAND TYPES (data):
FORWARD (press) 1
FORWARD (release) 2
BACKWARDS (press) 3
BACKWARDS (release) 4
LEFT (press) 5
LEFT (release) 6
RIGHT (press) 7
RIGHT (release) 8


UDP Audio/Video Header Definitions

This section provides information on how audio and video streaming data packets should be constructed and read in UDP. This is the protocol set for UDP robot-to-client based communication methods ONLY. These headers must be packed as the FIRST BYTE in each UDP packet sent. Additionally, it should be noted that the maximum allowed UDP packet size is 65507, and otherwise large packets may cause problems. The recommended packet size is less than 10k. The receiver of any UDP packets should expect a 65507 size packet, but needs to only use the size returned by the socket (the actual packet size).

VIDEO FRAMES:
DATATYPE_JPEG_FRAME 1
DATATYPE_UNCOMPRESSED_FRAME 1

AUDIO SAMPLE:
DATATYPE_WAV_SAMPLE 10
DATATYPE_MP3_SAMPLE 11


Message Headers (TCP)

***All Headers are defined as follows***
len = 6: [ | protocol # (char - 1) | type (char - 1) | length (int - 4) | ]
All headers must be followed directly with a DATA buffer exactly the size indicated by the length field. For example, if the last 4 bytes of the header represent the int "512", then the following piece of data sent MUST be a 512 byte buffer with the appropriate contents.

CONNECTION_REQUEST: Sent to request a connection to the server (by client or robot). This must be the first header sent by any connecting agent.
"protocol #" is the current protocol version.
"type" (char) 1.
"length" = (int) 0.
"DATA" no data is sent. Expect a non-accepting reply with a REJECT, ERROR, DISCONNECT, or expect an accepting REQUEST_LOGIN_INFO message.

REJECT: Server sends this header to inform a rejected connection request.
"protocol #" is the current protocol version.
"type" = (char) 2.
"length" = (int) 0.
"DATA" no data is sent after this. Connection should be terminated by the server immediately after this message is sent.

ERROR: If an error occurs that conflicts with the standard data flow, this header is sent. See ERROR documentation for more details on when to send errors.
"protocol #" is the current protocol version.
"type" = (char) 3.
"length" = (int) 4.
"DATA" 4 bytes (int) indicating the error number.

DISCONNECT: Send to inform an eminent disconnection. The sender typically disconnects immediately afterwards.
"protocol #" is the current protocol version.
"type" = (char) 4.
"length" = (int) 0.
"DATA" no data is sent after this. Connection should be terminated by the sender immediately after this message is sent.

REQUEST_LOGIN_INFO: Server sends to client or robot indicating to proceed with the protocol, and expects the next reply to contain proper login information.
"protocol #" is the current protocol version.
"type" = (char) 5.
"length" = (int) 0.
"DATA" no data is sent.

LOGIN_INFO: Client or robot send this immediately after receiving the REQUEST_LOGIN_INFO message. This contains username and password (encryption recommended). Password should be in MD5, but does not have to be.
"protocol #" is the current protocol version.
"type" = (char) 6.
"length" = (int) ? ([2] + [length of username] + [length of password]).
"DATA" 1 byte indicating the USER_TYPE (char), followed by username (one byte per character in username string), followed by a NULL byte (char 0), followed by password (one byte per character in password string). Password should be MD5 encrypted.

PHASE_CHANGE: Server sends this header to inform a shift into an operating phase.
"protocol #" is the current protocol version.
"type" = (char) 10.
"length" = (int) 1.
"DATA" 1 byte (char) indicating the phase that receiver should switch to.

ROBOT_LIST: Server sends a list of robots to a client which that client may choose to control.
"protocol #" is the current protocol version.
"type" = (char) 11.
"length" = (int) ? (for each robot, the length of the robot's id/username + 1 byte).
"DATA" for EACH ROBOT in the list: the username/id of the robot (one byte per character in the username string) followed by a NULL byte (char 0). In another words, all of the robot names in sequence terminated by null bytes.

ROBOT_SELECTION: Client sends this to indicate which robot the user chose to control.
"protocol #" is the current protocol version.
"type" = (char) 12.
"length" = (int) ? (length of the robot's username/id).
"DATA" the username/id of the robot (one byte per character in the username string).

REQUEST_STREAM_SOCKET_INFO: Server sends a request for video/audio/data streaming socket information, expecting a REQUEST_STREAM_SOCKET reply package. The server must expect what kind of a communication method this information will be used for based on its previous determining of what type of client/robot is connected.
"protocol #" is the current protocol version.
"type" = (char) 20.
"length" = 0.
"DATA" no data is sent.

STREAM_SOCKET_INFO: Video/Audio/Data streaming socket information sent to server upon request. Server must determine how to handle this data (i.e. TCP/UDP forwarding, or UDP-direct, etc.) depending on the type of system that sent it.
"protocol #" is the current protocol version.
"type" = (char) 21.
"length" = (int) ? (size of address + 4).
"DATA" Send the IP address (one byte per char), followed by 4 bytes for the int PORT number.

RESET: Sent by a server to either the client or the robot currently connected and interacting in phase three to indicate a reset from phase 3 back to phase 2 when one of the interacting members (robot or client) experience an unrecoverable disconnect or error. Upon receiving this message, phase 2 procedures should be handled (see protocol steps documentation for details).
"protocol #" is the current protocol version.
"type" = (char) 30.
"length" = 0.
"DATA" no data is sent.

SHUTDOWN: Sent by a server to the robot. This should successfully disconnect the robot and force itself to shut down.
"protocol #" is the current protocol version.
"type" = (char) 31.
"length" = (int) 0.
"DATA" no data is sent.

COMMAND: Sent by a client to a robot (and forwarded by the server) to give a command to the robot from the user. See TCP Protocol Definitions for information on what commands are labelled as.
"protocol #" is the current protocol version.
"type" = (char) 100.
"length" = (int) 2.
"DATA" 1 byte (char) representing a command action. IF and only if the command is a camera motion action, the second byte must a byte-numerical representation of the degrees wished to achieve (0-180). Otherwise, the second byte is blank/null.


ERROR Documentation

This is a list of errors (and their identifying numbers) that should be understood by all programs implementing this protocol in the event that someone sends an error. These errors should be used wisely and accurately in events where they are needed. Errors received that are not listed here should be ignored by the receiver.

General Errors:
SOME_ERROR 0


Back to Cyclops