Mud Master Chat Specs


Establishing a Connection

Caller:

Once a connection is made the caller sends a connection string; which looks like:


 "CHAT:<chat name>\n<ip address><port>".
The sprintf syntax is:

"CHAT:%s\n%s%-5u"  
The port must be 5 characters, padded on the right side with spaces. Once this string has been sent it waits for a response from the other side. If a "NO" is received the call is cancelled. If the call was accepted the string

"YES:<chat name>\n" 
is received. Next the MM version number is sent out. The version number sending is not required and can happen independently of the connection. It's just a convenient place to do it.

Receiver:

When a socket call is detected it accepts the socket then waits for the "CHAT:" string to be send from the caller. If the receiver wishes to deny the call, the string "NO" needs to be sent back to the caller. To accept the call, the string


"YES:<chat name>\n" 
is sent back. That's all the receiver has to do. Next the MM version number is sent out. This is not required.


Chat Data Blocks

A chat data block looks like this:


 <block ID byte><data><end of data byte>
All data dealing with needs to follow this format with a couple exceptions. The connection process doesn't use the data blocks and the file transfer blocks are a fixed size and don't need the <end of data> byte.

Below is a list of the <block ID> values:


#define CHAT_NAME_CHANGE	1
#define CHAT_REQUEST_CONNECTIONS	2
#define CHAT_CONNECTION_LIST	3
#define CHAT_TEXT_EVERYBODY	4
#define CHAT_TEXT_PERSONAL	5
#define CHAT_TEXT_GROUP	6
#define CHAT_MESSAGE	7
#define CHAT_DO_NOT_DISTURB	8
#define CHAT_SEND_ACTION	9
#define CHAT_SEND_ALIAS	10
#define CHAT_SEND_MACRO	11
#define CHAT_SEND_VARIABLE	12
#define CHAT_SEND_EVENT	13
#define CHAT_SEND_GAG	14
#define CHAT_SEND_HIGHLIGHT	15
#define CHAT_SEND_LIST	16
#define CHAT_SEND_ARRAY	17
#define CHAT_SEND_BARITEM	18
#define CHAT_VERSION	19
#define CHAT_FILE_START	20
#define CHAT_FILE_DENY	21
#define CHAT_FILE_BLOCK_REQUEST	22
#define CHAT_FILE_BLOCK	23
#define CHAT_FILE_END	24
#define CHAT_FILE_CANCEL	25
#define CHAT_PING_REQUEST	26
#define CHAT_PING_RESPONSE	27
#define CHAT_PEEK_CONNECTIONS	28
#define CHAT_PEEK_LIST	29
#define CHAT_SNOOP	30
#define CHAT_SNOOP_DATA	31

The <end of data> byte is 255:


#define CHAT_END_OF_COMMAND	255

Block ID values table

CHAT_NAME_CHANGE 1
CHAT_REQUEST_CONNECTIONS 2
CHAT_CONNECTION_LIST 3
CHAT_TEXT_EVERYBODY 4
CHAT_TEXT_PERSONAL 5
CHAT_TEXT_GROUP 6
CHAT_MESSAGE 7
CHAT_DO_NOT_DISTURB 8
CHAT_SEND_ACTION 9
CHAT_SEND_ALIAS 10
CHAT_SEND_MACRO 11
CHAT_SEND_VARIABLE 12
CHAT_SEND_EVENT 13
CHAT_SEND_GAG 14
CHAT_SEND_HIGHLIGHT 15
CHAT_SEND_LIST 16
CHAT_SEND_ARRAY 17
CHAT_SEND_BARITEM 18
CHAT_VERSION 19
CHAT_FILE_START 20
CHAT_FILE_DENY 21
CHAT_FILE_BLOCK_REQUEST 22
CHAT_FILE_BLOCK 23
CHAT_FILE_END 24
CHAT_FILE_CANCEL 25
CHAT_PING_REQUEST 26
CHAT_PING_RESPONSE 27
CHAT_PEEK_CONNECTIONS 28
CHAT_PEEK_LIST 29
CHAT_SNOOP 30
CHAT_SNOOP_DATA 31
CHAT_END_OF_COMMAND 255

CHAT_NAME_CHANGE

When a user changes their chat name the new name needs to be broadcast to all of their connections. The data block looks like:


"<CHAT_NAME_CHANGE><new name><CHAT_END_OF_COMMAND>" - "%c%s%c"


