现在的位置: 首页 > 综合 > 正文

qq2005beta1/2/3 cs 协议 release 1

2013年03月18日 ⁄ 综合 ⁄ 共 17366字 ⁄ 字号 评论关闭

qq2005beta1/2/3 c<-->s 协议
sunwang<sunwangme@hotmail.com>
release 1
2005-09-19

说明
======
所有的short long都是网络字节顺序

参考
======
libeva-0.3.2-1
miranda-qq-0.1.0.9

0. 怎么发包
======
 0.0 Packet::setPasswordKey ::setSessionKey
 0.1 XXXPacket::OutPacket
 0.2 XXXPacket重载putBody
 0.3 new XXXPacktet(cmd,needAck)
 0.4 XXXPacket->fill(buffer,&len)    //这里完成所有的header body的填充解密工作
 0.5 Net->send(buffer,len)
 
1. 怎么收包
======
 1.0 Net->recv(buffer,len)      //如果是tcp,根据buffer的头两个字节进行完整性分析务必取到一个完整的包
 1.1 new InPacket(buffer,len)
 1.2 new XXXPacket
 1.3 XXXPacket->setInPacket(InPacket)
 1.4 XXXPacket->parse()       //这里调用parseBody
 1.5 XXXPacket重载parseBody
 
2. 命令格式
======

tcpPacketLen:2           //UDP没有此字段;tcp时候,指整个包的长度,用于包的完整性分析;udp不需要此字段,每次都会收到一个完整的包
packetStartTag:1 = 0x02
version:2
command:2
sequence:2           //由包的发起方填充,可以是任意值,应答方必须保证sequence不变
id:4
body[]             //QQ_CMD_REQUEST_LOGIN_TOKEN,QQ_CMD_LOGIN不加密或者用特殊方式加密外,其他包的body都用TEA+sessionKey加密
packetEndTag:1 = 0x03

fields comment:
version: 
 const short QQ_CLIENT_062E = 0x062E;   /**  client GB QQ2000c build 630 */
 const short QQ_CLIENT_072E = 0x072E;   /** client En QQ2000c build 305 */
 const short QQ_CLIENT_0801 = 0x0801;   /** client En QQ2000c build 630 */
 const short QQ_CLIENT_0A1D = 0x0A1D;   /** client Gb QQ2003c build 0808 */
 const short QQ_CLIENT_0B07 = 0x0B07;   /** client Gb QQ2003c build 0925 */
 const short QQ_CLIENT_0B2F = 0x0B2f;   /** client GB QQ2003iii build 0117 */
 const short QQ_CLIENT_0B35 = 0x0B35;   /** GB QQ2003iii build 0304 (offical release) */
 const short QQ_CLIENT_0B37 = 0x0B37;   /** QQ20003  */
 const short QQ_CLIENT_0C0B = 0x0C0B;   /** QQ2004 */
 const short QQ_CLIENT_0C0D = 0x0C0D;   /** QQ2004 preview*/
 const short QQ_CLIENT_0C21 = 0x0C21;   /** QQ2004 */
 const short QQ_CLIENT_0C49 = 0x0C49;   /** QQ2004II */
 const short QQ_CLIENT_0D05 = 0x0D05;   /** QQ2005 beta1 */
 const short QQ_CLIENT_0D51 = 0x0D51;   /** QQ2005 beta2 */

3. 命令集合
======

31 commands now,divided to 9 sets

session cmd set:6
======
const short QQ_CMD_REQUEST_LOGIN_TOKEN     = 0x0062;
const short QQ_CMD_LOGIN        = 0x0022;
const short QQ_CMD_KEEP_ALIVE       = 0x0002;
const short QQ_CMD_LOGOUT        = 0x0001;
const short QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS  = 0x0081;
const short QQ_CMD_CHANGE_STATUS      = 0x000D;

