diff options
-rw-r--r-- | cacheserver/Makefile | 14 | ||||
-rw-r--r-- | cacheserver/README | 1 | ||||
-rw-r--r-- | cacheserver/utmpserver.c | 143 | ||||
-rw-r--r-- | cacheserver/utmpsync.c | 27 | ||||
-rw-r--r-- | include/proto.h | 8 | ||||
-rw-r--r-- | include/pttstruct.h | 10 | ||||
-rw-r--r-- | mbbsd/cal.c | 7 | ||||
-rw-r--r-- | mbbsd/stuff.c | 69 | ||||
-rw-r--r-- | mbbsd/talk.c | 25 |
9 files changed, 299 insertions, 5 deletions
diff --git a/cacheserver/Makefile b/cacheserver/Makefile new file mode 100644 index 00000000..42b077b4 --- /dev/null +++ b/cacheserver/Makefile @@ -0,0 +1,14 @@ +# $Id$ +.include "../pttbbs.mk" + +PROGRAMS= utmpserver utmpsync + +all: ${PROGRAMS} + +.for fn in ${PROGRAMS} +${fn}: ${fn}.c + ${CC} ${CFLAGS} ${LDFLAGS} -DPTTBBS_UTIL -o ${fn} ${fn}.c ../util/util_*.o +.endfor + +clean: + rm -f *~ ${PROGRAMS} diff --git a/cacheserver/README b/cacheserver/README new file mode 100644 index 00000000..3bfeddbc --- /dev/null +++ b/cacheserver/README @@ -0,0 +1 @@ +這是一個測試的東西. 除非確定你知道這個程式在幹什麼, 否則請不理會這個目錄 :P diff --git a/cacheserver/utmpserver.c b/cacheserver/utmpserver.c new file mode 100644 index 00000000..60cd02ad --- /dev/null +++ b/cacheserver/utmpserver.c @@ -0,0 +1,143 @@ +/* $Id$ */ +#include "bbs.h" +#include <err.h> + +struct { + int uid; + int nFriends, nRejects; + int friend[MAX_FRIEND]; + int reject[MAX_REJECT]; +} utmp[USHM_SIZE]; + +inline int countarray(int *s, int max) +{ + int i; + for( i = 0 ; i < max && s[i] ; ++i ) + ; + return i; +} + +int +reverse_friend_stat(int stat) +{ + int stat1 = 0; + if (stat & IFH) + stat1 |= HFM; + if (stat & IRH) + stat1 |= HRM; + if (stat & HFM) + stat1 |= IFH; + if (stat & HRM) + stat1 |= IRH; + if (stat & IBH) + stat1 |= IBH; + return stat1; +} + +int set_friend_bit(int me, int ui) +{ + int hit = 0; + /* 判斷對方是否為我的朋友 ? */ + if( intbsearch(utmp[ui].uid, utmp[me].friend, utmp[me].nFriends) ) + hit = IFH; + + /* 判斷我是否為對方的朋友 ? */ + if( intbsearch(utmp[me].uid, utmp[ui].friend, utmp[ui].nFriends) ) + hit |= HFM; + + /* 判斷對方是否為我的仇人 ? */ + if( intbsearch(utmp[ui].uid, utmp[me].reject, utmp[me].nRejects) ) + hit |= IRH; + + /* 判斷我是否為對方的仇人 ? */ + if( intbsearch(utmp[me].uid, utmp[ui].reject, utmp[ui].nRejects) ) + hit |= HRM; + + return hit; +} + +void initdata(int index) +{ + utmp[index].nFriends = countarray(utmp[index].friend, MAX_FRIEND); + utmp[index].nRejects = countarray(utmp[index].reject, MAX_REJECT); + if( utmp[index].nFriends > 0 ) + qsort(utmp[index].friend, utmp[index].nFriends, + sizeof(int), qsort_intcompar); + if( utmp[index].nRejects > 0 ) + qsort(utmp[index].reject, utmp[index].nRejects, + sizeof(int), qsort_intcompar); +} + +int main(int argc, char **argv) +{ + struct sockaddr_in clientaddr; + int ch, port = 5120, sfd, cfd, len, index, i, uid; + + while( (ch = getopt(argc, argv, "p:h")) != -1 ) + switch( ch ){ + case 'p': + port = atoi(optarg); + break; + + case 'h': + default: + fprintf(stderr, "usage: utmpserver [-p port]\n"); + return 1; + } + + if( (sfd = tobind(port)) < 0 ) + return 1; + + while( 1 ){ + len = sizeof(clientaddr); + if( (cfd = accept(sfd, (struct sockaddr *)&clientaddr, &len)) < 0 ){ + if( errno != EINTR ) + sleep(1); + continue; + } + 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); + 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 ){ +#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); + } + return 0; +} diff --git a/cacheserver/utmpsync.c b/cacheserver/utmpsync.c new file mode 100644 index 00000000..13ffcf4e --- /dev/null +++ b/cacheserver/utmpsync.c @@ -0,0 +1,27 @@ +/* $Id$ */ +#include "bbs.h" +#include <err.h> + +extern SHM_t *SHM; +int towrite(int fd, void *buf, int len); +int toconnect(char *host, int port); + +int main(int argc, char **argv) +{ + int sfd, index, i; + attach_SHM(); + if( (sfd = toconnect(OUTTACACHEHOST, OUTTACACHEPORT)) < 0 ) + return 1; + + index = -1; + towrite(sfd, &index, sizeof(index)); + for( i = 0 ; i < USHM_SIZE ; ++i ) + if( towrite(sfd, &SHM->uinfo[i].uid, sizeof(SHM->uinfo[i].uid)) < 0 || + towrite(sfd, SHM->uinfo[i].friend, + sizeof(SHM->uinfo[i].friend)) < 0 || + towrite(sfd, SHM->uinfo[i].reject, + sizeof(SHM->uinfo[i].reject)) < 0 ){ + fprintf(stderr, "sync error %d\n", i); + } + return 0; +} diff --git a/include/proto.h b/include/proto.h index 2828a196..9851a9e0 100644 --- a/include/proto.h +++ b/include/proto.h @@ -523,6 +523,12 @@ int qsort_intcompar(const void *a, const void *b); void *MALLOC(int size); void FREE(void *ptr); #endif +#ifdef OUTTACACHE +int tobind(int port); +int toconnect(char *host, int port); +int toread(int fd, void *buf, int len); +int towrite(int fd, void *buf, int len); +#endif /* syspost */ int post_msg(char* bname, char* title, char *msg, char* author); @@ -559,7 +565,7 @@ int t_talk(); int t_display(); int my_query(char *uident); int logout_friend_online(); -int login_friend_online(); +void login_friend_online(); int isvisible_uid(int tuid); int friend_stat(userinfo_t *me, userinfo_t * ui); int call_in(userinfo_t *uentp, int fri_stat); diff --git a/include/pttstruct.h b/include/pttstruct.h index 9f950c92..5895c31d 100644 --- a/include/pttstruct.h +++ b/include/pttstruct.h @@ -477,4 +477,14 @@ typedef struct time_t chrono; int recno; } TagItem; + +#ifdef OUTTACACHE +typedef struct { + int index; // 在 SHM->uinfo[index] + int uid; // 避免在 cache server 上不同步, 再確認用. + int friendstat; + int rfriendstat; +} ocfs_t; +#endif + #endif diff --git a/mbbsd/cal.c b/mbbsd/cal.c index 462818de..43c0d2f5 100644 --- a/mbbsd/cal.c +++ b/mbbsd/cal.c @@ -431,9 +431,14 @@ p_sysinfo(void) prints("記憶體用量: sbrk: %d KB, idrss: %d KB, isrss: %d KB\n", ((int)sbrk(0) - 0x8048000) / 1024, (int)ru.ru_idrss, (int)ru.ru_isrss); + prints("特別參數:" #ifdef CRITICAL_MEMORY - prints("目前在 CRITICAL_MEMORY 模式下\n"); + " CRITICAL_MEMORY" #endif +#ifdef OUTTACACHE + " OUTTACACHE" +#endif + ); } pressanykey(); return 0; diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c index 767fdca1..008f18f9 100644 --- a/mbbsd/stuff.c +++ b/mbbsd/stuff.c @@ -694,3 +694,72 @@ int qsort_intcompar(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +#ifdef OUTTACACHE +#include <err.h> +int tobind(int port) +{ + int sockfd, val; + struct sockaddr_in servaddr; + + if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) + err(1, NULL); + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&val, sizeof(val)); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(port); + if( bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) + err(1, NULL); + if( listen(sockfd, 5) < 0 ) + err(1, NULL); + + return sockfd; +} + +int toconnect(char *host, int port) +{ + int sock; + struct sockaddr_in serv_name; + if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ + perror("socket"); + return -1; + } + + serv_name.sin_family = AF_INET; + serv_name.sin_addr.s_addr = inet_addr(host); + serv_name.sin_port = htons(port); + if( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ){ + close(sock); + return -1; + } + return sock; +} + +int toread(int fd, void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = read(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} + +int towrite(int fd, void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = write(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} +#endif diff --git a/mbbsd/talk.c b/mbbsd/talk.c index 8052ae5a..23a5a305 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -210,12 +210,31 @@ reverse_friend_stat(int stat) return stat1; } -int -login_friend_online(void) +void login_friend_online(void) { userinfo_t *uentp; int i, stat, stat1; int offset = (int)(currutmp - &SHM->uinfo[0]); +#ifdef OUTTACACHE + int sfd; + if( (sfd = toconnect(OUTTACACHEHOST, OUTTACACHEPORT)) > 0 ){ + if( towrite(sfd, &offset, sizeof(offset)) > 0 && + towrite(sfd, &currutmp->uid, sizeof(currutmp->uid)) > 0 && + towrite(sfd, currutmp->friend, sizeof(currutmp->friend)) > 0 && + towrite(sfd, currutmp->reject, sizeof(currutmp->reject)) > 0 ){ + ocfs_t fs; + while( toread(sfd, &fs, sizeof(fs)) > 0 ) + if( SHM->uinfo[fs.index].uid == fs.uid ){ + currutmp->friend_online[currutmp->friendtotal++] + = fs.friendstat; + SHM->uinfo[fs.index].friend_online[ SHM->uinfo[fs.index].friendtotal++ ] = fs.rfriendstat; + } + close(sfd); + return; + } + close(sfd); + } +#endif for (i = 0; i < SHM->UTMPnumber && currutmp->friendtotal < MAX_FRIEND; i++) { uentp = (SHM->sorted[SHM->currsorted][0][i]); if (uentp && uentp->uid && (stat = set_friend_bit(currutmp, uentp))) { @@ -230,7 +249,7 @@ login_friend_online(void) } } } - return 0; + return; } int |