summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cacheserver/utmpserver.c150
-rw-r--r--mbbsd/mbbsd.c3
-rw-r--r--sample/pttbbs.conf7
3 files changed, 119 insertions, 41 deletions
diff --git a/cacheserver/utmpserver.c b/cacheserver/utmpserver.c
index 2fb3f7ab..05a5ccfd 100644
--- a/cacheserver/utmpserver.c
+++ b/cacheserver/utmpserver.c
@@ -9,6 +9,23 @@ struct {
int reject[MAX_REJECT];
} utmp[USHM_SIZE];
+#ifdef NOFLOODING
+#define MAXWAIT 1024
+#define FLUSHTIME (3600*6)
+
+struct {
+ time_t lasttime;
+ int count;
+} flooding[MAX_USERS];
+
+int nWaits, lastflushtime;
+struct {
+ int uid;
+ int fd;
+ int index;
+} waitqueue[MAXWAIT];
+#endif /* NOFLOODING */
+
inline int countarray(int *s, int max)
{
int i;
@@ -68,11 +85,70 @@ void initdata(int index)
sizeof(int), qsort_intcompar);
}
+inline void syncutmp(int cfd)
+{
+ int nSynced = 0, i;
+ for( i = 0 ; i < USHM_SIZE ; ++i, ++nSynced )
+ if( toread(cfd, &utmp[i].uid, sizeof(utmp[i].uid)) > 0 &&
+ toread(cfd, utmp[i].friend, sizeof(utmp[i].friend)) > 0 &&
+ toread(cfd, utmp[i].reject, sizeof(utmp[i].reject)) > 0 ){
+ if( utmp[i].uid )
+ initdata(i);
+ }
+ else
+ for( ; i < USHM_SIZE ; ++i )
+ utmp[i].uid = 0;
+ close(cfd);
+ fprintf(stderr, "%d users synced\n", nSynced);
+}
+
+void processlogin(int cfd, int uid, int index)
+{
+ if( toread(cfd, utmp[index].friend, sizeof(utmp[index].friend)) > 0 &&
+ toread(cfd, utmp[index].reject, sizeof(utmp[index].reject)) > 0 ){
+ /* 因為 logout 的時候並不會通知 utmpserver , 可能會查到一些
+ 已經 logout 的帳號。所以不能只取 MAX_FRIEND 而要多取一些 */
+#define MAX_FS (2 * MAX_FRIEND)
+ int iu, nFrs, stat, rstat;
+ ocfs_t fs[MAX_FS];
+
+ utmp[index].uid = uid;
+ initdata(index);
+
+ for( nFrs = iu = 0 ; iu < USHM_SIZE && nFrs < MAX_FS ; ++iu )
+ if( iu != index && utmp[iu].uid ){
+ if( (stat = set_friend_bit(index, iu)) ){
+ rstat = reverse_friend_stat(stat);
+ fs[nFrs].index = iu;
+ fs[nFrs].uid = utmp[iu].uid;
+ fs[nFrs].friendstat = (stat << 24) + iu;
+ fs[nFrs].rfriendstat = (rstat << 24) + index;
+ ++nFrs;
+ }
+ }
+
+ towrite(cfd, &fs, sizeof(ocfs_t) * nFrs);
+ }
+ close(cfd);
+}
+
+#ifdef NOFLOODING
+void flushwaitqueue(void)
+{
+ int i;
+ for( i = 0 ; i < nWaits ; ++i )
+ processlogin(waitqueue[i].fd, waitqueue[i].uid, waitqueue[i].index);
+ lastflushtime = time(NULL);
+ nWaits = 0;
+ memset(flooding, 0, sizeof(flooding));
+}
+#endif
+
/* XXX 具有被 DoS 的可能, 請用 firewall 之類擋起來 */
int main(int argc, char **argv)
{
struct sockaddr_in clientaddr;
- int ch, port = 5120, sfd, cfd, len, index, i, uid;
+ int ch, port = 5120, sfd, cfd, len, index, uid;
char *iface_ip = NULL;
while( (ch = getopt(argc, argv, "p:i:h")) != -1 )
@@ -92,7 +168,15 @@ int main(int argc, char **argv)
if( (sfd = tobind(iface_ip, port)) < 0 )
return 1;
+#ifdef NOFLOODING
+ lastflushtime = time(NULL);
+#endif
while( 1 ){
+#ifdef NOFLOODING
+ if( lastflushtime < (time(NULL) - 1800) )
+ flushwaitqueue();
+#endif
+
len = sizeof(clientaddr);
if( (cfd = accept(sfd, (struct sockaddr *)&clientaddr, &len)) < 0 ){
if( errno != EINTR )
@@ -101,49 +185,35 @@ int main(int argc, char **argv)
}
toread(cfd, &index, sizeof(index));
if( index == -1 ){
- int nSynced = 0;
- for( i = 0 ; i < USHM_SIZE ; ++i, ++nSynced )
- if( toread(cfd, &utmp[i].uid, sizeof(utmp[i].uid)) > 0 &&
- toread(cfd, utmp[i].friend, sizeof(utmp[i].friend)) > 0 &&
- toread(cfd, utmp[i].reject, sizeof(utmp[i].reject)) > 0 ){
- if( utmp[i].uid )
- initdata(i);
- }
- else
- for( ; i < USHM_SIZE ; ++i )
- utmp[i].uid = 0;
- close(cfd);
- fprintf(stderr, "%d users synced\n", nSynced);
+ syncutmp(cfd);
continue;
}
- if( toread(cfd, &uid, sizeof(uid)) > 0 &&
- toread(cfd, utmp[index].friend, sizeof(utmp[index].friend)) > 0 &&
- toread(cfd, utmp[index].reject, sizeof(utmp[index].reject)) > 0 ){
- /* 因為 logout 的時候並不會通知 utmpserver , 可能會查到一些
- 已經 logout 的帳號。所以不能只取 MAX_FRIEND 而要多取一些 */
-#define MAX_FS (2 * MAX_FRIEND)
- int iu, nFrs, stat, rstat;
- ocfs_t fs[MAX_FS];
-
- utmp[index].uid = uid;
- initdata(index);
-
- for( nFrs = iu = 0 ; iu < USHM_SIZE && nFrs < MAX_FS ; ++iu )
- if( iu != index && utmp[iu].uid ){
- if( (stat = set_friend_bit(index, iu)) ){
- rstat = reverse_friend_stat(stat);
- fs[nFrs].index = iu;
- fs[nFrs].uid = utmp[iu].uid;
- fs[nFrs].friendstat = (stat << 24) + iu;
- fs[nFrs].rfriendstat = (rstat << 24) + index;
- ++nFrs;
- }
- }
-
- towrite(cfd, &fs, sizeof(ocfs_t) * nFrs);
+ if( toread(cfd, &uid, sizeof(uid)) > 0 ){
+ if( !(0 < uid || uid > MAX_USERS) ){ /* for safety */
+ close(cfd);
+ continue;
+ }
+
+#ifdef NOFLOODING
+ if( (time(NULL) - flooding[uid].lasttime) < 20 )
+ ++flooding[uid].count;
+ if( flooding[uid].count > 10 ){
+ if( nWaits == MAXWAIT )
+ flushwaitqueue();
+ waitqueue[nWaits].uid = uid;
+ waitqueue[nWaits].index = index;
+ waitqueue[nWaits].fd = cfd;
+ ++nWaits;
+
+ continue;
+ }
+ flooding[uid].lasttime = time(NULL);
+#endif
+
+ /* cfd will be closed in processlogin() */
+ processlogin(cfd, uid, index);
}
- close(cfd);
}
return 0;
}
diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c
index cc8afba3..92377e37 100644
--- a/mbbsd/mbbsd.c
+++ b/mbbsd/mbbsd.c
@@ -819,7 +819,8 @@ setup_utmp(int mode)
if (!(cuser.numlogins % 20) && cuser.userlevel & PERM_BM)
check_BM(); /* Ptt 自動取下離職板主權力 */
#ifndef _BBS_UTIL_C_
- friend_load(0);
+ if( strcmp(cuser.userid, STR_GUEST) != 0 ) // guest 不處理好友
+ friend_load(0);
nice(3);
#endif
}
diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf
index 3410610c..e3a3a68e 100644
--- a/sample/pttbbs.conf
+++ b/sample/pttbbs.conf
@@ -168,6 +168,13 @@
/* 如果 time_t 是 8 bytes的話 (如 X86_64) */
//#define TIMET64
+/* 使用 cacheserver, 在外部運算好友資料, 如果您確定這個在做什麼才開啟 */
+//#define OUTTACACHE
+//#define OUTTACACHEHOST "192.168.0.1"
+//#define OUTTACACHEPORT 5120
+/* 在 cacheserver 上面擋掉狂上下站的使用者 */
+//#define NOFLOODING
+
/* 前進站畫面 */
#define INSCREEN \
"前進站畫面 (請至 pttbbs.conf 修改您的前進站畫面)"