account cmd set:8
======
const short QQ_CMD_MODIFY_INFO       = 0x0004;
const short QQ_CMD_SEARCH_USER       = 0x0005;
const short QQ_CMD_GET_USER_INFO      = 0x0006;
const short QQ_CMD_GET_LEVEL       = 0x005C;
const short QQ_CMD_REQUEST_KEY       = 0x001D; //c <-->c 之间的一些key,如file transfer
const short QQ_CMD_FRIEND_REMARK_OP     = 0x003E; 
const short QQ_CMD_REQUEST_EXTRA_INFORMATION   = 0x0065; //QQ_CMD_GET_USER_INFO不能得到完整信息,扩展信息用这个取
const short QQ_CMD_SIGNATURE_OP      = 0x0067; //个人的签名,一般只取在线好友的签名

friend cmd set:6
======
const short QQ_CMD_GET_FRIEND_LIST      = 0x0026;
const short QQ_CMD_GET_FRIEND_ONLINE     = 0x0027;
const short QQ_CMD_ADD_FRIEND       = 0x0009;
const short QQ_CMD_DELETE_FRIEND      = 0x000A;
const short QQ_CMD_ADD_FRIEND_AUTH      = 0x000B;
const short QQ_CMD_DELETE_ME       = 0x001C; //如果我将对方拖到黑名单,协议规定要发这个命令给服务器以要求对方从联系人中删除我

group cmd set:3
======
const short QQ_CMD_GROUP_NAME_OP = 0x003C;
const short QQ_CMD_UPLOAD_GROUP_FRIEND = 0x003D;
const short QQ_CMD_DOWNLOAD_GROUP_FRIEND = 0x0058;

chat cmd set:2
======
const short QQ_CMD_SEND_IM = 0x0016;
const short QQ_CMD_RECV_IM = 0x0017;

qun cmd set:1
======
const short QQ_CMD_QUN_CMD = 0x0030;

phone cmd set:2
======
const short QQ_CMD_CELL_PHONE_1 = 0x0021;
const short QQ_CMD_CELL_PHONE_2 = 0x0029;

system cmd set:2
======
const short QQ_CMD_ACK_SYS_MSG = 0x0012;
const short QQ_CMD_RECV_MSG_SYS = 0x0080;

debug cmd set:1
======
const short QQ_CMD_TEST = 0x0031;

4. 命令解析
======

下面只讨论body,各个字段都是加密前或者解密后的内容.
后面跟了[x]的命令,暂时不解析

4.1 QQ_CMD_REQUEST_LOGIN_TOKEN
======

c -> s : 需要ack,body不加密
null:1 = 0x00

c <- s : body不加密
replyCode:1
tokenLength:1          //现在得到的都是8字节的token
token:tokenLength

fields comment:
replyCode:
 const unsigned char QQ_REQUEST_LOGIN_TOKEN_REPLY_OK = 0x00;

4.2 QQ_CMD_LOGIN
======

c -> s : 需要ack,特殊加密方式
iniKey:16 = {
   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
   }
encryptedStream:length         //是一个416字节的流用iniKey使用TEA算法加密后得到的长度为length字节的流
///////////////416字节的流说明如下//////////////
nullEncryptedStream:16        //用passwordKey(=password'md5'md5)作为128位密码使用TEA算法加密空串得到128位流
unknown:36 = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x4c, 0x28, 0xeb, 0xaa, 0xe9,
   0x7f, 0x2a, 0x7c, 0xf9, 0xa9, 0x0f, 0x84, 0xdd,
   0xbb, 0xb2, 0x0f, 0x01
   }
loginMode:1
unknown:16 = {
   0x43, 0xc3, 0x80, 0x19, 0x46, 0x05, 0x3e, 0x4b,
   0x91, 0x60, 0x5b, 0xf8, 0x17, 0xd7, 0xf3, 0x5b
   }
tokenLength:1
token:tokenLength
unknown:100 = {
   0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00
   }
zeroRest:416-$ = {0}        //剩下的用零填充
///////////////////////////////////////////////

c <- s :            //不是用passwordKey就是用iniKey使用TEA加密
replyCode:1
IF replyCode=QQ_LOGIN_REPLY_OK
 sessionKey:16
 qqNumber:4
 userIP:4
 userPort:2
 serverIP:4
 serverPort:2
 loginTime:4
 unknown:2
 fileShareToken:24         //file share token used in Qun disk share file access
 unknown:16
 clientKey:32          //client key for QQ Home
 unknown:12
 lastLoginIP:4
 lastLoginTime:4
 unknown:8
