Mud Master Chat Establishing a Connection Caller: Once a connection is made the caller sends a connection string; which looks like: "CHAT:\n". 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:\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:\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: . 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 byte. Below is a list of the 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 The byte is 255: #define 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: "" – "%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 "" – "%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. "" – "%c%s%c". The ip/port string looks like ",,,,…>". If a connection is missing an IP address the address in the string should say "". A sample string might looks something like this: "28.25.102.48,4050,100.284.27.65,4000,,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: 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 " 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 " 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: 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: 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: 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 %s is not allowing commands.\n" Receiver: Just print the message string. CHAT_VERSION Sender: CHAT_FILE_START Sender: 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: This is used when a CHAT_FILE_START has been received and you want to prevent the transfer from continuing. 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: Sent to request the next block of data in a transfer. Receiver: Need to create a file block to be sent back. File blocks are fixed length so they don't need the CHAT_END_OF_COMMAND byte. 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: 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: Receiver: Close up your files and be done with it. CHAT_FILE_CANCEL Sender: Either side can send this command to abort a file transfer in progress. CHAT_PING_REQUEST Sender: 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: The timing data is just the data that was sent to you with the CHAT_PING_REQUEST.