CHAT_REQUEST_CONNECTIONS

Sender:

Requesting connections from another connection asks to see all the people that person has marked as public, then try to connect to all of those yourself. The request for connections is just:


 "<CHAT_REQUEST_CONNECTIONS><CHAT_END_OF_COMMAND>" - "%c%c"

Receiver:

Need to put all the IPs and port numbers of your public connections in a comma delimited string and send them back as a connection list.


"<CHAT_CONNECTION_LIST><ip addresses and ports><CHAT_END_OF_COMMAND>" - "%c%s%c"
The ip/port string looks like

"<ip address>,<port>,<ip address>,<port>, ...>"
If a connection is missing an IP address the address in the string should say:

 "<Unknown>"  
A sample string might looks something like this:

"28.25.102.48,4050,100.284.27.65,4000,<Unknown>,4050"


CHAT_CONNECTION_LIST

This is a result from a connection request. The IP addresses and port numbers need to be parsed out of the string and an attempt made to connect them. See CHAT_REQUEST_CONNECTIONS for the format of the string.


CHAT_TEXT_EVERYBODY

Sender:



<CHAT_TEXT_EVERYBODY><text to send><CHAT_END_OF_COMMAND>

Used to send some chat text to everybody. All the text you want to be displayed needs to be generated on the sender's side, including the line feeds and the "<chat name> chats to everybody" string. "\n%s chats to everybody, '%s'\n" The reason for sending all the text rather than having the receiving side generate the "<chatname> chats to everybody" is just to be polite and lift some of the burden from the receiver's side. The receiver can just print the string that comes in and isn't having to constantly build all the chat strings. The data should only be sent to chat connections are you not ignoring.

Receiver:

If the chat connection isn't being ignored, you simply print the string. If you have any connections marked as being served you need to echo this string to those connections. Or if this is coming from a connection being served, you need to echo to all your other connections. This allows people who cannot connect directly to each other to connect with a 3rd person who can connect to both and be a server for them.


CHAT_TEXT_PERSONAL

Sender:



<CHAT_TEXT_PERSONAL><text to send><CHAT_END_OF_COMMAND>

This works the same way as CHAT_TEXT_EVERYBODY as far as what you need to send. The text should obviously be changed so the person receiving knows this was a personal chat and not broadcast to everybody.


  "\n%s chats to you, '%s'\n"

Receiver:

Just print the string that comes in if you aren't ignoring this connection.


CHAT_TEXT_GROUP

Sender:



<CHAT_TEXT_GROUP><group><text to send><CHAT_END_OF_COMMAND>

Used when you send text to a specific group of connections. Works basically the same as the other text commands. The group name is a 15 character string. If must be 15 characters long - pad it on the right with spaces to fill it out.


 "\n%s chats to the group, '%s'\n"

Receiver:

Just print the string that comes in if you aren't ignoring this connection.


CHAT_MESSAGE

Sender:



<CHAT_MESSAGE><message><CHAT_END_OF_COMMAND>

This is used to send a message to another chat connection. An example of this is when you try to send a command (action, alias, etc. ...) to another chat connection and they don't have you flagged as accepting commands. In that case a chat message is sent back to the sender telling them that command are not being accepted. To let the other side know the message is generated from the chat program it is a good idea to make the string resemble something like:


 "\n<CHAT> %s is not allowing commands.\n"

Receiver:

Just print the message string.


CHAT_VERSION

Sender:



<CHAT_VERSION><version string><CHAT_END_OF_COMMAND>


CHAT_FILE_START

Sender:



<CHAT_FILE_START><filename,length><CHAT_END_OF_COMMAND>

This is sent to start sending a chat connection a file. The filename should be just the filename and not a path. Length is the size of the file in bytes.

Receiver:

First should check to make sure you are allowing files from this connection. Make sure the filename is valid and that the length was trasnmitted. MM by default won't allow you to overwrite files; which keeps people from messing with file already in your directory. If for any reason the data isn't valid or you don't want to accept files from this person a CHAT_FILE_DENY should be sent back to abort the transfer. If you want to continue with the transfer you need to start it off by requesting a block of data with CHAT_FILE_BLOCK_REQUEST.


CHAT_FILE_DENY

Sender:



<CHAT_FILE_DENY><message><CHAT_END_OF_COMMAND>