IF replyCode=QQ_LOGIN_REPLY_REDIRECT
 qqNumber:4
 redirectedServerIP:4
 redirectedServerPort:2
IF replyCode=QQ_LOGIN_REPLY_PWD_ERROR
 messageError:bodyLength-1       //the messege is encoded by "GB18030"
IF replyCode=QQ_LOGIN_REPLY_MISC_ERROR
 unknown: bodyLength-1
 
fileds comment:
replyCode:
 const unsigned char QQ_LOGIN_REPLY_OK = 0x00;
 const unsigned char QQ_LOGIN_REPLY_REDIRECT = 0x01;
 const unsigned char QQ_LOGIN_REPLY_PWD_ERROR = 0x05;
 const unsigned char QQ_LOGIN_REPLY_MISC_ERROR = 0x06;
loginMode:
 const unsigned char QQ_LOGIN_MODE_NORMAL = 0x0A;
 const unsigned char QQ_LOGIN_MODE_INVISIBLE = 0x28;

4.3 QQ_CMD_LOGOUT
======

c -> s : 不需要ack
passwordKey:16           //password'md5'md5

4.4 QQ_CMD_KEEP_ALIVE
======

每分钟c向s发送一次,可以保证NAT的bind的持久性,并助于无状态服务器跟踪用户的状态

c -> s : 需要ack
id:4

c <- s :
是5个用0x1f结尾的不定长的string
xxxx/0x1f            //unknown
xxxx/0x1f            //unknown
xxxx/0x1f            //onlineUsersNumber
xxxx/0x1f            //userIP
xxxx/0x1f            //userPort

4.5 QQ_CMD_GET_FRIEND_LIST
======

c -> s : 需要ack
position:2
sorted:1
unknown:1 = 0x00
unknown:1 = 0x01

c <- s :
position:2
friendItem[]:bodyLength-2

fields comment:
position:
 const short QQ_FRIEND_LIST_POSITION_START = 0x0000;
 const short QQ_FRIEND_LIST_POSITION_END = 0xFFFF;
 由于是无状态服务器,每次设定列表的position,从0开始,如果返回了10个好友,请第二次从10开始,直到返回0xffff
sorted:
 const unsigned char QQ_FRIEND_LIST_UNSORTED = 0;
 const unsigned char QQ_FRIEND_LIST_SORTED = 1;
friendItem:
 qqNumber:4
 face:2
 age:1
 gender:1
  const unsigned char QQ_FRIEND_GENDER_GG = 0x0;
  const unsigned char QQ_FRIEND_GENDER_MM = 0x1;
 nicknameLength:1
 nickname:nicknameLength
 unknown:2
 extFlag:1
  bit1:qqshow
 commonFlag:1
  bit1:memeber
  bit4:TCP mode
  bit5:mobile QQ
  bit6:mobile binding
  bit7:webcam

4.6 QQ_CMD_GET_FRIEND_ONLINE
======

c -> s : 需要ack
unknown:1 = 0x02
position:1
unknown:3 = 0x00

c <- s :
position:1
friendOnlineItem[]:bodyLength-1

fields comment:
position:
 const char QQ_FRIEND_ONLINE_LIST_POSITION_START = 0x00;
 const char QQ_FRIEND_ONLINE_LIST_POSITION_END = 0xFF;
 由于是无状态服务器,每次设定列表的position,从0开始,如果返回了10个好友,请第二次从10开始,直到返回0xff
friendOnlineItem:
 friendStatusItem:
  qqNumber:4
  unknown:1
  ip:4
  port:2
  unknown:1
  status:1
   const unsigned char QQ_FRIEND_STATUS_ONLINE = 10
   const unsigned char QQ_FRIEND_STATUS_OFFLINE = 20
   const unsigned char QQ_FRIEND_STATUS_LEAVE = 30
   const unsigned char QQ_FRIEND_STATUS_INVISIBLE = 40
  unknown:2
  unknownKey:16 
 unknown:2
 extFlag:1
 commonFlag:1
 unknown:2
 ending:1
 
4.7 QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS
======

c <- s : 需要ack
friendStatusItem

c -> s :
null

