数据结构

消息索引

  1. msgindex:全消息箱
  2. 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相关

意义不明…… 貌似是通讯录一类的东西