This is used when a CHAT_FILE_START has been received and you want to prevent the transfer from continuing. <message> is a string telling the reason it was denied. For example, if the file already existed you might deny it with:


"File already exists."

Receiver:

Print the deny message. Deal with cleaning up any files you opened when you tried to start the transfer.


CHAT_FILE_BLOCK_REQUEST

Sender:



 <CHAT_FILE_BLOCK_REQUEST><CHAT_END_OF_COMMAND>

Sent to request the next block of data in a transfer.

Receiver:

Need to create a file block to be sent back. If the end of file is reached need to send a CHAT_FILE_END close up the files and let the user know it is done sending.


CHAT_FILE_BLOCK

Sender:



<CHAT_FILE_BLOCK><block of data>

A file block is 500 bytes. A file block is ALWAYS 500 bytes so no CHAT_END_OF_COMMAND is needed.

Receiver:

The receiver needs to keep track of the number of bytes written to properly write the last block of data. If you keep track of the bytes written you know when to expect that last block that probably doesn't have a full 500 bytes to be saved. File transfers are receiver driven, so for each block of data you accept, you need to send another CHAT_FILE_BLOCK_REQUEST back out to get more data.


CHAT_FILE_END

Sender:



<CHAT_FILE_END><CHAT_END_OF_COMMAND>

Receiver:

Close up your files and be done with it.


CHAT_FILE_CANCEL

Sender:



<CHAT_FILE_CANCEL><CHAT_END_OF_COMMAND>

Either side can send this command to abort a file transfer in progress.


CHAT_PING_REQUEST

Sender:



<CHAT_PING_REQUEST><timing data><CHAT_END_OF_COMMAND>

The timing data is really up to the ping requester. MM uses the number of clocks ticks elapsed to determine the length of a ping. Your timing data is sent right back to you from the side receiving the ping so you can use anything you want to indicate the length of a ping. The reason for sending the ping data was to keep the code simple. If rather than sending the data you keep track of it in your program, you'd have to build some sort of object that keeps track of all the pings you have sent and their start times. This way you don't have to keep track of the start time, it's given right back to you when the ping is returned.

Receiver:

When a request is received send the timing data right back in a CHAT_PING_RESPONSE block.


CHAT_PING_RESPONSE

Sender:



<CHAT_PING_RESPONSE><timing data><CHAT_END_OF_COMMAND>

The timing data is just the data that was sent to you with the CHAT_PING_REQUEST.


CHAT_PEEK_CONNECTIONS

Sender:



<CHAT_PEEK_CONNECTIONS><CHAT_END_OF_COMMAND>

This is sent to request all the public connections the other person has. Unlike the Request Connections command, this one just returns a list to be viewed. It doesn't connect you to them all.

Receiver:

Sends back:


<CHAT_PEEK_LIST><address list><CHAT_END_OF_COMMAND>  
It's been too long since I wrote this to remember why I changed it, but this uses a slightly different format than the Request Connection list. The address should look like:

 "<address>~<port>~<name>"  
Like the Request Connections, and unknown address should be returned as "<Unknown>" for consistency. Same address list would look something like:

"204.285.28.18~4050~Omawarisan~<Unknown>~4050~Baalzebul"


CHAT_PEEK_LIST

This is the result returned from CHAT_PEEK_CONNECTIONS. The format for the data is above.


CHAT_SNOOP

Sender:



<CHAT_SNOOP><CHAT_END_OF_COMMAND>

This sends a request to the other client to start/stop snooping.

Receiver:

The receiver needs to be in charge of allowing the snooping. You probably don't want anybody able to snoop you at will. When being snooped, all data seen on the screen should be send to the person snooping. This gives the person requesting the snoop a view through the eyes of the person being snooped. Data is sent with the CHAT_SNOOP_DATA command.


CHAT_SNOOP_DATA

Sender:



<CHAT_SNOOP_DATA><text><CHAT_END_OF_COMMAND>

The text to send should just be the same text being seen on the person who is being snooped's side. The current text color should probably be embedded at the start of the line to ensure that the snooped text comes out the right color initially on the receiving side.

Receiver:

MM indicates the snooped text by prefacing ">>" at the start of each line printed from the remote side (bright green). This allows the user to tell which lines are coming from the snooped connection, and which are normal text from their connection. This is really up to you how you want it to appear for the user.


(End of MudMaster Chat Spec)