4.8 QQ_CMD_CHANGE_STATUS
======

c -> s : 需要ack
status:1
miscStatus:4
 const int QQ_MISC_STATUS_HAVING_VIDEO = 0x00000001

c <- s :
replyCode:1
 const unsigned char QQ_CHANGE_STATUS_REPLY_OK = 0x30
 
4.9 QQ_CMD_SEND_IM
======

c -> s : 需要ack
sender:4
receiver:4
version:2
sender:4
receiver:4
fileSessionKey:16
contentType:2
 const short QQ_IM_NORMAL_TEXT = 0x000B
sequence:2
sendingTime:4
face:2
content:
 unknown:3 = {0x00,0x00,0x00}
 font:1 = 0x01         //Has Font Attribute?
 unknown:4 = {0x00,0x00,0x00,0x00}
 replyType:1
  const unsigned char QQ_IM_NORMAL_REPLY = 0x01
  const unsigned char QQ_IM_AUTO_REPLY = 0x02 
 messageString         //string without 0x00 at the end
 spaceFlag:1 = 0x20
 terminateFlag:1 = 0x00
 fontFlag:1
  const unsigned char fontFlag_bold = 0x20
  const unsigned char fontFlag_italic =0x40
  const unsigned char fontFlag_underline = 0x80
  const unsigned char fontFlag_sizeMask = 0x1f
 red:1
 green:1
 blue:1
 terminateFlag:1 = 0x00
 encoding:2
  const short QQ_IM_ENCODING_GB = 0x8602
 fontNameString         //just set font name to "Song Ti" in Chinese
 EnterFlag:1 = 0x0d

c <- s :
replyCode:
 const unsigned char QQ_SEND_IM_REPLY_OK = 0x00

4.10 QQ_CMD_RECV_IM
======

c <- s : 需要ack
version:2
sender:4
receiver:4
fileSessionKey:16
contentType:2
sequence:2
sendingTime:4
face:2
content:
 unknown:3 = {0x00,0x00,0x00}
 font:1 = 0x01         //Has Font Attribute?
 unknown:4 = {0x00,0x00,0x00,0x00}
 replyType:1
  const unsigned char QQ_IM_NORMAL_REPLY = 0x01
  const unsigned char QQ_IM_AUTO_REPLY = 0x02 
 messageString         //string
 spaceFlag:1 = 0x20
 terminateFlag:1 = 0x00
 fontFlag:1
 red:1
 green:1
 blue:1
 terminateFlag:1 = 0x00
 encoding:2
 fontNameString         //just set font name to "Song Ti" in Chinese
 EnterFlag:1 = 0x0d

c -> s :
null

4.11 QQ_CMD_GET_USER_INFO
======

c -> s : 需要ack
id:4

c <- s :
是37个用0x13结尾的不定长的string
xxxx/0x1e            //Info_qqID
xxxx/0x1e            //Info_nick
xxxx/0x1e            //...
xxxx/0x1e            //Info_qqShow
xxxx/0x1e            //Info_unknown6

fields commnet:
enum Info_Index{
 Info_qqID,       Info_nick,      Info_country,  Info_province,  Info_zipcode,
 Info_address,    Info_telephone, Info_age,      Info_gender,    Info_name,
 Info_email,      Info_pagerSn,   Info_pagerNum, Info_pagerSp,   Info_pagerBaseNum,
 Info_pagerType,  Info_occupation,Info_homepage, Info_authType,  Info_unknown1,
 Info_unknown2,   Info_face,      Info_mobile,   Info_mobileType,Info_intro,
 Info_city,       Info_unknown3,  Info_unknown4, Info_unknown5,  Info_openHp,
 Info_openContact,Info_college,   Info_horoscope,Info_zodiac,    Info_blood,
 Info_qqShow,     Info_unknown6 
 };

4.12 QQ_CMD_MODIFY_INFO
======

c -> s : 需要ack
是39个用0x13结尾的不定长的string,QQ_CMD_GET_USER_INFO的基础上加了密码修改的字段
xxxx/0x1e            //currentPassword,不改密码就为null
xxxx/0x1e            //newPassword,不改密码就为null
xxxx/0x1e            //Info_qqID
xxxx/0x1e            //Info_nick
xxxx/0x1e            //...
xxxx/0x1e            //Info_qqShow
xxxx/0x1e            //Info_unknown6

