diff options
-rw-r--r-- | pttbbs/daemon/angelbeats/abc.c | 4 | ||||
-rw-r--r-- | pttbbs/daemon/angelbeats/angelbeats.c | 123 | ||||
-rw-r--r-- | pttbbs/include/daemons.h | 3 | ||||
-rw-r--r-- | pttbbs/include/proto.h | 1 | ||||
-rw-r--r-- | pttbbs/mbbsd/angel.c | 70 | ||||
-rw-r--r-- | pttbbs/mbbsd/mbbsd.c | 17 | ||||
-rw-r--r-- | pttbbs/mbbsd/user.c | 2 |
7 files changed, 130 insertions, 90 deletions
diff --git a/pttbbs/daemon/angelbeats/abc.c b/pttbbs/daemon/angelbeats/abc.c index 415179bc..b5f001d6 100644 --- a/pttbbs/daemon/angelbeats/abc.c +++ b/pttbbs/daemon/angelbeats/abc.c @@ -83,6 +83,8 @@ int main(int argc, char *argv[]) "max_masters_of_online_angels=%d\n" "min_masters_of_active_angels=%d\n" "max_masters_of_active_angels=%d\n" + "my_index=%d\n" + "my_active_index=%d\n" "my_active_masters=%d\n", rpt.total_angels, rpt.total_online_angels, @@ -91,6 +93,8 @@ int main(int argc, char *argv[]) rpt.max_masters_of_online_angels, rpt.min_masters_of_active_angels, rpt.max_masters_of_active_angels, + rpt.my_index, + rpt.my_active_index, rpt.my_active_masters); } else { if (toread(fd, &req, sizeof(req)) != sizeof(req)) { diff --git a/pttbbs/daemon/angelbeats/angelbeats.c b/pttbbs/daemon/angelbeats/angelbeats.c index 55c65861..e9270eb5 100644 --- a/pttbbs/daemon/angelbeats/angelbeats.c +++ b/pttbbs/daemon/angelbeats/angelbeats.c @@ -16,7 +16,7 @@ // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // -------------------------------------------------------------------------- -// TODO change to sort by activity +// TODO cache report results. #include <stdio.h> #include <stdlib.h> @@ -52,9 +52,9 @@ static int verbose = 0; // (total online angels are twice than active angels) typedef struct { + time_t last_activity; // last known activity from master int uid; int masters; // counter of who have this one as angel - time_t last_activity; // last known activity from master char userid[IDLEN+1]; } AngelInfo; @@ -78,6 +78,13 @@ int angel_list_comp_masters(const void *pva, const void *pvb) { return pa->masters - pb->masters; } +int angel_list_comp_advanced(const void *pva, const void *pvb) { + AngelInfo *pa = (AngelInfo*) pva, *pb = (AngelInfo*) pvb; + if (pa->last_activity == pb->last_activity) + return pa->masters - pb->masters; + return pa->last_activity > pb->last_activity ? 1 : -1; +} + // search stubs AngelInfo * @@ -119,9 +126,9 @@ angel_list_preserve(int newsz) { } void -angel_list_sort_by_masters() { +angel_list_sort() { qsort(g_angel_list, g_angel_list_size, sizeof(AngelInfo), - angel_list_comp_masters); + angel_list_comp_advanced); } AngelInfo * @@ -151,17 +158,11 @@ angel_list_get_index(AngelInfo *kanade) { int suggest_online_angel(int master_uid) { - userinfo_t *astat = NULL; - int candidates[ANGEL_SUGGEST_RANGE] = {0}, num_candidates = 0; + userinfo_t *astat; int i; - // 1. find appropriate angels - // 2. select from one of them - // 3. return uid - for (i = 0; i < g_angel_list_size; i++) { - AngelInfo *kanade = g_angel_list+i; - int is_good_uid = 0; + AngelInfo *kanade = g_angel_list + i; // skip the master himself if (kanade->uid == master_uid) @@ -172,65 +173,33 @@ suggest_online_angel(int master_uid) { for (astat = search_ulistn(kanade->uid, 1); astat && strcasecmp(astat->userid, kanade->userid) == 0; astat++) { + // ignore all dead processes if (astat->mode == DEBUGSLEEPING) continue; + // if any sessions is not safe, ignore it. - if (!(astat->userlevel & PERM_ANGEL) || - astat->angelpause) { - is_good_uid = 0; + if (!(astat->userlevel & PERM_ANGEL) || astat->angelpause) break; - } - if (!is_good_uid) - is_good_uid = astat->uid; - } - - // a good candidate? - if (is_good_uid) - candidates[num_candidates++] = is_good_uid; - // terminate when too many candidates - if (num_candidates >= ANGEL_SUGGEST_RANGE) - break; - } - if (!num_candidates) - return 0; - // verbose report - if (debug || verbose) { - printf("suggest candidates: "); - for (i = 0; i < num_candidates; i++) { - printf("%d, ", candidates[i]); + return astat->uid; } - printf("\n"); } - - return candidates[rand() % num_candidates]; + return 0; } int inc_angel_master(int uid) { AngelInfo *kanade = angel_list_find_by_uid(uid); - int idx; if (!kanade) return 0; kanade->masters++; - idx = angel_list_get_index(kanade); - // TODO only sort when kanade->masters > (kanade+1)->masters - if (idx + 1 < g_angel_list_size && - kanade->masters > (kanade+1)->masters) { - angel_list_sort_by_masters(); - kanade = angel_list_find_by_uid(uid); - assert(kanade); - fprintf(stderr, " * angel (%s) position changed: %d -> %d\n", - kanade->userid, idx, angel_list_get_index(kanade)); - } return 1; } int dec_angel_master(int uid) { AngelInfo *kanade = angel_list_find_by_uid(uid); - int idx; if (!kanade) return 0; if (kanade->masters == 0) { @@ -238,17 +207,20 @@ dec_angel_master(int uid) { "which was already zero: %d\n", uid); return 0; } - idx = angel_list_get_index(kanade); kanade->masters--; - // TODO only sort when kanade->masters < (kanade-1)->masters - if (idx > 0 && - kanade->masters < (kanade-1)->masters) { - angel_list_sort_by_masters(); - kanade = angel_list_find_by_uid(uid); - assert(kanade); - fprintf(stderr, " * angel (%s) position changed: %d -> %d\n", - kanade->userid, idx, angel_list_get_index(kanade)); - } + return 1; +} + +int +touch_angel_activity(int uid) { + AngelInfo *kanade = angel_list_find_by_uid(uid); + int now = (int)time(0); + + now -= now % 60; + if (!kanade || kanade->last_activity == now) + return 0; + + kanade->last_activity = now; return 1; } @@ -306,7 +278,7 @@ int init_angel_list() { g_angel_list_size = 0; passwd_apply(NULL, init_angel_list_callback); - angel_list_sort_by_masters(); + angel_list_sort(); return 0; } @@ -319,6 +291,9 @@ create_angel_report(int myuid, angel_beats_report *prpt) { prpt->min_masters_of_active_angels = SHRT_MAX; prpt->min_masters_of_online_angels = SHRT_MAX; prpt->total_angels = g_angel_list_size; + prpt->my_index = 0; + prpt->my_active_index = 0; + if(debug) printf("g_angel_list_size: %d\n", g_angel_list_size); for (i = 0; i < g_angel_list_size; i++, kanade++) { // online? @@ -342,21 +317,30 @@ create_angel_report(int myuid, angel_beats_report *prpt) { is_online = 1; } if (debug) { + printf("(masters=%d, activity=%d, ", + kanade->masters, kanade->last_activity); switch(logins) { case 0: - printf("(not online)"); + printf("NOT online)"); break; case 1: - printf("(online)"); + printf("online)"); break; default: - printf("(multi login: %d)", logins); + printf("multi login: %d)", logins); break; } printf("\n"); } // update report numbers prpt->total_online_angels += is_online; + if (myuid > 0) { + if (myuid == kanade->uid) { + prpt->my_index = i + 1; + if (!is_pause) + prpt->my_active_index = prpt->total_active_angels + 1; + } + } if (is_online) { if (!is_pause) { prpt->total_active_angels++; @@ -439,12 +423,10 @@ client_cb(int fd, short event, void *arg) { Cdatelite(&clk), master_uid); data.angel_uid = suggest_online_angel(data.master_uid); if (data.angel_uid > 0) { - fprintf(stderr, "<pos: %d> ", - angel_list_get_index( - angel_list_find_by_uid(data.angel_uid))); inc_angel_master(data.angel_uid); uid = getuserid(data.angel_uid); strlcpy(angel_uid, uid, sizeof(angel_uid)); + angel_list_sort(); } fprintf(stderr, "result: [%s]\n", data.angel_uid > 0 ? angel_uid : "<none>"); @@ -453,7 +435,14 @@ client_cb(int fd, short event, void *arg) { fprintf(stderr, "%s request remove link by " "master [%s] to angel [%s]\n", Cdatelite(&clk), master_uid, angel_uid); - dec_angel_master(data.angel_uid); + if (dec_angel_master(data.angel_uid)) + angel_list_sort(); + break; + case ANGELBEATS_REQ_HEARTBEAT: + fprintf(stderr, "%s update activity (heartbeat) to angel [%s]\n", + Cdatelite(&clk), angel_uid); + if (touch_angel_activity(data.angel_uid)) + angel_list_sort(); break; case ANGELBEATS_REQ_REPORT: fprintf(stderr, "%s report by [%s]\n", Cdatelite(&clk), master_uid); diff --git a/pttbbs/include/daemons.h b/pttbbs/include/daemons.h index 92908340..f9a5e038 100644 --- a/pttbbs/include/daemons.h +++ b/pttbbs/include/daemons.h @@ -66,6 +66,7 @@ enum ANGELBEATS_OPERATIONS { ANGELBEATS_REQ_SUGGEST, ANGELBEATS_REQ_SUGGEST_AND_LINK, ANGELBEATS_REQ_REMOVE_LINK, + ANGELBEATS_REQ_HEARTBEAT, }; typedef struct { @@ -85,6 +86,8 @@ typedef struct { short max_masters_of_online_angels; short min_masters_of_active_angels; short max_masters_of_active_angels; + short my_index; + short my_active_index; short my_active_masters; } angel_beats_report ; diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h index 476a31d3..97afc698 100644 --- a/pttbbs/include/proto.h +++ b/pttbbs/include/proto.h @@ -35,6 +35,7 @@ int a_angelmsg(void); int a_angelreport(void); int a_angelreload(void); int angel_reject_me(userinfo_t * uin); +void angel_notify_activity(void); void CallAngel(void); void angel_toggle_pause(); void angel_load_my_fullnick(char *buf, int szbuf); // full nick! diff --git a/pttbbs/mbbsd/angel.c b/pttbbs/mbbsd/angel.c index 846c4f9a..04229b51 100644 --- a/pttbbs/mbbsd/angel.c +++ b/pttbbs/mbbsd/angel.c @@ -44,6 +44,21 @@ angel_beats_do_request(int op, int master_uid, int angel_uid) { // Local Angel Service void +angel_notify_activity() { + static time4_t t = 0; + time4_t tick = now; + + // tick: every 15 minutes. + tick -= tick % (15 * 60 * 60); + + // ping daemon only in different ticks. + if (tick == t) + return; + t = tick; + angel_beats_do_request(ANGELBEATS_REQ_HEARTBEAT, 0, usernum); +} + +void angel_toggle_pause() { // TODO record angels that don't do their job @@ -158,30 +173,58 @@ angel_get_nick() return _myangel_nick; } -int -a_changeangel(){ +static int +do_changeangel(int force) { char buf[4]; + static time_t last_time = 0; + const char *prompt = "登記完成,下次呼叫時會從上線的天使中選出新的小天使"; /* cuser.myangel == "-" means banned for calling angel */ - if (cuser.myangel[0] == '-') return 0; + if (cuser.myangel[0] == '-') + return 0; + + if (!cuser.myangel[0]) { + vmsg(prompt); + return 0; + } + + // TODO Allow changing only if user really tried to contact angel. +#ifdef ANGEL_CHANGE_TIMELIMIT_MINS + if (force) + last_time = 0; + if (last_time && + (now - last_time < ANGEL_CHANGE_TIMELIMIT_MINS * 60)) { + vmsgf("每次更換小天使最少間隔 %d 分鐘。", + ANGEL_CHANGE_TIMELIMIT_MINS); + return 0; + } + +#endif + + mvouts(b_lines - 3, 0, "\n" + "請注意若未呼叫過目前的小天使就申請更換,很可能會再換到同個天使\n"); getdata(b_lines - 1, 0, "更換小天使後就無法換回了喔! 是否要更換小天使? [y/N]", buf, 3, LCECHO); if (buf[0] == 'y') { - char buf[100]; - snprintf(buf, sizeof(buf), "%s 小主人 %s 換掉 %s 小天使\n", - Cdatelite(&now), cuser.userid, cuser.myangel); - log_file(BBSHOME "/log/changeangel.log", LOG_CREAT, buf); + log_filef(BBSHOME "/log/changeangel.log",LOG_CREAT, + "%s 小主人 %s 換掉 %s 小天使\n", + Cdatelite(&now), cuser.userid, cuser.myangel); if (cuser.myangel[0]) angel_beats_do_request(ANGELBEATS_REQ_REMOVE_LINK, usernum, searchuser(cuser.myangel, NULL)); pwcuSetMyAngel(""); - vmsg("小天使登記完成,下次呼叫時會從目前上線的天使中選出新的小天使"); + last_time = now; + vmsg(prompt); } return 0; } +int a_changeangel(void) { + return do_changeangel(0); +} + int a_angelmsg(){ char msg[3][75] = { "", "", "" }; @@ -315,8 +358,12 @@ int a_angelreport() { rpt.max_masters_of_active_angels/base2); } - if (HasUserPerm(PERM_ANGEL)) + if (HasUserPerm(PERM_ANGEL)) { + if (currutmp->angelpause == ANGELPAUSE_NONE) + prints("\n\t 您的線上小天使順位為 %d, 全部小天使順位為 %d\n", + rpt.my_active_index, rpt.my_index); prints("\n\t 您目前大約有 %d 位小主人。\n", rpt.my_active_masters); + } } close(fd); pressanykey(); @@ -507,7 +554,7 @@ AngelNotOnline(){ "其它任意鍵離開"))) { case 'h': move(b_lines - 4, 0); clrtobot(); - a_changeangel(); + do_changeangel(1); break; #ifdef BN_NEWBIE case 'p': @@ -590,8 +637,9 @@ TalkToAngel(){ snprintf(xnick, sizeof(xnick), "%s小天使", _myangel_nick); snprintf(prompt, sizeof(prompt), "問%s小天使: ", _myangel_nick); // if success, record uent. - if (my_write(uent->pid, prompt, xnick, WATERBALL_ANGEL, uent)) + if (my_write(uent->pid, prompt, xnick, WATERBALL_ANGEL, uent)) { lastuent = uent; + } } return; } diff --git a/pttbbs/mbbsd/mbbsd.c b/pttbbs/mbbsd/mbbsd.c index 5761d21a..cdca0ac4 100644 --- a/pttbbs/mbbsd/mbbsd.c +++ b/pttbbs/mbbsd/mbbsd.c @@ -53,7 +53,6 @@ struct ProgramOption { int flag_listenfd; char* flag_tunnel_path; - bool flag_bypass; bool flag_fork; bool flag_checkload; char flag_user[IDLEN+1]; @@ -400,12 +399,15 @@ show_call_in(int save, int which) int mode = currutmp->msgs[which].msgmode; #ifdef PLAY_ANGEL - if (mode == MSGMODE_TOANGEL) + if (mode == MSGMODE_TOANGEL) { snprintf(buf, sizeof(buf), ANSI_COLOR(1;37;46) "★%s" ANSI_COLOR(37;45) " %s " ANSI_RESET, currutmp->msgs[which].userid, currutmp->msgs[which].last_call_in); - else + // I must be an Angel. Let's try to update angel beats info. + // TODO maybe it's better to move this to "sender". + angel_notify_activity(); + } else #endif snprintf(buf, sizeof(buf), ANSI_COLOR(1;33;46) "★%s" ANSI_COLOR(37;45) " %s " ANSI_RESET, currutmp->msgs[which].userid, @@ -1533,8 +1535,7 @@ static void usage(char *argv0) "non-daemon mode\n" "\t-D use non-daemon mode, imply -t tty\n" "\t-h hostip hostip (default 127.0.0.1)\n" - "\t-b bypass opening and ask password directly\n" - "\t-u user for -b: user (default guest)\n" + "\t-u user login as user directly without pw\n" "\n" "flags\n" "\t-t type terminal mode, telnet | tty\n" @@ -1677,12 +1678,6 @@ bool parse_argv(int argc, char *argv[], struct ProgramOption *option) } #endif break; - case 'b': - option->flag_bypass = true; - // TODO - fprintf(stderr, "not yet implemented\n"); - exit(1); - break; case 'u': strlcpy(option->flag_user, optarg, sizeof(option->flag_user)); break; diff --git a/pttbbs/mbbsd/user.c b/pttbbs/mbbsd/user.c index 6d3a857c..8eefd4e2 100644 --- a/pttbbs/mbbsd/user.c +++ b/pttbbs/mbbsd/user.c @@ -1208,7 +1208,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) post_change_perm(changefrom, x.userlevel, cuser.userid, x.userid); #ifdef PLAY_ANGEL if (x.userlevel & ~changefrom & PERM_ANGEL) - mail_id(x.userid, "翅膀長出來了!", "etc/angel_notify", "[上帝]"); + mail_id(x.userid, "翅膀長出來了!", "etc/angel_notify", "[天使公會]"); #endif } |