SUPPORTDESK PROTOCOL (SP) Version 0.5 Gareth Williams May 2006 TABLE OF CONTENTS 1. INTRODUCTION 2. THE SP MODEL 2.1. Communication Modes 2.2. Timing 2.3. States 2.4. Session Length 3. THE SP SPECIFICATIONS 3.1. SP Commands 3.2. SP Command Replies 3.3. SP Event Messages 4. EXTENSIONS 4.1. Password Encryption 5. EXAMPLES ----------------------------------------------------------------------- 1. INTRODUCTION The objective of the SupportDesk Protocol (SP) is to facilitate communication between various SupportDesk clients and a central SupportDesk server connected by a TCP/IP transmission subsystem. As users login to and use the SupportDesk system, they transmit various commands to the server, with login information, messages they would like to send to other users, etc. The server will send out replies to commands that require an immediate response, such as a "LIST_USERS" command from an operator (oper), which requires an immediate response detailing the names of the users currently on the system (see section 3.1 for more information). The server will also send out event messages at any time, detailing time critical information for the client, such as a message that has just been sent to them by another client (see section 3.3 for more information). ----------------------------------------------------------------------- 2. THE SP MODEL 2.1. COMMUNICATION MODES The SP protocol has two modes of communication that can be used with each client connection. They are: operator mode (oper), and user mode (user). The mode that will be used for the duration of the connection is established at login time, before any other communication can take place, and persists until the connection ends. The two modes correspond to the two different types of user on the system. Regular users connect to the system, either by passworded login or anonymously, to ask questions of the operators. These users can only write messages in the hope that an operator will see and answer them, they can not communicate with other users. Thus the set of commands, replies, and event messages available in a user session is restricted. Operators (opers) are those who run the system and answer the questions of the users. Opers must login with a password, and are identified by their name. Opers can communicate with anyone else on the system, identify those users who do not currently have an oper reading what they are writing, ban troublesome users, shut down the server, etc. In an oper session the complete set of commands, replies, and event messages is available. 2.2. TIMING The supportdesk protocol is a combination of a command-reply based model (such as SMTP) and a realtime-events based model (such as IRC). Commands can be sent from the client, which generate replies from the server. However, some commands will not generate a reply. Other times, a "reply" will arrive without a command being sent - this is referred to in this document as an event message. The client can send the server a command at any time (provided that command is valid in the current state - no sending messages to other users before you have logged in, for example), eliciting a reply from the server, depending on the command. The server can send the client an event message at any time. An event message will never require a reply from the client. It simply provides the client with additional information as it becomes available, saving the client from needing to constantly poll the server for it. 2.3. STATES The communication channel between the client and the server can be in several different states. These states will dictate the commands that are currently valid, as well as the types of event messages that the server will transmit. The states are: (a) the user is not logged in (b) the user is logged in as a normal user (c) the user is logged in as an oper (d) the user has logged out When the communication channel is first opened, it always starts in state (a). The only commands valid in this state are "LOGIN" and "LOGOUT". Once login information is presented successfully by the client the server decides whether they are a normal user or an oper. The state then proceeds to EITHER (b) OR (c), respectively, where the majority of communication will take place. If "LOGOUT" is issued instead of "LOGIN" the state proceeds directly to (d). In state (b) a small subset of commands and event messages are available, specifically those related to sending and receiving messages. In state (c) the full set of commands and event messages are available. Once in either state (b) or (c), it is impossible to transition to the other. The only possible state transition is to (d). Once in state (d) there are no commands available. Any event messages that are already waiting may still be transmitted, after which the communication channel should be closed. Therefore there are exactly three paths possible: (a) -> (b) -> (d) (a) -> (c) -> (d) (a) -> (d) 2.4 SESSION LENGTH Each client makes a single TCP/IP connection to the server. This connection persists for the duration of the communication. "LOGIN" is negotiated, communication takes place (in both directions), and then finally "LOGOUT" is sent and the connection is closed. If the connection is dropped midway then the session is lost, and must begin again from scratch, as a new connection. ----------------------------------------------------------------------- 3. THE SP SPECIFICATIONS 3.1. SP COMMANDS An SP command defines a specific request made of the supportdesk server by a client. For each action an end user (including opers) may wish to execute (eg. sending a message, setting a ban on a particular user, logging in), there is deliberately a 1:1 mapping to a specific SP command for that action, which the client software will transmit to the server. Each SP command is a clear-text character string, containing no spaces. Some commands are followed by additional arguments. The entire command and it's arguments (if any) is terminated by a linefeed character ("LF", ASCII character 10). Arguments are separated from the command itself by a single space. Commands are case sensitive, and all commands are strictly upper case. The general syntax of an SP command is as follows: COMMAND [argument 1] [argument 2] ... Example: the "LOGIN" command. User "gareth" wishes to login to the system using the password "abc": LOGIN gareth abc The entire set of SP commands is detailed in full below. The SP replies are detailed in Section 3.2. Compulsory arguments appear within angle brackets, <>, and must be supplied with the command. Optional arguments appear within square brackets, [], and may be supplied at the discretion of the client. LOGIN [password] Available to both opers and normal users. This command is used to identify the user to the server. The first argument field must contain the name the user wishes to use on the server. This is what they will be identified with by opers. If the server requires a password for the specific name they wish to use, it must be supplied as the second argument. If no password is supplied and the chosen name is not in the server's list of passworded users then anonymous login is assumed. The server is required to respond with one of the following: INCORRECT - login failed (unspecified reason). HELLO_OPER - login succeeded and you are recognised as being an oper (impossible with anonymous login). HELLO_USER - login succeeded and you are recognised as being a regular user. Only once either "HELLO_OPER" or "HELLO_USER" is obtained can any other command besides "LOGIN" or "LOGOUT" be used. The set of commands available will then depend upon whether the user is an oper or not, distinguished by "HELLO_OPER" and "HELLO_USER" respectively. LOGOUT Available to both opers and normal users, as well as users that have not logged in as either yet but wish to gracefully drop the connection without doing so. Takes no arguments. The server is not required to respond. SEND This particular syntax is only available to normal users. This command is used to transmit messages the end user types. Note that no recipient may be specified by a normal user. The messages simply go to "the system". It is up to the opers' discretion to decide which opers will read them, and reply, if any. The only argument is the message to be sent, and is compulsory. The message begins immediately after the "SEND" command and it's compulsory following space to deliminate it from the argument, and runs until the terminating linefeed character, not including this character. The message itself may contain space characters, but may not contain any linefeed characters (as these will be interpreted as the terminating character). The server is required to respond with: ERROR - if the message wasn't sent for some reason (eg. if the "SEND" command was issued by itself, without the compulsory message argument). The server is not required to respond if the message is sent successfully. This is because the message will be echoed back to the client via the event message "MESSAGE" upon receipt anyway (see section 3.3 for more information), making a command reply redundant. SEND This particular syntax is only available to opers. This command is used to transmit messages the oper types to a specific end user (either a normal user or another oper). Note that opers must always specify a recipient. This is the first argument. The second argument is the message to be sent, and is also compulsory. The message begins immediately after the first argument and it's compulsory following space to deliminate it from the second argument, and runs until the terminating linefeed character, not including this character. The message itself may contain space characters, but may not contain any linefeed characters (as these will be interpreted as the terminating character). The server is required to respond with: ERROR - if the message wasn't sent for some reason (eg. if the "SEND" command was issued by itself, without one or both of the compulsory arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. The server is not required to respond if the message is sent successfully. If the oper is "watching" the user they are typing to, as they will be if their client is behaving in a sensible fashion (why send messages to someone without looking at the conversation?), then the message will be echoed back via the event message "ROOM" upon receipt anyway (see section 3.3 for more information), making a command reply redundant. LIST_USERS Only available to opers. This command accepts no arguments. It is provided as a mechanism for the client to deliberately poll the server for a list of users and opers currently logged in. Ordinarily the server will send event messages to all opers when new users login and logout. Examples: USER bob - the user "bob" has logged in OPER bob - the oper "bob" has logged in SYS_LOGOUT bob - the user or oper "bob" has logged out In this way, a client running in oper mode can keep it's list of who is currently online up to date (see section 3.3 for more information). However, it is possible for the client's list to be out of sync with reality. The obvious example is directly after it's own login - it will begin to receive event messages for new users logging in and out, but will know nothing of users that were already connected before it's own login. To synchronise it's own list of users the client must issue the "LIST_USERS" command. The server must then respond by re-sending a login event message for each user currently on the system, followed by the "END_OF_USER_LIST" command response. Example: the start of a typical session for the oper "gareth" (with explanations added on the right hand side) may look like this: SupportDesk Server 0.4 READY <- server is ready to begin LOGIN gareth abc <- client sends username and password HELLO_OPER gareth <- server acknowledges him as an oper LIST_USERS <- client requests current user list USER fred <- there is a user "fred" logged in USER bob <- there is a user "bob" logged in OPER sam <- there is an oper "sam" logged in USER jimmy <- there is a user "jimmy" logged in END_OF_USER_LIST <- server asserts "that is all" - the complete list has now been sent The client now has an up-to-date list of users, and can rely on event messages sent from the server to keep it in sync from now on. Note that the server does not include the oper making the request, "gareth", in the list. LIST_FLAGS Only available to opers. This command accepts no arguments. Very similar to the "LIST_USERS" command above, it is provided as a mechanism for the client to deliberately poll the server for a list of users that currently have "flags" set. Ordinarily the server will send an event message to all opers when a normal user is typing messages and has no opers "attending". The event message is "FLAG", and in plain English means "this user needs to be attended to". Once the user typing messages is being attended to by an oper, another event message is sent to all opers, called "UNFLAG", to cancel the previous flag message. Examples: FLAG bob - the user "bob" requires an oper's attention UNFLAG bob - the user "bob" no longer requires attention In this way, a client running in oper mode can keep it's list of who is currently "waiting to be served" up to date (see section 3.3 for more information). However, it is possible for the client's list to be out of sync with reality. The obvious example is directly after it's own login - it will begin to receive "FLAG" event messages for users requiring attention, but will know nothing of users that already had flags set before it's own login. To synchronise it's own list of flags the client must issue the "LIST_FLAGS" command. The server must then respond by re-sending a "FLAG" event message for each user that currently has a flag set, followed by the "END_OF_FLAG_LIST" command response. Example: continuing the previous example from the "LIST_USERS" command (above), the next thing oper "gareth" may wish to do in his typical session is synchronise his flags. Again, explanations are added on the right hand side: ... LIST_USERS USER fred USER bob OPER sam USER jimmy END_OF_USER_LIST LIST_FLAGS <- client requests to see current flags FLAG bob <- user "bob" has a "FLAG" set FLAG jimmy <- user "jimmy" has a "FLAG" set END_OF_FLAG_LIST <- server asserts "that is all" - the complete list has now been sent The client now has an up-to-date list of flags, and can rely on event messages sent from the server to keep it in sync from now on. LIST_BANS Only available to opers. This command accepts no arguments. It is provided as a mechanism for the client to deliberately poll the server for the current ban list. Ordinarily the server will send event messages to all opers when new bans are put in place or removed. Examples: BAN_IP 192.168.1.1 fred - set ban on 192.168.1.1 UNBAN_IP 192.168.1.1 - remove ban on 192.168.1.1 In this way, a client running in oper mode can keep it's own ban list up to date (see section 3.3 for more information). However, it is possible for the client's list to be out of sync with reality. The obvious example is directly after it's own login - it will begin to receive event messages for new bans, but will know nothing of bans already existing before it's own login. To synchronise it's own ban list with the server's, the client must issue the "LIST_BANS" command. The server must then respond by re-sending a BAN_IP event message for each IP address currently on the ban list, followed by the "END_OF_BAN_LIST" command response. The client now has an up-to-date ban list, and can rely on event messages sent from the server to keep it in sync from now on. Note: the user's nickname at the time the ban was set is supplied as well as the IP address with the BAN_IP event message, so that opers can more easily distinguish between bans. WATCH Only available to opers. This command is provided for opers to specify that they wish to receive the conversation stream of a particular user. Once issued successfully, the server will begin relaying messages that the specified user types (and possibly has typed in the past, depending on how many messages the particular server implementation wishes to buffer), as well as messages that other opers have typed to the user, by way of "ROOM" event messages. This command is also used to receive the conversation stream of other opers an oper wishes to converse with. Additionally, it is highly recommended that an oper issue a "WATCH" on himself when he first connects so that he will see messages other opers may send to him, as opers don't have flags. This command accepts a single argument - the name of the user to "watch". The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "WATCH" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded, and "ROOM" event messages will now be relayed. UNWATCH Only available to opers. This command is provided as a mechanism to terminate a "watch", set by the "WATCH" command above, on a specified user. Opers should use this to specify that they no longer wish to receive the conversation stream of a particular user. Once issued successfully, the server will stop relaying "ROOM" event messages for the specified user. This command accepts a single argument - the name of the user to stop "watching". The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "WATCH" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded, and "ROOM" event messages will no longer be relayed. ATTEND Only available to opers. This command is provided as a mechanism for opers to assert that they are "attending" to a particular user, and thus this user's "FLAG" that is shown to other opers can be lowered. This command accepts a single argument - the name of the user to "attend". The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "ATTEND" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded. UNATTEND Only available to opers. This command is provided as a mechanism for opers to revoke an earlier assertion that they are "attending" to a particular user, thus allowing the specified user's "FLAG" that is shown to other opers to be raised again. This command accepts a single argument - the name of the user to stop "attending". The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "UNATTEND" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded. BAN Only available to opers. This command is provided to allow opers to ban troublesome users from the system. The argument is the name of a user currently on the system. Considering anonymous logins are allowed, it is useless to ban a user by name alone. The server should therefore record the IP address the specified user is currently connecting from, as well as their username. Future connections from this IP address should be refused, with the event message "BANNED" (see section 3.3 for more information), until the ban is lifted using the "UNBAN" command. The issue of a "BAN" against a user should always result in the termination of their current connection. This command takes exactly one argument, the name of the user to issue the ban against. The name must correspond to a user currently using the system. The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "BAN" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded (on a correctly functioning server, this will hopefully be followed by a "SYS_LOGOUT" event for the specified user, as they are kicked off the system). UNBAN Only available to opers. This command is provided to allow opers to remove previously set bans without having to edit the server banlist by hand. This command takes exactly one argument, the IP address to be removed from the ban list. The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "UNBAN" command was issued by itself, without any arguments). OK - if the command succeeded, and all bans (if any) matching the IP address provided have been lifted. KICK Only available to opers. This command is provided to allow opers to temporarily kick a user off the system, without recording a permanent ban (see "BAN" command above) for them. The issue of a "KICK" against a user should result in only the termination of their current connection. This command takes exactly one argument, the name of the user to issue the kick against. The name must correspond to a user currently on the system. The server is required to respond with one of the following: ERROR - if the command failed, for an unspecified reason (eg. if the "KICK" command was issued by itself, without any arguments). NO_SUCH_USER - if the user specified as the first argument does not currently exist. OK - if the command succeeded (on a correctly functioning server, this will hopefully be followed by a "SYS_LOGOUT" event for the specified user, as they are kicked off the system). SHUTDOWN Only available to opers. This command instructs the server to shut down. Upon receipt of this command, the server program should close all network connections and then terminate immediately. This command does not accept any arguments. The server is not required to respond. 3.2. SP REPLIES An SP reply is any message that the server sends in response to a specific command sent by the client. A command can have many possible replies, one, or none. A reply must always have at least one corresponding command to evoke it. Each SP reply is a clear-text character string, containing no spaces. SP replies may not have any arguments. The reply is terminated by a linefeed character ("LF", ASCII character 10). Replies are case sensitive, and all replies are strictly upper case. Example: for commands that require a user on the system to be specified as an argument, it is possible for the specified user not to exist. When this is the case, the server must reply with "NO_SUCH_USER". The "SEND" command for opers is one such example. On a system with no user called "fred", one might observe the following: SEND fred hi there fred. <- the initial SP command NO_SUCH_USER <- the SP reply The entire set of SP replies is detailed in full below. The SP commands are detailed in Section 3.1. HELLO_USER Only sent in response to the LOGIN command. This reply indicates to the client that the server has recognised them as a user, and the communication state will now enter "user mode". HELLO_OPER Only sent in response to the LOGIN command. This reply indicates to the client that the server has recognised them as an oper, and the communication state will now enter "oper mode". INCORRECT Only sent in response to the LOGIN command. This reply indicates to the client that the server has not recognised them, for an unspecified reason, and the communication state will remain in "login mode". ERROR Sent in response to several different commands. This reply is sent to indicate that the server has not performed the requested action, for an unspecified reason. This will usually be because the command sent to it was not in the correct format, not containing the correct number of arguments for example. NO_SUCH_USER Sent in response to several different commands. This reply is sent to indicate that the server does not recognise the user specified as an argument to a command. END_OF_USER_LIST Sent in response to the LIST_USERS command. This reply is sent to indicate that the command succeeded, and all current login event messages have now been repeated. END_OF_FLAG_LIST Sent in response to the LIST_FLAGS command. This reply is sent to indicate that the command succeeded, and all current flag event messages have now been repeated. END_OF_BAN_LIST Sent in response to the LIST_BANS command. This reply is sent to indicate that the command succeeded, and all current ban event messages have now been repeated. OK Sent in response to several different commands. This reply is sent to indicate that the command succeeded. 3.3. SP EVENT MESSAGES An SP event message is any message that the server sends to the client that is not in response to a specific command. Event messages may be sent by the server at any time, in order to deliver time dependent information to the client without the need for polling. Each SP event message is a clear-text character string, containing no spaces. Some event messages are followed by additional arguments. The entire event message and it's arguments (if any) is terminated by a linefeed character ("LF", ASCII character 10). Arguments are separated from the event message itself by a single space. Event messages are case sensitive, and all event messages are strictly upper case. Example: suppose user "bob" starts typing messages with no opers currently "attending" him. A "FLAG" event message will be sent to all opers to notify them of this when it occurs: FLAG bob The entire set of SP event messages is detailed in full below. Compulsory arguments appear within angle brackets, <>, and must be supplied by the server with the event message. READY This event message is sent at the beginning of a new session to indicate that the server is ready to begin communication. This event message does not have any arguments. Note, however, that a server supporting the password encryption extension (see section 4.1 for more information) will transmit it's auth_key as the first argument to this event message. Clients that follow only the core specification of this protocol, and do not implement the password encryption extension, should simply ignore any arguments supplied with this event message. USER This event message is sent to opers to indicate that a new user, with the name "username", has just logged in. OPER This event message is sent to opers to indicate that a new oper, with the name "username", has just logged in. SYS_LOGOUT This event message is sent to opers to indicate that the user or oper with the name "username" has just logged out. FLAG This event message is sent to opers to indicate that a user, with the name "username", is typing messages without any opers currently attending to him / her. UNFLAG This event message is sent to opers to indicate that a previously flagged user, with the name "username", is no longer in a flagged state. This effectively revokes the previous FLAG event message sent for the user. BAN_IP This event message is sent to opers to indicate that a user, with the name "username" and ip address "ip address", has had a ban set on them. UNBAN_IP This event message is sent to opers to indicate that a previous ban, against the ip address "ip address", has been lifted. MESSAGE This event message is sent to a user to deliver a message that has just been written to them. The argument specifies the message to be delivered. The message begins immediately after the "MESSAGE" event message and it's compulsory following space to deliminate it from the argument, and runs until the terminating linefeed character, not including this character. The message itself may contain space characters, but may not contain any linefeed characters (as these will be interpreted as the terminating character). ROOM This event message is sent to an oper to deliver a message that has just been written to a user that the oper has set a "watch" on (see the WATCH command in section 3.1 for more information). The first argument specifies the name of the user the message was written to. The second specifies the message to be delivered. The message begins immediately after the first argument and it's compulsory following space to deliminate it from the second argument, and runs until the terminating linefeed character, not including this character. The message itself may contain space characters, but may not contain any linefeed characters (as these will be interpreted as the terminating character). BANNED This event message is sent to a user or an oper to notify them that they have been banned from the system. This should be the last transmission sent, upon setting of a ban, before the connection to the user is dropped. KICKED This event message is sent to a user or an oper to notify them that they have been kicked from the system. This should be the last transmission sent before the connection to the user is dropped. ----------------------------------------------------------------------- 4. EXTENSIONS 4.1. PASSWORD ENCRYPTION Although not part of the core specification, a particular server implementation may offer support for transmitting passwords as MD5 hashes instead of clear text. This is an optional extension. Servers implementing it must still allow clear text password authentication as well, to accommodate clients that do not support the password encryption extension. This extension is supported in the official SupportDesk software (both server and client) as of version 0.2. Naturally it is useless for the client to simply hash it's password by itself and transmit it, or this hash then becomes the password itself. An attacker who intercepted the hash could simply transmit the same hash again to gain access. Therefore the server must provide a piece of unique data each session that the client can combine with it's password before hashing. This piece of data is called the auth_key. The server randomly generates a new auth_key, 32 characters long, for each new session. When it transmits it's "READY" event message to initiate communication, as per the core specification (see section 3.3 for more information), it transmits the auth_key as an argument to this event message: READY auth_key For example: READY Ri6%@O|0`xY0([TD)'GTt;bMlUC2>'LP Clients that do not implement this extension should simply ignore the auth_key. The auth_key must be exactly 32 characters long and may not contain any linefeed characters (as these will be interpreted as the terminating character). A client implementing this extension should then take the auth_key and join it to the end of the any password they wish to use by way of simple string concatenation. For example, using the auth_key from the example above and the password "secret" would result in the string: secretRi6%@O|0`xY0([TD)'GTt;bMlUC2>'LP This new string should then be hashed using the well known MD5 hashing algorithm. An important property of MD5 is that it is a one way hashing algorithm. You can easily generate a uniform length hash, 32 characters long, from any input data. However it is virtually impossible to recover the original input data from only the hash. This holds true even if you already have part of the original input data (ie. the auth_key). Continuing our example, this gives us the hash: aa7cc0d774532597dc0126cc576adeaa This hash is then transmitted to the server in place of the password. For example: LOGIN gareth aa7cc0d774532597dc0126cc576adeaa The server can easily calculate if this is correct by taking the password stored on disk (for the user "gareth" in this case, the password "secret"), combining it with the auth_key it generated earlier, calculating the MD5 hash, and checking if the hash matches the hash supplied by the client. Two examples follow. In the first the client opts to authenticate using a clear text password, and in the second the client opts to authenticate using an MD5 hash. The client knows it has the option of authenticating by MD5 hash because the server supplied an auth_key along with the "READY" event message, indicating that it supports this extension. Example 1: READY aQHTx2_3.XdK hello? server: MESSAGE hi there server: MESSAGE how can I help? client: SEND hi. I'm just testing the system. server: MESSAGE hi. I'm just testing the system. server: MESSAGE oh, ok. no worries. client: SEND I'll logout now server: MESSAGE I'll logout now server: MESSAGE bye client: SEND bye server: MESSAGE bye client: LOGOUT A transcript from a typical oper session follows. The oper is called "gareth" and talks to a user called "sally". Lines sent from the server are annotated with the prefix "server: " and lines sent by gareth's client are annotated with the prefix "client: ". These annotations are provided only for the reader of this document and are not transmitted during actual communication. server: READY client: LOGIN gareth password server: HELLO_OPER gareth client: LIST_USERS server: USER sally server: END_OF_USER_LIST client: LIST_FLAGS server: FLAG sally server: END_OF_FLAG_LIST client: WATCH sally server: OK server: ROOM sally hello? server: UNFLAG sally client: SEND sally hi there server: ROOM sally hi there client: SEND sally how can I help? server: ROOM sally how can I help? server: ROOM sally hi. I'm just testing the system. client: SEND sally oh, ok. no worries. server: ROOM sally oh, ok. no worries. server: ROOM sally I'll logout now client: SEND sally bye server: ROOM sally bye server: ROOM sally bye server: SYS_LOGOUT sally client: LOGOUT -----------------------------------------------------------------------