c <- s :
message:bodyLength          //如果开头就是id,说明修改成功

4.13 QQ_CMD_SEARCH_USER
======

c -> s : 需要ack
searchType:1
 const unsigned char QQ_SEARCH_ALL = 0x31;
 const unsigned char QQ_SEARCH_CUSTOM = 0x30;
divider:1 = 0x1f
IF searchType=QQ_SEARCH_ALL
 pageString:          //string,从0开始的页数index

IF searchType=QQ_SEARCH_CUSTOM
 qqNumberString:         //可以为null,必须填充0x2D
 divider:1 = 0x1f
 qqNumberString:         //可以为null,必须填充0x2D;如果不是全匹配,必须用0x25结尾
 divider:1 = 0x1f
 qqNumberString:         //可以为null,必须填充0x2D;如果不是全匹配,必须用0x25结尾
 divider:1 = 0x1f
 pageString:          //string,从0开始的页数index
 endFlag:1 = 0x00

c <- s :
OnlineUserItem[]:bodyLength       //如果开头两个字节是0x2d 0x31说明结束了

fields comment:
OnlineUserItem:
 qqNumberString:
 divider:1 = 0x1e or 0x1f
 nicknameString:
 divider:1 = 0x1e or 0x1f
 priviceString:
 divider:1 = 0x1e or 0x1f
 faceString:
 divider:1 = 0x1e or 0x1f
 divider:1 = 0x1f 

4.14 QQ_CMD_GET_LEVEL
======

c -> s : 需要ack
unknown:1 = 0x00
qqNumber[]:bodyLength-1        //one array contains qq id

c <- s :
replyCode:1
LevelUserItem[]:bodyLength-1

fields comment:
LevelUserItem:
 qqNumber:4
 onelineTime:4
 level:2
 timeRemainder:2

4.15 QQ_CMD_REQUEST_KEY
======

c -> s : 需要ack
keyType:1

c <- s :
keyType:1
 const unsigned char QQ_REQUEST_UNKNOWN_KEY = 0x03
 const unsigned char QQ_REQUEST_FILE_AGENT_KEY = 0x04
replyCode:1
 const unsigned char QQ_REQUEST_KEY_REPLY_OK = 0x00
IF replyCode=QQ_REQUEST_KEY_REPLY_OK & IF keyType=QQ_REQUEST_FILE_AGENT_KEY
fileAgentKey:16
unknown:12
tokenLength:1
fileAgenttoken:tokenLength

4.16 QQ_CMD_FRIEND_REMARK_OP [x]
======

好友备注设置

c -> s : 需要ack
c <- s :

4.17 QQ_CMD_REQUEST_EXTRA_INFORMATION
======

c -> s : 需要ack
requestType:1 = 0x01
offset:2            //和前面取用户列表一样的用法,从零开始

c <- s :
replyCode:1 = 0x01
offset:2
unknown:1 = 0x03
UserExtraItem[]:bodyLength-4

fields comment:
UserExtraItem:
 qqNumber:4
 infoFlag:2           //information flags( signature, QQ tang, QQ album, QQ firend making )
  const unsigned short QQ_EXTAR_INFO_PAL       = 0x0004;  // QQ friends center flag
  const unsigned short QQ_EXTAR_INFO_USER_HEAD = 0x0010;  // QQ customized face flag, QQ calls them user head, because all pictures stored in UserHead directory
  const unsigned short QQ_EXTAR_INFO_ALBUM     = 0x0100;  // QQ ablum flag
  const unsigned short QQ_EXTAR_INFO_TANG      = 0x0800;  // QQ tang flag, is QQ tang a sort of game? not sure what it is.
  const unsigned short QQ_EXTAR_INFO_SIGNATURE = 0x4000;  // QQ personal signature flag
 delimiter:1 = 0x00
 
4.18 QQ_CMD_SIGNATURE_OP
======

qq个性签名

c -> s : 需要ack
subCmd:1
 const unsigned char QQ_SIGNATURE_MODIFY = 0x01
 const unsigned char QQ_SIGNATURE_DELETE = 0x02
 const unsigned char QQ_SIGNATURE_REQUEST = 0x03
