1. Current OpenVerse protocol. ~ A protocol is a standardized language spoken by nodes on a network in order to communicate with each other. The OpenVerse protocol is currently divided into several parts: the control connection, ORT registration and login, and DCC file transfer. 1.1. The control connection. ~ The control connection protocol consists of newline-delimited packets, each of which is a command word followed by any number of space-prefixed arguments. An empty field is indicated by sending two contiguous spaces. Two empty fields would be represented by three contiguous spaces, and so on. See below for examples. To join an OpenVerse server (room), a client opens the control connection to a specified port on a server. The server's name and port are previously arranged, through configuration, a history list, room exits, or other means. The client authenticates itself to the server, and the server then sends the client information about the current state of the room: room name, room image, list of users, list of objects. After this the server continues to give the client updates about events in the room, such as movement, users entering and leaving, and chat. The client sends the server information about its own moves and chatting and so on, and the server relays this information to the other clients. 1.1.1. Creating the control connection. ~ The client opens the connection and immediately sends an initial command. The valid commands at this point are AUTH, USERS, and TRANS. If the server sees there are too many simultaneous connections from a single source address, it sends "TOOMANYCONNECTIONS" and kills the connection. If the server determines that there are too many users already in the room, it sends "ROOMFULL" to the client, and both disconnect. Both of the above tests are common to the AUTH, USERS, and TRANS initial commands, so if a user already has several chat connections, he or she may not be able to issue a USERS command, or an ORT server on his or her machine may fail to connect. Also if the room has exactly the maximum number allowed users, a user count query (USERS) will fail with ROOMFULL. If the client sends a command other than AUTH, USERS, or TRANS, "AUTH REQD" is sent by the server and the connection is killed. This can be confusing because shortly after the client opens the connection the server sends "PING", and if the client responds with "PONG" before issuing any other command it gets disconnected. This may confuse AUTH, USERS, and TRANS response parsers. After all this testing, the command is processed. 1.1.2. Joining the server. ~ 1.1.2.1. Client login. ~ The client opens the connection and sends: > AUTH nick pos-x pos-y av-name name-x name-y av-size balloon-x balloon-y < {nick} Desired nickname of the user. Cannot contain spaces. {pos-x} Desired initial X coordinate. Rooms are 640 pixels wide. {pos-y} Desired initial Y coordinate. Rooms are 480 pixels tall. {av-name} Name of the user's avatar image file. Includes any filename extension (currently just .gif). Cannot contain spaces. {name-x} X position of the center of the nametag relative to the center of the avatar image. {name-y} Y position of the center of the nametag relative to the center of the avatar image. {av-size} Size of the avatar image file in bytes. {balloon-x} X position of the base of the point of the balloon relative to the center of the avatar image. See below for diagram. {balloon-y} Y position of the base of the point of the balloon relative to the center of the avatar image. See below for diagram. .--------------------. The N indicates the point by which .' `. the speech balloon is placed. __| | -< N | The same point on the opposite side ""| | is used for balloons facing the `. .' other direction. `--------------------' 1.1.2.2. Validation. ~ The fields are tested for validity using the following rules: Field Numeric-Only Max-Length Min-Value Invalid Unique ~ {nick} checked checked {pos-x} checked 3 0 {pos-y} checked 3 0 {av-name} {name-x} checked 4 {name-y} checked 4 {av-size} checked 6 0 {balloon-x} checked 4 {balloon-y} checked 4 Num-Only is (erroneously) defined as containing only characters in the set "-0123456789". As a consequence, the server will allow values such as "0-0" with unpredictable results. The Num_Only test is the first performed. If the test fails for any field, "AUTH FAILED (Non Numeric)" is sent to the client and the connection is closed. The client does not appear to have any code to process this message; instead it assumes it will never happen, which is a mistake because the client will be left in an unpredictable state when connecting to a broken server or in case of a version mismatch. Max-Length is the maximum number of characters in the field. The minimum length for all fields is zero characters, not one character as may be expected. If the Max-Length test fails, "AUTH FAILED (String Lengths)" is sent and the connection is closed. The client does not have code to handle this error message. Min-Value is the minimum numeric value for the field. If the field numerically compares as less, "AUTH FAILED (String Lengths)" is sent and the connection is terminated. The client ignores this error message. The Invalid test is then performed on the {nick} field [1]. If {nick} is an empty string, a one-character string consisting of only "*" or ".", or a string whose first character is "-", the server rejects it, sending "BADNAME" to the client and killing the connection. {nick} is then checked for uniqueness. if the name {nick} already belongs to another user in the room, the server sends "NAMEINUSE" to the client over the control connection, and the connection is closed. To the server, nicknames are case-sensitive, so "Joe" and "joe" can both be in the room at the same time. This contrasts with some parts of the client, and is one difference than standard IRC policy. Lastly, each server object gets a chance to disconnect the client. If a server object decides to disconnect, it is its responsibility to first send a reason code to the client. 1.1.2.2. Room name and image. ~ If the client is still connected after all these checks, the user is finally admitted to the room. The server sends: > ROOMNAME room-name ROOM img-name img-size < {room-name} Name of the room. Can contain embedded spaces. {img-name} Name of the room background image file. Cannot contain spaces. {img-size} Size of the room background image file in bytes. Note that the client can handle these commands at any time, therefore the room server can change the room name or background image without forcing reconnects. The client also always recognizes the above error messages, with the exception of the AUTH errors, which it never recognizes. Upon reception of ROOM, the client checks to see if it already has a room image file of the given name and file size. If not, it requests the room image file from the server, with {img-name} as above: > DCCSENDROOM img-name < File transfers are discussed in greater detail below. Notice the potential for collision between room image filenames. This is especially troublesome with personal servers using the default name "room.gif" but with customized graphics. Also if a server changes its room image yet keeps the same name, if the file size remains unchanged (which is quite possible since room images are nearly always 640x480, except with ELC's client and server) the client will never know. 1.1.2.3. OpenVerse Rapid Transit (ORT). ~ After describing the room name and image to the client, the server checks to see if it is currently hosting an ORT. The server does not support more than one simultaneous ORT. If it has an ORT stopped, it sends the client a user and an exit object to represent the ORT: > NEW nick pos-x pos-y av-name name-x name-y av-size balloon-x balloon-y < {nick} Nickname of the ORT; shown in nametag. Can't include spaces. {pos-x} X coordinate of center of the ORT image. {pos-y} Y coordinate of the center of the ORT image. {av-name} Name of the avatar image file used to display the ORT. {name-x} X coordinate of the nametag. Constant "0". {name-y} Y coordinate of the nametag. Constant "60". {av-size} Size of the avatar image file in bytes. {balloon-x} X coordinate of the speech balloon. Constant "66". {balloon-y} Y coordinate of the speech balloon. Constant "-44". > EXIT_OBJ obj-name left top right bottom duration host port < {obj-name} Name of the exit object. Constant "ov_tram_exit". {left} Left edge of the ORT. Calculated {pos-x} - 60. {top} Top edge of the ORT. Calculated {pos-y} - 60. {right} Right edge of the ORT. Calculated {pos-x} + 60. {bottom} Bottom edge of the ORT. Calculated {pos-y} + 60. {duration} Duration value of exit. Constant "0" (infinite). {host} Name or network address of the destination server. {port} Port number of the room on the destination server. To the client, the visible portion of the ORT is an ordinary user, capable of chatting, receiving files, and being queried, ignored, or whois'ed. The nametag and balloon are positioned as with the AUTH command, as above. The functional portion of the ORT is an ordinary exit object, which the client has the option of honoring or ignoring. Its duration is set to infinite, with the expectation that it will be explicitly deleted later. The nametag and balloon locations, unfortunately, are not configurable, and will look strange with ORT images not the same size as the standard train. Also the exit object is always a 120x120 square centered on the ORT image. This can be very confusing for larger or smaller ORT images. Plus, the exit object name is always "ov_tram_exit", so no more than one ORT can be in a room at a single time. ELC fixes this. In most places it's known as the ORT/OpenVerse Rapid Transit, but it's also known as the Ort, the OV Tram, a Transport, and in one place, "The Bus". 1.1.2.4. Server objects. ~ Every time a user joins the room, all the server object files are sourced. The server object files are expected to send commands to the client indicating their presense. Unfortunately, server object files are also expected to initialize themselves at this time, so they need to track whether or not they have been previously initialized. They also register hooks during this initialization, and unless the server object is very careful, all hooks are re-registered every time a user enters the room, which is a terrible memory leak and may lead to duplicated processing and other potential problems. This bug exists in version 0.8-7 but has since been fixed in ELC's code. Furthermore, prior to the first user entering the room, no server objects have been sourced and therefore cannot be initialized, so no server object can disconnect the first user to enter the room (see above). 1.1.2.5. Informing other users. ~ After the server announces the ORT and other server objects are sent to the new user, it then sees to sending the other users in the room informationa bout the newly-joined client. In each case below, the server sends all clients, including the one that just joined, notification about the user, with the following command: > NEW nick pos-x pos-y av-name name-x name-y av-size balloon-x balloon-y < These fields are analogous to those of AUTH (see above). First the server checks to see whether or not it already has the avatar image file the client wants to use. If not, it pretends for a moment that the new user wants default.gif, and sends this to the other users in the room. More specifically, it hard-codes certain fields as follows: {av-name} "default.gif". {name-x} "0". {name-y} "20". {av-size} The size, in bytes, of the default.gif file on the server. {balloon-x} "24". {balloon-y} "6". These values are repeated again below for other cases, as specified. It also begins a file transfer to get the real avatar from the client, and when the upload is done the server tells the other users that there was an avatar change. If the server does in fact already have an avatar image file with the asme name as the one requested, it next checks to see if the server's avatar image file size is equal to {av-size} bytes. If they do not match, the procedure for not having the avatar image file is followed. If they do match, the avatar image file is checked for validity and acceptable dimensions. If the file is not in GIF format or has width or height greater than the server-configured maximums, the above procedure is again followed, except that no file transfer is performed. Instead the server sends to the new client: > TOOBIG widthxheight < Where {width} and {height} are the maximum width and height values the server is willing to accept. {width} and {height} are separated by the letter "x". If the server already has the image file and determines that it is a GIF of suitable size, all the fields are broadcast just as they appeared in the client's initial AUTH line. Note that the first NEW command that a client sees upon connecting to the server is the one describing him or herself, unless there is an ORT in the room, or possibly another server object that creates a fake user (currently none known). This confuses an old version of ovcon, which was developed prior to the ORT: It assumed that its own user would be the first echoed back, but with a nickname truncated and otherwise massaged to suit the server, and therefore assumed that its own name was equal to that of the first NEW. IF there was an ORT in the room, it took on names such as "ORT_Number_1", much to the user's consternation. This also means that the user sees his or her avatar below all other avatars in the room excepting the ORT, yet above any server objects except those created dynamically, unless the server also sends an ABOVE, which some versions do. All very confusing... 1.1.2.6. Populating the room. ~ The final step of connecting to a room server is the server sending the new client a list of users in the room. For each authenticated user in the room besides the new user, the server sends a NEW to the new user: > NEW nick pos-x pos-y av-name name-x name-y av-size balloon-x balloon-y < The fields are as before. If the server currently has the {av-name} avatar image file, it and the rest of the fields are sent as they arrived in AUTH or as they were changed over the course of the chat. If the server does not have the {av-name} avatar image file, it instead sends the "default.gif" values, similarly to the above case of telling the existing users about the new, but duplicated here for convenience: {av-name} "default.gif". {name-x} "0". {name-y} "20". {av-size} The size, in bytes, of the default.gif file on the server. {balloon-x} "24". {balloon-y} "6". 1.1.3. Getting a user count. ~ The passageways and history facilities in the client and the room display in the ORT server employ the USERS command to check which room servers are online and how many users they each have. After opening a connection, the client immediately sends "USERS", and the server responds: > USERS count < {count} is nominally the number of users connected to the server at that time. After sending USERS, the server drops the connection. Unfortunately, {count} is not actually the number of users connected but really is the number of open sockets on the server, less one. Therefore many non-users are also counted: the ORT, not-yet-authenticated users, hanging connections, others querying for a USERS count, etc. As a result, the ORT always displays at least one user in each room, but as Cruise said this encourages users to explore new rooms, thinking people are already there, but of course this is silly---ORT users quickly learn that "1" means "0". 1.1.4. ORT authentication. ~ ================== Currently the OpenVerse control protocol is as follows: * The client opens a TCP/IP connection to the server. * They chat using messages formatted thusly: COMMAND arg1 arg2 arg3 ... argN Arguments are space-delimited. Packets are newline-delimited. File transfer ("DCC"): * To send files from client to server, the server opens a TCP socket and tells the client over the control connection which port number it is via a DCCSENDAV message. The client then connects to that port and immediately sends a hunk of data from the file. When the server is finished getting the data, it takes the total number of bytes written so far, encodes it as a 32-bit big-endian integer, and sends it to the client. When the client gets the expected number, it repeats the process until there is no more data. * To send files from server to client, the server opens a TCP socket and tells the client over the control connection which port number to connect to via DCCGET{AV,OB,ROOM}. When the client connects, the server immediately starts sending file data, and things continue as above except with the direction reversed. * To send files from client to client, the sender opens a TCP socket and sends a SUB message to the receiver (relayed through the control connection to the server) including the hostname and port to connect to. When the receiver connects, the sender immediately starts sending data, as in the above two scenarios. Advantages: Disadvantages: Alternate proposal: Advantages: Disadvantages: Chatting > CHAT < CHAT > SCHAT < SCHAT > PRIVMSG < PRIVMSG > URL < URL Movement and effects > MOVE < MOVE > PUSH < PUSH > EFFECT < EFFECT File transfer > SEND > DCCSENDAV > DCCSENDOB > DCCSENDROOM > RSEND < DCCGETAV < DCCGETOB < DCCGETROOM < DCCSENDAV The subchannel Ignore Server objects Miscellaneous > QUERY > PONG < PING Protocol basics Chat protocol Joining the room Connecting Login > AUTH Validation < AUTH FAILED (Non Numeric) < AUTH FAILED (String Lengths) < BADNAME < NAMEINUSE Room description < ROOMNAME < ROOM > DCCSENDROOM Sending ORT object < NEW < EXIT_OBJ > DCCSENDAV Sending server objects Informing other users < NEW Announcing other users < NEW < ABOVE Main chat Chatting > CHAT < CHAT > SCHAT < SCHAT > PRIVMSG < PRIVMSG > URL < URL Movement and effects > MOVE < MOVE > PUSH < PUSH > EFFECT < EFFECT File transfer > SEND > DCCSENDAV > DCCSENDOB > DCCSENDROOM > RSEND < DCCGETAV < DCCGETOB < DCCGETROOM < DCCSENDAV The subchannel Ignore Server objects Miscellaneous > QUERY > PONG < PING Leaving the room < NOMORE Reference Sending AUTH ... Receiving AUTH REQD ... File transfer protocol User total ORT login ORT registration vim:ft=help:et:tw=80:ts=8