(未显示同一用户的5个中间版本) | |||
第1行: | 第1行: | ||
+ | [[Category:BBS 代码分析]] | ||
== 数据结构 == | == 数据结构 == | ||
第9行: | 第10行: | ||
** 对于收件箱:已读消息个数 | ** 对于收件箱:已读消息个数 | ||
* 之后:struct msghead[] | * 之后:struct msghead[] | ||
+ | ** 对应 MsgHead | ||
+ | |||
+ | <source lang="c"> | ||
+ | struct msghead { | ||
+ | int pos, len; // 消息体在msgcontent中的位置&长度 | ||
+ | char sent; // 1: 发送的消息 0: 收到的消息 | ||
+ | char mode; // | ||
+ | char id[IDLEN+2]; // 发送/接收者ID | ||
+ | time_t time; // 发送/接收时间 | ||
+ | int frompid, topid; // 发送/接收者进程号 | ||
+ | }; | ||
+ | </source> | ||
+ | |||
+ | == 发送消息过程分析 == | ||
+ | <source lang="cpp"> | ||
+ | int sendmsgfunc(struct user_info *uentp, const char *msgstr, int mode) | ||
+ | { | ||
+ | char uident[STRLEN]; | ||
+ | struct user_info *uin; | ||
+ | struct msghead head, head2; | ||
+ | |||
+ | *msgerr = 0; | ||
+ | uin = uentp; // uin = 接收者userinfo | ||
+ | strcpy(uident, uin->userid); // uident = 接收者userid | ||
+ | if (!HAS_PERM(currentuser, PERM_SEECLOAK) && uin->invisible && strcmp(uin->userid, currentuser->userid) && mode != 4) | ||
+ | // 若接收者隐身并且我们不能看隐身,并且不是自己发给自己,则不让发 | ||
+ | { | ||
+ | return -2; | ||
+ | } | ||
+ | if ((mode != 3) && (LOCKSCREEN == uin->mode)) { /* Leeward 98.02.28 */ | ||
+ | // 对方锁屏,不让发 | ||
+ | strcpy(msgerr, "对方已经锁定屏幕,请稍候再发或给他(她)写信..."); | ||
+ | return -1; | ||
+ | } | ||
+ | if ((mode != 3) && (false == canIsend2(currentuser,uin->userid))) { /*Haohmaru.06.06.99.检查自己是否被ignore */ | ||
+ | // 对方拒绝你的消息,不让发 | ||
+ | // canIsend2()在stuff.c | ||
+ | // 拒绝列表在ignores文件里 | ||
+ | strcpy(msgerr, "对方拒绝接受你的讯息..."); | ||
+ | return -1; | ||
+ | } | ||
+ | if (mode != 3 && uin->mode != WEBEXPLORE) { | ||
+ | if (get_unreadcount(uident) > MAXMESSAGE) { | ||
+ | // 未读消息太多,不让发 | ||
+ | strcpy(msgerr, "对方尚有一些讯息未处理,请稍候再发或给他(她)写信..."); | ||
+ | return -1; | ||
+ | } | ||
+ | } | ||
+ | if (msgstr == NULL) { | ||
+ | // 木有消息,不让发…… | ||
+ | // Comment: 为啥不早查…… | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | // 开工构造消息头 | ||
+ | // 这个是存接收者那边的…… | ||
+ | head.time = time(0); // 发送时间 | ||
+ | head.sent = 0; // 接收方消息头 | ||
+ | head.mode = mode; // 发送者模式 | ||
+ | strncpy(head.id, currentuser->userid, IDLEN+2); // 发送者userid(sent=0) | ||
+ | head.frompid = getuinfopid(); // 发送者pid | ||
+ | head.topid = uin->pid; // 接收者pid | ||
+ | // 这个是存发送者那边的…… | ||
+ | memcpy(&head2, &head, sizeof(struct msghead)); // 拷一份,发送者消息头 | ||
+ | head2.sent = 1; // 我发的! | ||
+ | strncpy(head2.id, uident, IDLEN+2); // 接收者userid(sent=1) | ||
+ | // 造好了 | ||
+ | |||
+ | // 再查一次用户userinfo…… | ||
+ | // t_search()在stuff.c | ||
+ | uin = t_search(MsgDesUid, uentp->pid); | ||
+ | // 这次查败了,说明接收者跑了,可能是写消息的时候跑的 | ||
+ | if ((uin == NULL) || (uin->active == 0) || (uin->pid == 0) || ((kill(uin->pid, 0) != 0) && (uentp->pid != 1)) | ||
+ | || strncasecmp(MsgDesUid,uident,STRLEN)) { | ||
+ | strcpy(msgerr, "对方已经离线..."); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | // 保存消息 | ||
+ | // 消息加到接收者收件箱 | ||
+ | if (save_msgtext(uident, &head, msgstr) < 0) | ||
+ | return -2; | ||
+ | if (strcmp(currentuser->userid, uident)&&mode!=3) { | ||
+ | // 如果不是自己发给自己,那就在发送者这边也存一份…… | ||
+ | if (save_msgtext(currentuser->userid, &head2, msgstr) < 0) | ||
+ | return -2; | ||
+ | } | ||
+ | if( uin->mode == WWW ){ | ||
+ | uin->mailcheck |= CHECK_MSG; | ||
+ | return 1; | ||
+ | } | ||
+ | // 保存完毕 | ||
+ | |||
+ | // 消息通知 | ||
+ | // 发送SIGUSR2说明有新消息 | ||
+ | if (uentp->pid != 1 && kill(uin->pid, SIGUSR2) == -1) { | ||
+ | strcpy(msgerr, "对方已经离线....."); | ||
+ | return -1; | ||
+ | } | ||
+ | |||
+ | // 完成! | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | </source> | ||
== libmsg.c == | == libmsg.c == | ||
+ | ; canmsg [(struct userec *fromuser, struct user_info *uin)] | ||
+ | * User.CanSendTo() | ||
+ | |||
+ | ; can_override [(char *userid, char *whoasks)] | ||
+ | : 没人用过…… | ||
+ | |||
+ | ; msg_can_sendmsg [(char *userid, int utmppid)] | ||
+ | : 没人用过…… | ||
; save_msgtext() | ; save_msgtext() | ||
第44行: | 第158行: | ||
; translate_msg() | ; translate_msg() | ||
− | : | + | : 将消息转换为在消息记录之类里面看见的样子 |
; mail_msg() | ; mail_msg() |
2012年2月16日 (四) 05:05的最新版本
数据结构
消息索引
- msgindex:全消息箱
- msgindex2:收件箱
- 0x00-0x03 4字节
- 对于收件箱:已读消息个数
- 之后:struct msghead[]
- 对应 MsgHead
struct msghead {
int pos, len; // 消息体在msgcontent中的位置&长度
char sent; // 1: 发送的消息 0: 收到的消息
char mode; //
char id[IDLEN+2]; // 发送/接收者ID
time_t time; // 发送/接收时间
int frompid, topid; // 发送/接收者进程号
};
发送消息过程分析
int sendmsgfunc(struct user_info *uentp, const char *msgstr, int mode)
{
char uident[STRLEN];
struct user_info *uin;
struct msghead head, head2;
*msgerr = 0;
uin = uentp; // uin = 接收者userinfo
strcpy(uident, uin->userid); // uident = 接收者userid
if (!HAS_PERM(currentuser, PERM_SEECLOAK) && uin->invisible && strcmp(uin->userid, currentuser->userid) && mode != 4)
// 若接收者隐身并且我们不能看隐身,并且不是自己发给自己,则不让发
{
return -2;
}
if ((mode != 3) && (LOCKSCREEN == uin->mode)) { /* Leeward 98.02.28 */
// 对方锁屏,不让发
strcpy(msgerr, "对方已经锁定屏幕,请稍候再发或给他(她)写信...");
return -1;
}
if ((mode != 3) && (false == canIsend2(currentuser,uin->userid))) { /*Haohmaru.06.06.99.检查自己是否被ignore */
// 对方拒绝你的消息,不让发
// canIsend2()在stuff.c
// 拒绝列表在ignores文件里
strcpy(msgerr, "对方拒绝接受你的讯息...");
return -1;
}
if (mode != 3 && uin->mode != WEBEXPLORE) {
if (get_unreadcount(uident) > MAXMESSAGE) {
// 未读消息太多,不让发
strcpy(msgerr, "对方尚有一些讯息未处理,请稍候再发或给他(她)写信...");
return -1;
}
}
if (msgstr == NULL) {
// 木有消息,不让发……
// Comment: 为啥不早查……
return 0;
}
// 开工构造消息头
// 这个是存接收者那边的……
head.time = time(0); // 发送时间
head.sent = 0; // 接收方消息头
head.mode = mode; // 发送者模式
strncpy(head.id, currentuser->userid, IDLEN+2); // 发送者userid(sent=0)
head.frompid = getuinfopid(); // 发送者pid
head.topid = uin->pid; // 接收者pid
// 这个是存发送者那边的……
memcpy(&head2, &head, sizeof(struct msghead)); // 拷一份,发送者消息头
head2.sent = 1; // 我发的!
strncpy(head2.id, uident, IDLEN+2); // 接收者userid(sent=1)
// 造好了
// 再查一次用户userinfo……
// t_search()在stuff.c
uin = t_search(MsgDesUid, uentp->pid);
// 这次查败了,说明接收者跑了,可能是写消息的时候跑的
if ((uin == NULL) || (uin->active == 0) || (uin->pid == 0) || ((kill(uin->pid, 0) != 0) && (uentp->pid != 1))
|| strncasecmp(MsgDesUid,uident,STRLEN)) {
strcpy(msgerr, "对方已经离线...");
return -1;
}
// 保存消息
// 消息加到接收者收件箱
if (save_msgtext(uident, &head, msgstr) < 0)
return -2;
if (strcmp(currentuser->userid, uident)&&mode!=3) {
// 如果不是自己发给自己,那就在发送者这边也存一份……
if (save_msgtext(currentuser->userid, &head2, msgstr) < 0)
return -2;
}
if( uin->mode == WWW ){
uin->mailcheck |= CHECK_MSG;
return 1;
}
// 保存完毕
// 消息通知
// 发送SIGUSR2说明有新消息
if (uentp->pid != 1 && kill(uin->pid, SIGUSR2) == -1) {
strcpy(msgerr, "对方已经离线.....");
return -1;
}
// 完成!
return 1;
}
libmsg.c
- canmsg [(struct userec *fromuser, struct user_info *uin)]
- User.CanSendTo()
- can_override [(char *userid, char *whoasks)]
- 没人用过……
- msg_can_sendmsg [(char *userid, int utmppid)]
- 没人用过……
- save_msgtext()
- 对应 MsgBox.SaveMsgText()
- 把消息存到用户的msgindex与msgcontent文件中。如果是接收到的,也存到msgindex2中。
- load_msghead()
- 对应 MsgBox.LoadMsgHead()
- 读出某个消息头,可以指定全消息箱还是收件箱。
- get_msgcount()
- 对应 MsgBox.GetMsgCount()
- 获取消息数量。
- clear_msg()
- 对应 MsgBox.ClearMsg()
- 清除所有消息
- get_unreadcount()
- 对应 MsgBox.GetUnreadCount()
- 获取未读消息数
- get_unreadmsg()
- 对应 MsgBox.GetUnreadMsg()
- 从收件箱里获取某条消息,并且修改已读指针。
- load_msgtext()
- 对应 MsgBox.LoadMsgText()
- 读取某条消息的内容。
- sendmsgfunc()
- 发送消息。
- translate_msg()
- 将消息转换为在消息记录之类里面看见的样子
- mail_msg()
- 将所有消息放入邮件寄回信箱。
- mailbacklastmsg()
- 将未发送成功消息寄回信箱。
SMS支持
不在研究范围……
SQL相关
意义不明…… 貌似是通讯录一类的东西