IF subCmd=QQ_SIGNATURE_MODIFY
 unknown:1 = 0x00
 length:1
 signature:length
IF subCmd=QQ_SIGNATURE_DELETE
 null
IF subCmd=QQ_SIGNATURE_REQUEST
 number:2
 signRequestItem<number>: bodyLength-3

c <- s :
subCmd:1
replyCode:1
 const unsigned char QQ_SIGNATURE_REQUEST_REPLY_OK = 0x00
IF subCmd=QQ_SIGNATURE_MODIFY
 null
IF subCmd=QQ_SIGNATURE_DELETE
 null
IF subCmd=QQ_SIGNATURE_REQUEST
 signItem[]: bodyLength-2

fields comment:
signRequestItem:
 qqNumber:4
 unknown:4 = time or 0x00 00 00 01 or 0x00 00 00 02

signItem:
 qqNumber:4
 lastModifyTime:4
 signLength:1
 sign:signLength

4.19 QQ_CMD_ADD_FRIEND
======

c -> s : 需要ack
qqNumberString:bodyLength

c <- s :
qqNumberString: //string,my qq id
delimiter:1 = 0x1f
replyCode:1
 const unsigned char QQ_AUTH_NO_AUTH = 0x30;    //Add Successful
 const unsigned char QQ_AUTH_NEED_AUTH = 0x31;  //Adding not allowed
 const unsigned char QQ_AUTH_NO_ADD = 0x32;     //Need authorization,

4.20 QQ_CMD_ADD_FRIEND_AUTH
======

c -> s : 需要ack
qqNumberString:bodyLength
delimiter:1 = 0x1f
subCmd:1
 const unsigned char QQ_MY_AUTH_APPROVE = 0x30; //Accept
 const unsigned char QQ_MY_AUTH_REJECT = 0x31; //Reject
 const unsigned char QQ_MY_AUTH_REQUEST = 0x32; //Request
delimiter:1 = 0x1f
message:bodyLength-$

c <- s :
replyCode:            //服务器决定帮助投递,并回了一个ack而已,真正结果在 s-->c QQ_CMD_RECV_MSG_SYS 的包里面
 const unsigned char QQ_ADD_FRIEND_AUTH_REPLY_OK = 0x30 

4.21 QQ_CMD_DELETE_FRIEND
======

c -> s : 需要ack
qqNumberString:bodyLength

c <- s :
replyCode:1
 const unsigned char QQ_DELETE_FRIEND_REPLY_OK = 0x00

4.22 QQ_CMD_DELETE_ME
======

c -> s : 需要ack
qqNumber:4

c <- s :
replyCode:1           //服务器决定帮助投递,并回了一个ack而已
 const unsigned char QQ_DELETE_ME_REPLY_OK = 0x00

4.23 QQ_CMD_GROUP_NAME_OP
======

c -> s : 需要ack
subCmd:1
 const unsigned char QQ_UPLOAD_GROUP_NAME = 0x2 //upload group name
 const unsigned char QQ_DOWNLOAD_GROUP_NAME = 0x1//download group name
IF subCmd=QQ_UPLOAD_GROUP_NAME
 groupNameItem[]:bodyLength-1
IF subCmd=QQ_DOWNLOAD_GROUP_NAME
 unknown:1 = 0x02
 unknown:4 = 0x00 00 00 00

c <- s :
subCmd:1
replyCode:1
 const unsigned char  = QQ_CMD_GROUP_NAME_OP_REPLY_OK = 0x00  //i can NOT sure
IF subCmd=QQ_DOWNLOAD_GROUP_NAME
 unknown:4
 groupNameItem[]:bodyLength-6
 
fields comment:
groupNameItem:
 groupIndex:1         //fixed group,ie,the first one,should not upload
 groupName:16         //fixed length array,faint ,so ugly

4.24 QQ_CMD_UPLOAD_GROUP_FRIEND
======

c -> s : 需要ack
groupFriendItem[]:bodyLength

c <- s :
replyCode:1
 const unsigned char = QQ_CMD_UPLOAD_GROUP_FRIEND_REPLY_OK = 0x00 //i can NOT sure
 
