$Id: PROTOCOL,v 1.1 2005/02/23 16:10:14 bobas Exp $ Vypress Chat protocol description revision 1.0, 2005-01-23 --------------------------------- I've recieved requests for VypressChat protocol specs, so here it is. This is based on information I got from Vasily Krysin (echat) and Konstantin Vyatkin (Vypress Research). Please note that information concerning 1.9.x is incomplete; Vypress Research stopped answering my emails, It look like they don't want to support vyqchat anymore. If you know anything more than below, please contact me, so I could make this manual as complete as possible. Especially RSA usage and bulletin-board support deatils are welcome! I. Vypress Chat 1.5.x protocol ------------------------------ Warning! Information provided below may contain subtle errors (like sender exchanged with reciever). If in doubt, please compare it with vcprotocol.cpp from VyQChat (see VCProtocol::vc_* functions). These mistakes will be corrected in future revisions of this document. Each Vypress Chat packet begins with 'X' and 9 random characters from '0'..'9' range (unique packet ID). Then comes packet type id (single character). For example: X1234567892#Main\0Nick\0text of string\0 ^^ ^^ ^ ^ ^ ^ ^----- 0x00 == string splitter || || | | | |------------------- plain text to display on chat || || | | |--------------------- 0x00 == string splitter || || | |------------------------- nick || || |--------------------------- 0x00 == string splitter || ||-------------------------------- channel || |--------------------------------- 0x32 == type of packet - chat ||------------------------------------------ packet id |------------------------------------------- 0x58 == Vypress Chat ============================================================================== Available packets: ********************************************************************************************** *** Packet from list updater (Who here) '0' + <Name of updater> + #0 ^^^ - its a single byte 0x00, showing end of a line ********************************************************************************************** *** Answer to the previous packet ("Im here") '1' + <Name of updater> + #0 + <Name of responder> + #0 + Status + RemoteActive ^^^^^ status of responder (byte) '0' - Normal '1' - DND '2' - Away '3' - Offline ^^^^^ window state (byte) '0' - active '1' - not active ********************************************************************************************** *** Simple chat string on the channel '2' + <Name of channel> + #0 + <Name of author> + #0 + <Text> + #0 ********************************************************************************************** *** Nick change '3' + <From who> + #0 + <To who> + #0 + Gender ^^^^ - gender of the user '0' - male '1' - female ********************************************************************************************** *** Join to channel '4' + <Who joined> + #0 + <Name of channel> + #0 + Status + Gender ********************************************************************************************** *** Leave from channel '5' + <Who leaved> + #0 + <Name of channel> + #0 + Gender ********************************************************************************************** *** Message '6' + <From who> + #0 + <To who> + #0 + <Text> + #0 ********************************************************************************************** *** Multiaddress message 'E' + <From who> + #0 + <To who> + #0 + <Text> + #0 ********************************************************************************************** *** Message ack '7' + Status + <Who received> + #0 + <To who ack> + #0 + Gender + CurrentAA + #0 ^^^^^^^^^ current autoanswer (may be empty, for ex in Normal mode) ********************************************************************************************** *** Remote execution '8' + <Who execute> + #0 + <To who> + #0 + <Command line> + #0 + <Password> + #0 ^^^^^^^^ may be empty ********************************************************************************************** *** Execution ack '9' + <To who> + #0 + <From who> + #0 + <Execution text> + #0 ********************************************************************************************** *** /ME on the channels 'A' + <Name of channel> + #0 + <Who said> + #0 + <Text> + #0 ********************************************************************************************** *** New topic 'B' + <Name of channel> + #0 + <Text of topic> + ' (' + <Name of author> + ') ' + #0 ********************************************************************************************** *** Current topic (sending to each who join channel) 'C' + <To who> + #0 + <Name of channel> + #0 + <Text of topic> + #0 ********************************************************************************************** *** Change of status 'D' + <Who changed> + #0 + Status + Gender + CurrentAA + #0 ********************************************************************************************** *** INFO request 'F' + <To who> + #0 + <From who> + #0 ********************************************************************************************** *** INFO request ack 'G' + <To who> + #0 + <From who> + #0 + <Computer name> + #0 + <User name> + #0 + <IP addresses> + #0 + <List of channels - one string without splitting> + '#' + #0 + CurrentAA + #0 ********************************************************************************************** *** BEEP signal 'H' + '0' + <To who> + #0 + <From who> + #0 ack 'H' + '1' + <To who> + #0 + <From who> + #0 + Gender ********************************************************************************************** *** Sound request 'I' + <From who> + #0 + <File name> + #0 + <Name of channel> + #0 ********************************************************************************************** *** Private join to chat 'J' + '0' + <From who> + #0 + <To who> + #0 + Gender leave chat 'J' + '1' + <From who> + #0 + <To who> + #0 + Gender Simple string 'J' + '2' + <From who> + #0 + <To who> + #0 + <Text> + #0 "/me" string 'J' + '3' + <From who> + #0 + <To who> + #0 + <Text> + #0 ********************************************************************************************** *** /HERE request 'L' + <From who> + #0 + <Name of channel> + #0 ********************************************************************************************** *** /HERE ack 'K' + <To who> + #0 + <Name of channel> + #0 + <From who> + #0 + RemoteActive ********************************************************************************************** *** Activity change 'M' + <From who> + #0 + RemoteActive ********************************************************************************************** *** Request for channel list 'N' + <From who> + #0 ********************************************************************************************** *** Request for channel list ack 'O' + <To who> + #0 + <List of channels - one string without splitting> + '#' + #0 ********************************************************************************************** *** Ping (not implemented - SeaD) ping 'P' + '0' + <To who> + #0 + <From who> + #0 + <Time hh:mm:ss - 8 symbols> + #0 pong 'P' + '1' + <To who> + #0 + <From who> + #0 + <Received time sending back hh:mm:ss - 8 symbols> + #0) ********************************************************************************************** II. Vypress Chat 1.9.x protocol changes --------------------------------------- Vypress Chat 1.9.x uses version advertising, so that newer VC versions know what functions are supported by remote side of conversation and can preserve compatibility with older software. Second important change is unique user ID based on the UUID. As far as I know UUIDs are supported in Windows only for now. UUID is a 128-bit number that should be globally unique and persistent (should not change after reset). Vypress Chat 1.9 uses UUID when handling a nickname conflict; Vypress Chat 1.9.1 also uses it during file transfer. UUID is widely used at 1.9.5 and 2.0 to store RSA public key in association with user. (see http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCGuidGen.asp for info on how to create uuids). In vyqchat UUIDs are created using OpenSSL random numbers generator, and than saved in config file so it doesn't change (until you delete this file); UUID is however not really used yet for any purpose, except including in packets. //************************************************************************** //*** Join to the #Main (MAIN_CHANNEL_NAME) // // '4' + <Who's joined> + #0 + <Channel name> + #0 + Status + Gender // // Ver 1.9: // '4' + <Nickname> + #0 + "#Main" + #0 + (char)Status + (char)Gender + #0 + (dword)VERSION + UUID + (char)cCodePage + (DWORD)dwColor + #0 PACKERSION(1,9) indicates the protocol version. Version 1,92 means that your client is able to receive files via TCP. Version 1,93 means you are able to respond to the TCP pings. Version 1,9 should be used unless you implement these featues. Version should be encoded using 4 bytes, so for example, version 1.91 looks like this: 5B,00,01,00 cCodePage should be '1' for UTF8 encoding, '0' otherwise. It is suggested to always set it to '1' (to indicate that you are using UTF-8 encodings for all strings) to avoid charset incompatibility. When you are joining the network with such flag, Vypress Chat 1.9 or later will send you all text string as UTF-8 encoded (including nicknames and channel names in all packets). dwColor is a RGB encoded color value that chat may use to display your strings at common chat. This is optional feature in Vypress Chat that allows using custom color and if a user has this feature switched on then Chat will use this value to display your text. You may use RGB(0,0,0) (black). Vypress Chat 1.9 relies on the PING-PONG for maintaining users list, so you should respond to the following packets: //************************************************************************** //*** PING // // PING // 'P' + '0' + <ToWhom> + #0 + <FromNickname> + #0 + <Time in the format hh:mm:ss, 8 charactes> + #0 Response: //************************************************************************** //*** PONG // // PONG // 'P' + '1' + <ToWhom> + #0 + <MyNicknmane> + #0 + <received time should be sent back> + #0) //************************************************************************** //*** I'm here! // // '1' + <NickFrom> + #0 + <YourNick> + #0 + Status + RemoteActive // ^^^^^ // your current status // '0' - Normal // '1' - DND // '2' - Away // '3' - Offline // ^^^^^ // windows state // '0' - active // '1' - inactive // // Ver 1.9: // '1' + <NickFrom> + #0 + <YourNick> + #0 + (char)Status + RemoteActive + #0 + (DWORD)PACKVERSION(1.9) + (char)Gender + UUID + #0 + (DWORD)0 (reserved) + (char)cCodePage + (DWORD)dwColor#0 // // CodePage: 0 - Current ANSI, 1 - UTF-8 //************************************************************************** //*** Who is here? // // '0' + <FromNickname> + #0 + (char)cCodePage + #0 // //************************************************************************** //*** Join a channel #Channel // // '4' + <NicknameFrom> + #0 + <ChannelName> + #0 + Status + Gender // // Ver 1.9: // '4' + <NicknameFrom> + #0 + < ChannelName > + #0 + (char)Status + (char)Gender + #0 + (char)cCodePage + #0 //************************************************************************** //*** Message delivery confirmation / AutoAnswer // // '7' + Status + <ToNickname> + #0 + <FromNickname> + #0 + Gender // + CurrentAA + #0 // ^^^^^^^^ // current auto answer (may be empty) // Ver 1.9 // // '7' + Status + <ToNickname> + #0 + <FromNickname> + #0 + Gender + CurrentAA + #0 + PacketSignature + #0 // PacketSignature - first random bytes from the packet header with message //************************************************************************** //*** INFO request reply // // 'G' + <ToNickname> + #0 + <FromNickname> + #0 + <Computer name> + #0 + <Current user name> + #0 + <IP addresses> + #0 + <Channels list, without separators in one line> + '#' + #0 + CurrentAA + #0 + <Platform (OS) version> +#0 + <Chat software> + #0 //************************************************************************** //*** Flood blocking notification (your packets was blocked by other user // for flood) // // 'Z' + <ToNickname> + #0 + <FromNickname> + #0 + <seconds count> + #0