summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pttbbs/daemon/angelbeats/abc.c4
-rw-r--r--pttbbs/daemon/angelbeats/angelbeats.c123
-rw-r--r--pttbbs/include/daemons.h3
-rw-r--r--pttbbs/include/proto.h1
-rw-r--r--pttbbs/mbbsd/angel.c70
-rw-r--r--pttbbs/mbbsd/mbbsd.c17
-rw-r--r--pttbbs/mbbsd/user.c2
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
}