fields comment:
groupFriendItem:
 qqNumber:4
 groupIndex:1         //(groupIndex>> 2) & 0x3f is right,at QQ_CMD_DOWNLOAD_GROUP_FRIEND

4.25 QQ_CMD_DOWNLOAD_GROUP_FRIEND
======

c -> s : 需要ack
unknown:1 = 0x01
unknown:1 = 0x02
unknown:2 = 0x00 00
startID:4           //start from 0x00000000

c <- s :
unknown:6
nextID:4           //next query from this ID
groupFriendItem[]:bodyLength-10

4.26 QQ_CMD_QUN_CMD [x]
======

c -> s : 需要ack
c <- s :

fields comment:
 const unsigned char QQ_QUN_CMD_CREATE_QUN             = 0x01;
 const unsigned char QQ_QUN_CMD_MODIFY_MEMBER          = 0x02;
 const unsigned char QQ_QUN_CMD_MODIFY_QUN_INFO        = 0x03;
 const unsigned char QQ_QUN_CMD_GET_QUN_INFO           = 0x04;
 const unsigned char QQ_QUN_CMD_ACTIVATE_QUN           = 0x05;
 const unsigned char QQ_QUN_CMD_SEARCH_QUN             = 0x06;
 const unsigned char QQ_QUN_CMD_JOIN_QUN               = 0x07;
 const unsigned char QQ_QUN_CMD_JOIN_QUN_AUTH          = 0x08;
 const unsigned char QQ_QUN_CMD_EXIT_QUN               = 0x09;
 const unsigned char QQ_QUN_CMD_SEND_IM                = 0x0A;
 const unsigned char QQ_QUN_CMD_GET_ONLINE_MEMBER      = 0x0B;
 const unsigned char QQ_QUN_CMD_GET_MEMBER_INFO        = 0x0C;
 const unsigned char QQ_QUN_CMD_MODIFY_CARD            = 0x0E;
 const unsigned char QQ_QUN_CMD_REQUEST_CARD           = 0x10;
 const unsigned char QQ_QUN_CMD_SEND_IM_EX             = 0x1A;
 const unsigned char QQ_QUN_CMD_ADMIN                  = 0x1B;
 const unsigned char QQ_QUN_CMD_TRANSFER               = 0x1C;
 const unsigned char QQ_QUN_CMD_CREATE_TEMP_QUN        = 0x30;
 const unsigned char QQ_QUN_CMD_MODIFY_TEMP_QUN_MEMBER     = 0x31;
 const unsigned char QQ_QUN_CMD_EXIT_TEMP_QUN          = 0x32;
 const unsigned char QQ_QUN_CMD_GET_TEMP_QUN_INFO      = 0x33;
 const unsigned char QQ_QUN_CMD_SEND_TEMP_QUN_IM       = 0x35;
 const unsigned char QQ_QUN_CMD_GET_TEMP_QUN_MEMBERS       = 0x37;

4.27 QQ_CMD_CELL_PHONE_1 [x]
======

c -> s : 需要ack
c <- s :

4.28 QQ_CMD_CELL_PHONE_2 [x]
======

c -> s : 需要ack
c <- s :

4.29 QQ_CMD_ACK_SYS_MSG [x]
======

c -> s : 需要ack
c <- s :

4.30 QQ_CMD_RECV_MSG_SYS
======

c <- s : 需要ack
typeString/0x1f:
 const short QQ_MSG_SYS_BEING_ADDED = 1   //being added by other party
 const short QQ_MSG_SYS_ADD_FRIEND_REQUEST = 2 //Somebody request me
 const short QQ_MSG_SYS_ADD_FRIEND_APPROVED = 3 //Accept my request
 const short QQ_MSG_SYS_ADD_FRIEND_REJECTED = 4 //I was rejected
 const short QQ_MSG_SYS_UPDATE_HINT = 9   //faint,server update message
fromQQNumberString/0x1f:
toQQNumberString/0x1f:
message:bodyLength-$

c -> s :
null

4.31 QQ_CMD_TEST [x]
======

c -> s : 需要ack
c <- s :

抱歉!评论已关闭.