diff options
Diffstat (limited to 'cacheserver')
-rw-r--r-- | cacheserver/Makefile | 30 | ||||
-rw-r--r-- | cacheserver/README | 1 | ||||
-rw-r--r-- | cacheserver/authserver.c | 236 | ||||
-rw-r--r-- | cacheserver/friend.cpp | 350 | ||||
-rw-r--r-- | cacheserver/utmpserver.c | 222 | ||||
-rw-r--r-- | cacheserver/utmpserver2.c | 290 | ||||
-rw-r--r-- | cacheserver/utmpserver3.c | 341 | ||||
-rw-r--r-- | cacheserver/utmpsync.c | 27 |
8 files changed, 0 insertions, 1497 deletions
diff --git a/cacheserver/Makefile b/cacheserver/Makefile deleted file mode 100644 index bdff3f08..00000000 --- a/cacheserver/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# $Id$ -SRCROOT= .. -.include "$(SRCROOT)/pttbbs.mk" - -PROGRAMS= utmpserver utmpsync utmpserver2 utmpserver3 authserver -UTILDIR= $(SRCROOT)/util -UTILOBJ= $(UTILDIR)/util_stuff.o $(UTILDIR)/util_var.o $(UTILDIR)/util_file.o $(UTILDIR)/util_cache.o $(UTILDIR)/util_passwd.o $(UTILDIR)/util_record.o $(UTILDIR)/util_osdep.o $(UTILDIR)/util_args.o - -all: ${PROGRAMS} - -.SUFFIXES: .c .cpp .o -.c.o: - $(CCACHE) $(CC) $(CFLAGS) -c $*.c -.cpp.o: - $(CCACHE) $(CXX) $(CFLAGS) -c $*.cpp - -utmpserver: utmpserver.o $(UTILOBJ) - ${CC} ${CFLAGS} ${LDFLAGS} -o $* $*.o $(UTILOBJ) -utmpserver2: utmpserver2.o friend.o $(UTILOBJ) - ${CXX} ${CFLAGS} ${LDFLAGS} -o $* $*.o $(UTILOBJ) friend.o -utmpserver3: utmpserver3.o friend.o $(UTILOBJ) - ${CXX} ${CFLAGS} ${LDFLAGS} -levent -o $* $*.o $(UTILOBJ) friend.o -utmpsync: utmpsync.o $(UTILOBJ) - ${CC} ${CFLAGS} ${LDFLAGS} -o $* $*.o $(UTILOBJ) - -authserver: authserver.o $(UTILOBJ) - ${CC} ${CFLAGS} ${LDFLAGS} -lcrypt -levent -o $* $> - -clean: - rm -f *~ ${PROGRAMS} friend.o utmpserver.o utmpserver2.o utmpserver3.o utmpsync.o authserver.o diff --git a/cacheserver/README b/cacheserver/README deleted file mode 100644 index 3bfeddbc..00000000 --- a/cacheserver/README +++ /dev/null @@ -1 +0,0 @@ -這是一個測試的東西. 除非確定你知道這個程式在幹什麼, 否則請不理會這個目錄 :P diff --git a/cacheserver/authserver.c b/cacheserver/authserver.c deleted file mode 100644 index 5fbba03a..00000000 --- a/cacheserver/authserver.c +++ /dev/null @@ -1,236 +0,0 @@ -/* $Id$ */ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> - -#include <event.h> - -#include "bbs.h" - -struct timeval tv = {5, 0}; -struct event ev; -int clients = 0; - -#define READ_BLOCK 256 -#define MAX_CLIENTS 10 - -#define AUTH_PASSWDS BBSHOME "/.AUTH_PASSWDS" -#define ENTRY_SIZE 64 - -struct client_state { - struct event ev; - int state; - int uid; - int len; - int response; - struct evbuffer *evb; -}; - -enum { - FSM_ENTER, - FSM_AUTH, - FSM_SETPASSWD, - FSM_RESPOND, - FSM_EXIT -}; - -/** - * 瑼X亙蝣 - * @return 1 - 撖蝣潮航炊, 0 - 撖蝣潭迤蝣 - */ -int check_passwd(int uid, char *passwd) -{ - char buf[ENTRY_SIZE]; - int i, result = 1; - - if ((i = open(AUTH_PASSWDS, O_WRONLY)) < 0) - return result; - - if (lseek(i, uid * ENTRY_SIZE, SEEK_SET) < 0) - goto end; - - if (read(i, buf, ENTRY_SIZE) < ENTRY_SIZE) - goto end; - - if (!strcmp(buf, crypt(passwd, buf))) - result = 0; -end: - memset(buf, 0, ENTRY_SIZE); - close(i); - return result; -} - -/** - * 閮剖啣蝣 - * DES crypt 撠勗末 - */ -void set_passwd(int uid, char *passwd) -{ - char buf[ENTRY_SIZE]; - char saltc[3], c; - int i; - - i = 9 * random(); - saltc[0] = i & 077; - saltc[1] = (i >> 6) & 077; - - for (i = 0; i < 2; i++) { - c = saltc[i] + '.'; - if (c > '9') - c += 7; - if (c > 'Z') - c += 6; - saltc[i] = c; - } - saltc[2] = '\0'; - - memset(buf, 0, sizeof(buf)); - strlcpy(buf, crypt(passwd, saltc), sizeof(buf)); - - if ((i = open(AUTH_PASSWDS, O_WRONLY)) < 0) - return; - - if (lseek(i, uid * ENTRY_SIZE, SEEK_SET) < 0) - goto close; - write(i, buf, ENTRY_SIZE); -close: - close(i); -} - -void connection_client(int cfd, short event, void *arg) -{ - struct client_state *cs = arg; - int cmd; - static char buf[128]; - - // ignore clients that timeout - if (event & EV_TIMEOUT) - cs->state = FSM_EXIT; - - if (event & EV_READ) { - if (evbuffer_read(cs->evb, cfd, READ_BLOCK) < 0) - cs->state = FSM_EXIT; - } - - while (1) { - switch (cs->state) { - case FSM_ENTER: - if (EVBUFFER_LENGTH(cs->evb) < sizeof(int)) - goto break_out; - evbuffer_remove(cs->evb, &cmd, sizeof(cmd)); - cs->state = FSM_AUTH; - - case FSM_AUTH: - if (EVBUFFER_LENGTH(cs->evb) < sizeof(int) * 2) - goto break_out; - - evbuffer_remove(cs->evb, &cs->uid, sizeof(cs->uid)); - evbuffer_remove(cs->evb, &cs->len, sizeof(cs->len)); - if (EVBUFFER_LENGTH(cs->evb) < cs->len) - goto break_out; - - memset(buf, 0, sizeof(buf)); - evbuffer_remove(cs->evb, buf, cs->len); - cs->response = check_passwd(cs->uid, buf); - memset(buf, 0, sizeof(buf)); - - if (cmd == 2) - cs->state = FSM_SETPASSWD; - else { - cs->state = FSM_RESPOND; - goto break_out; - } - - case FSM_SETPASSWD: - if (EVBUFFER_LENGTH(cs->evb) < sizeof(int)) - goto break_out; - - evbuffer_remove(cs->evb, &cs->len, sizeof(cs->len)); - if (EVBUFFER_LENGTH(cs->evb) < cs->len) - goto break_out; - - memset(buf, 0, sizeof(buf)); - evbuffer_remove(cs->evb, buf, cs->len); - set_passwd(cs->uid, buf); - memset(buf, 0, sizeof(buf)); - - cs->state = FSM_RESPOND; - goto break_out; - - case FSM_RESPOND: - write(cfd, &cs->response, sizeof(cs->response)); - cs->state = FSM_EXIT; - - case FSM_EXIT: - if (clients == MAX_CLIENTS) - event_add(&ev, NULL); - close(cfd); - evbuffer_free(cs->evb); - free(cs); - clients--; - return; - } - } - -break_out: - if (cs->state == FSM_RESPOND) - event_set(&cs->ev, cfd, EV_WRITE, (void *) connection_client, cs); - event_add(&cs->ev, &tv); -} - -void connection_accept(int fd, short event, void *arg) -{ - struct sockaddr_in clientaddr; - socklen_t len = sizeof(clientaddr); - int cfd; - - if ((cfd = accept(fd, (struct sockaddr *)&clientaddr, &len)) < 0 ) - return; - - fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0) | O_NONBLOCK); - - struct client_state *cs = calloc(1, sizeof(struct client_state)); - cs->state = 0; - cs->evb = evbuffer_new(); - - event_set(&cs->ev, cfd, EV_READ, (void *) connection_client, cs); - event_add(&cs->ev, &tv); - clients++; - - if (clients > MAX_CLIENTS) - event_del(&ev); -} - -int main(int argc, char *argv[]) -{ - int ch, port = 5121, sfd; - char *iface_ip = NULL; - - Signal(SIGPIPE, SIG_IGN); - while( (ch = getopt(argc, argv, "p:i:h")) != -1 ) - switch( ch ){ - case 'p': - port = atoi(optarg); - break; - case 'i': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: authserver [-i interface_ip] [-p port]\n"); - return 1; - } - - if( (sfd = tobind(iface_ip, port)) < 0 ) - return 1; - - srandom(getpid() + time(NULL)); - event_init(); - event_set(&ev, sfd, EV_READ | EV_PERSIST, connection_accept, &ev); - event_add(&ev, NULL); - event_dispatch(); - return 0; -} diff --git a/cacheserver/friend.cpp b/cacheserver/friend.cpp deleted file mode 100644 index e62a7198..00000000 --- a/cacheserver/friend.cpp +++ /dev/null @@ -1,350 +0,0 @@ -#define NDEBUG -#include <algorithm> -#include <cassert> - -// for some constant and type -#include "bbs.h" - -/* for each login of user, - * input: my index, friend[MAX_FRIEND] of uid, reject[MAX_REJECT] of uid, - * for all my relation, - * output: his index, his uid, relation to me, relation to him - */ -/* 支 user utmp 銋憭, 券函 ref index 賣舫, 蝣箔 insert & delete O(1) */ -/* 嗆鈭 refer resource recycle */ - -typedef int Uid; -typedef int Idx; - - -struct Relation { - Uid him; - short him_offset; - - Relation(Uid _him, short _him_offset=-1) :him(_him),him_offset(_him_offset) {} -}; - -template<class T> -struct freelist { - static const int KEEP = 64; - static T* list[8][KEEP]; // 2^0~2^7 - static int tail[8]; - -#define IS_2xxN(a) (a && (a&(a-1))==0) - static T* alloc(int n) { - assert(n>0); - if(n<256 && IS_2xxN(n) && sizeof(T)*n<65536) { - int t=n; - int slot; - for(slot=0; t>1; t/=2) - slot++; - assert(0<=slot && slot<8); - if(tail[slot]) { - return list[slot][--tail[slot]]; - } - } - return (T*)malloc(sizeof(T)*n); - } - static void free(T* p, int n) { - assert(n>0); - if(n<256 && IS_2xxN(n) && sizeof(T)*n<65536) { - int t=n; - int slot; - for(slot=0; t>1; t/=2) - slot++; - assert(0<=slot && slot<8); - if(tail[slot]<KEEP) { - list[slot][tail[slot]++]=p; - return; - } - } - ::free(p); - } -}; - -template<class T> T* freelist<T>::list[8][KEEP]; -template<class T> int freelist<T>::tail[8]={0}; - -template<class T,int MIN_ROOM = 8, class S = int> -struct myvector { - // 憭扯港唾 STL vector, 雿 STL capacity 芣憓銝蝮桀 - // (敺靘潛, 隞 online friend 靘隤, capacity 銝蝮桀嗅祕瘝隞暻澆蔣) - // 甇文, pointer 64bit 璈其閬 8bytes, basic overhead 8*3 bytes, - // 雿鞈瘝暻澆之, 寧 S(int or short) 摮 size & capacity 瘥頛 - T *base; - S room, n; - - myvector() :base(0),room(0),n(0) {} - ~myvector() { - clear(); - } - S append(T data) { - if(room<n+1) - resizefor(n+1); - base[n++]=data; - return n-1; - } - void pop_back() { - assert(n>0); - n--; - resizefor(n); - } - void clear() { - n=0; - resizefor(n); - } - /* - T& operator[](int idx) { - return base[idx]; - } - */ - - void resizefor(S size) { - assert(size>=n); - if(size==0) { - if(base) freelist<T>::free(base, room); - base=0; - room=0; - } else { - S origroom=room; - if(room==0) - room=MIN_ROOM; - while(room<size) room=S(room*2); - if(size<MIN_ROOM) size=MIN_ROOM; - while(room/2>size) room=S(room/2); - if(room!=origroom || base==0) { - //base=(T*)realloc(base, sizeof(T)*room); - T* tmp=freelist<T>::alloc(room); - assert(tmp); - if(n>0) - memcpy(tmp, base, sizeof(T)*n); - if(base!=0) - freelist<T>::free(base, origroom); - base=tmp; - } - assert(base); - } - } -}; - -template<class R,class B> -struct RelationList: public myvector<Relation, 8, short> { - RelationList() :myvector<Relation, 8, short>() {} - void add(Uid me, Uid him) { - RelationList<B,R>& bl=R::backlist(him); - short me_offset=append(Relation(him)); - short him_offset=bl.append(Relation(me,me_offset)); - - setbackoffset(me_offset,him_offset); - assert(bl.base[him_offset].him==me); - assert(bl.base[him_offset].him_offset==me_offset); - } - void deleteall(Uid me) { - for(int i=0; i<n; i++) { - RelationList<B,R>& bl=R::backlist(base[i].him); - assert(bl.base[base[i].him_offset].him==me); - assert(bl.base[base[i].him_offset].him_offset==i); - bl.delete_half(base[i].him_offset); - //try_recycle(base[i].him); // dirty - } - clear(); - } - private: - void setbackoffset(short which,short offset) { - assert(0<=which && which<n); - base[which].him_offset=offset; - } - void delete_half(short offset) { - assert(0<=offset && offset<n); - if(offset<n-1) { - base[offset]=base[n-1]; - R::backlist(base[offset].him).setbackoffset(base[offset].him_offset,offset); - } - pop_back(); - } - friend class RelationList<B,R>; -}; - -struct Like; -struct Likeby; -struct Hate; -struct Hateby; -struct Like: public Relation { - Like(Uid _him, short _him_offset=-1) :Relation(_him,_him_offset) {} - static RelationList<Likeby,Like>& backlist(Uid him); -}; -struct Likeby: public Relation { - Likeby(Uid _him, short _him_offset=-1) :Relation(_him,_him_offset) {} - static RelationList<Like,Likeby>& backlist(Uid him); -}; -struct Hate: public Relation { - Hate(Uid _him, short _him_offset=-1) :Relation(_him,_him_offset) {} - static RelationList<Hateby,Hate>& backlist(Uid him); -}; -struct Hateby: public Relation { - Hateby(Uid _him, short _him_offset=-1) :Relation(_him,_him_offset) {} - static RelationList<Hate,Hateby>& backlist(Uid him); -}; - - -struct Utmp { - Utmp() { - for(int i=0; i<USHM_SIZE; i++) - utmp[i]=-1; - } - /* - Uid& operator[](int idx) { - return utmp[idx]; - } - */ - public: - Uid utmp[USHM_SIZE]; -}; -static Utmp utmp; - -struct BBSUser { - Uid me; - int online; - /* assume utmplist is short, so just use plain vector and linear search */ - myvector<int,2> utmplist; - - RelationList<Like,Likeby> like; - RelationList<Hate,Hateby> hate; - RelationList<Likeby,Like> likeby; - RelationList<Hateby,Hate> hateby; - - BBSUser() :me(-1),online(0),utmplist(),like(),hate(),likeby(),hateby() {} - BBSUser(Uid uid) :me(uid),online(0),utmplist(),like(),hate(),likeby(),hateby() {} - - void login(int utmpidx, const Uid likehim[MAX_FRIEND], const Uid hatehim[MAX_REJECT]) { - if(online>0) { - /* multiple login 閰, 隞交敺銝甈∠ like/hate 箸 */ - like.deleteall(me); - hate.deleteall(me); - } - utmp.utmp[utmpidx]=me; - utmplist.append(utmpidx); - online++; - assert(online==utmplist.n); - for(int i=0; i<MAX_FRIEND && likehim[i]; i++) - like.add(me, likehim[i]); - for(int i=0; i<MAX_REJECT && hatehim[i]; i++) - hate.add(me, hatehim[i]); - } - - void logout(int utmpidx) { - assert(utmp.utmp[utmpidx]==me); - assert(online==utmplist.n); - for(int i=0; i<utmplist.n; i++) - if(utmplist.base[i]==utmpidx) { - utmplist.base[i]=utmplist.base[utmplist.n-1]; - utmplist.pop_back(); - break; - } - utmp.utmp[utmpidx]=-1; - online--; - assert(online==utmplist.n); - if(online==0) { - like.deleteall(me); - hate.deleteall(me); - } - } - bool isfree() const { - return online==0 && like.n==0 && hate.n==0 && likeby.n==0 && hateby.n==0; - } -}; - -struct UserList { - BBSUser users[MAX_USERS]; - - UserList() { - for(int i=0; i<MAX_USERS; i++) - users[i].me=i; - } - void login(Uid uid, Idx idx, const Uid likehim[MAX_FRIEND], const Uid hatehim[MAX_REJECT]) { - assert(uid<MAX_USERS); - assert(idx<USHM_SIZE); - /* 望潔嗅 logout event, 甇 logout 芰潛 utmp override */ - if(utmp.utmp[idx]!=-1) users[utmp.utmp[idx]].logout(idx); - users[uid].login(idx, likehim, hatehim); - } -}; - -struct UserList userlist; -RelationList<Likeby,Like>& Like::backlist(Uid him) { return userlist.users[him].likeby; } -RelationList<Like,Likeby>& Likeby::backlist(Uid him) { return userlist.users[him].like; } -RelationList<Hateby,Hate>& Hate::backlist(Uid him) { return userlist.users[him].hateby; } -RelationList<Hate,Hateby>& Hateby::backlist(Uid him) { return userlist.users[him].hate; } - -struct Result { - Uid who; - int bits; - Result(Uid _who, int _bits) :who(_who),bits(_bits) {} - bool operator<(const Result& b) const { - return who<b.who; - } -}; - -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; - return stat1; -} - -extern "C" void utmplogin(int uid, int index, const int like[MAX_FRIEND], const int hate[MAX_REJECT]) -{ - /* login */ - userlist.login(uid, index, like, hate); -} - -extern "C" int genfriendlist(int uid, int index, ocfs_t *fs, int maxfs) -{ - /* collect data */ - BBSUser& u=userlist.users[uid]; - myvector<Result,64,short> work; - for(int i=0; i<u.like.n; i++) work.append(Result(u.like.base[i].him, IFH)); - for(int i=0; i<u.hate.n; i++) work.append(Result(u.hate.base[i].him, IRH)); - for(int i=0; i<u.likeby.n; i++) work.append(Result(u.likeby.base[i].him, HFM)); - for(int i=0; i<u.hateby.n; i++) work.append(Result(u.hateby.base[i].him, HRM)); - - /* sort */ - std::sort(work.base, work.base+work.n); - /* merge */ - if(work.n>0) { - int newn=1; - for(int i=1; i<work.n; i++) - if(work.base[i].who==work.base[newn-1].who) { - work.base[newn-1].bits|=work.base[i].bits; - } else { - work.base[newn++]=work.base[i]; - } - work.n=newn; - } - /* fill */ - int nfs=0; - for(int i=0; i<work.n && nfs<maxfs; i++) { - BBSUser& h=userlist.users[work.base[i].who]; - for(int j=0; j<h.utmplist.n && nfs<maxfs; j++) { - int rstat=reverse_friend_stat(work.base[i].bits); - if(h.utmplist.base[j]==index) continue; - fs[nfs].index=h.utmplist.base[j]; - fs[nfs].uid=h.me; - fs[nfs].friendstat=(work.base[i].bits<<24)|h.utmplist.base[j]; - fs[nfs].rfriendstat=(rstat<<24)|index; - nfs++; - } - } - return nfs; -} - -extern "C" void utmplogoutall(void) -{ - for(int i=0; i<USHM_SIZE; i++) - if(utmp.utmp[i]!=-1) - userlist.users[utmp.utmp[i]].logout(i); -} - diff --git a/cacheserver/utmpserver.c b/cacheserver/utmpserver.c deleted file mode 100644 index 85adf8c3..00000000 --- a/cacheserver/utmpserver.c +++ /dev/null @@ -1,222 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include <err.h> - -struct { - int uid; - int nFriends, nRejects; - int friend[MAX_FRIEND]; - 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; - 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); -} - -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, uid; - char *iface_ip = NULL; - - Signal(SIGPIPE, SIG_IGN); - while( (ch = getopt(argc, argv, "p:i:h")) != -1 ) - switch( ch ){ - case 'p': - port = atoi(optarg); - break; - case 'i': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: utmpserver [-i interface_ip] [-p port]\n"); - return 1; - } - - 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 ) - sleep(1); - continue; - } - toread(cfd, &index, sizeof(index)); - if( index == -1 ){ - syncutmp(cfd); - continue; - } - - 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); - } else { - close(cfd); - } - } - return 0; -} diff --git a/cacheserver/utmpserver2.c b/cacheserver/utmpserver2.c deleted file mode 100644 index 12c3a299..00000000 --- a/cacheserver/utmpserver2.c +++ /dev/null @@ -1,290 +0,0 @@ -/* $Id$ */ -#include <stdio.h> -#include <sys/time.h> - -#include "bbs.h" - -extern void utmplogin(int uid, int index, const int like[MAX_FRIEND], const int hate[MAX_REJECT]); -extern int genfriendlist(int uid, int index, ocfs_t *fs, int maxfs); -extern void utmplogoutall(void); -#ifdef FAKEDATA -FILE *fp; -#endif -#ifdef UTMPLOG -FILE *logfp; -#endif - -clock_t begin_clock; -time_t begin_time; -int count_flooding, count_login; - -#ifdef NOFLOODING -/* 0 ok, 1 delay action, 2 reject */ -int action_frequently(int uid) -{ - int i; - time_t now = time(NULL); - time_t minute = now/60; - time_t hour = minute/60; - - static time_t flood_base_minute; - static time_t flood_base_hour; - static struct { - unsigned short lastlogin; // truncated time_t - unsigned char minute_count; - unsigned char hour_count; - } flooding[MAX_USERS]; - - if(minute!=flood_base_minute) { - for(i=0; i<MAX_USERS; i++) - flooding[i].minute_count=0; - flood_base_minute=minute; - } - if(hour!=flood_base_hour) { - for(i=0; i<MAX_USERS; i++) - flooding[i].hour_count=0; - flood_base_hour=hour; - } - - if(abs(flooding[uid].lastlogin-(unsigned short)now)<=3 || - flooding[uid].minute_count>30 || - flooding[uid].hour_count>60) { - count_flooding++; - return 2; - } - - flooding[uid].minute_count++; - flooding[uid].hour_count++; - flooding[uid].lastlogin=now; - - if(flooding[uid].minute_count>5 || - flooding[uid].hour_count>20) { - count_flooding++; - return 1; - } - return 0; -} -#endif /* NOFLOODING */ - -void syncutmp(int cfd) { - int i; - int like[MAX_FRIEND]; - int hate[MAX_REJECT]; - -#ifdef UTMPLOG - int x=-1; - if(logfp && ftell(logfp)> 500*(1<<20)) { - fclose(logfp); - logfp=NULL; - } - if(logfp) fwrite(&x, sizeof(x), 1, logfp); -#endif - - printf("logout all\n"); - utmplogoutall(); - fprintf(stderr,"sync begin\n"); - for(i=0; i<USHM_SIZE; i++) { - int uid; -#ifdef FAKEDATA - fread(&uid, sizeof(uid), 1, fp); - if(uid==-2) - break; - fread(like, sizeof(like), 1, fp); - fread(hate, sizeof(hate), 1, fp); -#else - if( toread(cfd, &uid, sizeof(uid)) <= 0 || - toread(cfd, like, sizeof(like)) <= 0 || - toread(cfd, hate, sizeof(hate)) <= 0) - break; -#endif -#ifdef UTMPLOG - if(logfp) { - fwrite(&uid, sizeof(uid), 1, logfp); - fwrite(like, sizeof(like), 1, logfp); - fwrite(hate, sizeof(hate), 1, logfp); - } -#endif - - if(uid != 0) - utmplogin(uid, i, like, hate); - } - if(i<USHM_SIZE) { -#ifdef UTMPLOG - int x=-2; - if(logfp) fwrite(&x, sizeof(x), 1, logfp); -#endif - } - - fprintf(stderr,"sync end\n"); -} - -void processlogin(int cfd, int uid, int index) -{ - int like[MAX_FRIEND]; - int hate[MAX_REJECT]; - /* logout 銝虫 utmpserver , 航賣亙唬鈭 - 撌脩 logout 撣唾隞乩賢芸 MAX_FRIEND 閬憭銝鈭 */ -#define MAX_FS (2 * MAX_FRIEND) - int res; - int nfs; - ocfs_t fs[MAX_FS]; - -#ifdef FAKEDATA - fread(like, sizeof(like), 1, fp); - fread(hate, sizeof(hate), 1, fp); -#else - if(toread(cfd, like, sizeof(like)) <= 0 || - toread(cfd, hate, sizeof(hate)) <= 0) - return; -#endif -#ifdef UTMPLOG - if(logfp) { - int x=-3; - fwrite(&x, sizeof(x), 1, logfp); - fwrite(&uid, sizeof(uid), 1, logfp); - fwrite(&index, sizeof(index), 1, logfp); - fwrite(like, sizeof(like), 1, logfp); - fwrite(hate, sizeof(hate), 1, logfp); - } -#endif - - utmplogin(uid, index, like, hate); - nfs=genfriendlist(uid, index, fs, MAX_FS); -#ifndef FAKEDATA - res=0; -#ifdef NOFLOODING - res=action_frequently(uid); -#endif - towrite(cfd, &res, sizeof(res)); - towrite(cfd, &nfs, sizeof(nfs)); - towrite(cfd, fs, sizeof(ocfs_t) * nfs); -#endif -} - -void showstat(void) -{ - clock_t now_clock=clock(); - time_t now_time=time(0); - - time_t used_time=now_time-begin_time; - clock_t used_clock=now_clock-begin_clock; - - printf("%.24s : real %.0f cpu %.2f : %d login %d flood, %.2f login/sec, %.2f%% load.\n", - ctime(&now_time), (double)used_time, (double)used_clock/CLOCKS_PER_SEC, - count_login, count_flooding, - (double)count_login/used_time, (double)used_clock/CLOCKS_PER_SEC/used_time*100); - - begin_time=now_time; - begin_clock=now_clock; - count_login=0; - count_flooding=0; -} - -int main(int argc, char *argv[]) -{ - struct sockaddr_in clientaddr; - int ch, port = 5120, sfd, cfd, len; - char *iface_ip = NULL; - int cmd; - int uid,index; - int fail; - int firstsync=0; - -#ifdef UTMPLOG - logfp = fopen("utmp.log","a"); - if(logfp && ftell(logfp)> 500*(1<<20)) { - fclose(logfp); - logfp=NULL; - } -#endif - - Signal(SIGPIPE, SIG_IGN); - while( (ch = getopt(argc, argv, "p:i:h")) != -1 ) - switch( ch ){ - case 'p': - port = atoi(optarg); - break; - case 'i': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: utmpserver [-i interface_ip] [-p port]\n"); - return 1; - } - -#ifdef FAKEDATA - fp=fopen("utmp.data","rb"); -#else - if( (sfd = tobind(iface_ip, port)) < 0 ) - return 1; -#endif - while(1) { -#ifdef FAKEDATA - if(fread(&cmd, sizeof(cmd), 1, fp)==0) break; -#else - len = sizeof(clientaddr); - if( (cfd = accept(sfd, (struct sockaddr *)&clientaddr, &len)) < 0 ){ - if( errno != EINTR ) - sleep(1); - continue; - } - toread(cfd, &cmd, sizeof(cmd)); -#endif - - if(cmd==-1) { - syncutmp(cfd); -#ifndef FAKEDATA - close(cfd); -#endif - firstsync=1; - continue; - } - if(!firstsync) { - // don't accept client before first sync, to prevent incorrect friend data - close(cfd); - continue; - } - - fail=0; -#ifdef FAKEDATA - fread(&uid, sizeof(uid), 1, fp); - fread(&index, sizeof(index), 1, fp); -#else - if(cmd==-2) { - if(toread(cfd, &index, sizeof(index)) <= 0) - fail=1; - if(toread(cfd, &uid, sizeof(uid)) <= 0) - fail=1; - } else if(cmd>=0) { - // old client - fail=1; - } else { - printf("unknown cmd=%d\n",cmd); - } -#endif - if(index>=USHM_SIZE) { - fprintf(stderr, "bad index=%d\n",index); - fail=1; - } - - if(fail) { -#ifndef FAKEDATA - close(cfd); -#endif - continue; - } - - count_login++; - processlogin(cfd, uid, index); - if(count_login>=4000 || time(NULL)-begin_time>30*60) - showstat(); -#ifndef FAKEDATA - close(cfd); -#endif - } -#ifdef FAKEDATA - fclose(fp); -#endif - return 0; -} diff --git a/cacheserver/utmpserver3.c b/cacheserver/utmpserver3.c deleted file mode 100644 index 0e1eef02..00000000 --- a/cacheserver/utmpserver3.c +++ /dev/null @@ -1,341 +0,0 @@ -/* $Id$ */ -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <event.h> - -#include "bbs.h" - -extern void utmplogin(int uid, int index, const int like[MAX_FRIEND], const int hate[MAX_REJECT]); -extern int genfriendlist(int uid, int index, ocfs_t *fs, int maxfs); -extern void utmplogoutall(void); -#ifdef UTMPLOG -FILE *logfp; -#endif - -clock_t begin_clock; -time_t begin_time; -int count_flooding, count_login; - -#ifdef NOFLOODING -/* 0 ok, 1 delay action, 2 reject */ -int action_frequently(int uid) -{ - int i; - time_t now = time(NULL); - time_t minute = now/60; - time_t hour = minute/60; - - static time_t flood_base_minute; - static time_t flood_base_hour; - static struct { - unsigned short lastlogin; // truncated time_t - unsigned char minute_count; - unsigned char hour_count; - } flooding[MAX_USERS]; - - if(minute!=flood_base_minute) { - for(i=0; i<MAX_USERS; i++) - flooding[i].minute_count=0; - flood_base_minute=minute; - } - if(hour!=flood_base_hour) { - for(i=0; i<MAX_USERS; i++) - flooding[i].hour_count=0; - flood_base_hour=hour; - } - - if(abs(flooding[uid].lastlogin-(unsigned short)now)<=3 || - flooding[uid].minute_count>30 || - flooding[uid].hour_count>60) { - count_flooding++; - return 2; - } - - flooding[uid].minute_count++; - flooding[uid].hour_count++; - flooding[uid].lastlogin=now; - - if(flooding[uid].minute_count>5 || - flooding[uid].hour_count>20) { - count_flooding++; - return 1; - } - return 0; -} -#endif /* NOFLOODING */ - -void syncutmp(int cfd) { - int i; - int like[MAX_FRIEND]; - int hate[MAX_REJECT]; - -#ifdef UTMPLOG - int x=-1; - if(logfp && ftell(logfp)> 500*(1<<20)) { - fclose(logfp); - logfp=NULL; - } - if(logfp) fwrite(&x, sizeof(x), 1, logfp); -#endif - - printf("logout all\n"); - utmplogoutall(); - fprintf(stderr,"sync begin\n"); - for(i=0; i<USHM_SIZE; i++) { - int uid; - if( toread(cfd, &uid, sizeof(uid)) <= 0 || - toread(cfd, like, sizeof(like)) <= 0 || - toread(cfd, hate, sizeof(hate)) <= 0) - break; -#ifdef UTMPLOG - if(logfp) { - fwrite(&uid, sizeof(uid), 1, logfp); - fwrite(like, sizeof(like), 1, logfp); - fwrite(hate, sizeof(hate), 1, logfp); - } -#endif - - if(uid != 0) - utmplogin(uid, i, like, hate); - } - if(i<USHM_SIZE) { -#ifdef UTMPLOG - int x=-2; - if(logfp) fwrite(&x, sizeof(x), 1, logfp); -#endif - } - - fprintf(stderr,"sync end\n"); -} - -struct client_state { - struct event ev; - int state; - struct evbuffer *evb; -}; - -void processlogin(struct client_state *cs, int uid, int index) -{ - int like[MAX_FRIEND]; - int hate[MAX_REJECT]; - /* logout 銝虫 utmpserver , 航賣亙唬鈭 - 撌脩 logout 撣唾隞乩賢芸 MAX_FRIEND 閬憭銝鈭 */ -#define MAX_FS (2 * MAX_FRIEND) - int res; - int nfs; - ocfs_t fs[MAX_FS]; - - evbuffer_remove(cs->evb, like, sizeof(like)); - evbuffer_remove(cs->evb, hate, sizeof(hate)); -#ifdef UTMPLOG - if(logfp) { - int x=-3; - fwrite(&x, sizeof(x), 1, logfp); - fwrite(&uid, sizeof(uid), 1, logfp); - fwrite(&index, sizeof(index), 1, logfp); - fwrite(like, sizeof(like), 1, logfp); - fwrite(hate, sizeof(hate), 1, logfp); - } -#endif - - utmplogin(uid, index, like, hate); - nfs=genfriendlist(uid, index, fs, MAX_FS); - res=0; -#ifdef NOFLOODING - res=action_frequently(uid); -#endif - evbuffer_drain(cs->evb, 2147483647); - evbuffer_add(cs->evb, &res, sizeof(res)); - evbuffer_add(cs->evb, &nfs, sizeof(nfs)); - evbuffer_add(cs->evb, fs, sizeof(ocfs_t) * nfs); -} - -void showstat(void) -{ - clock_t now_clock=clock(); - time_t now_time=time(0); - - time_t used_time=now_time-begin_time; - clock_t used_clock=now_clock-begin_clock; - - printf("%.24s : real %.0f cpu %.2f : %d login %d flood, %.2f login/sec, %.2f%% load.\n", - ctime(&now_time), (double)used_time, (double)used_clock/CLOCKS_PER_SEC, - count_login, count_flooding, - (double)count_login/used_time, (double)used_clock/CLOCKS_PER_SEC/used_time*100); - - begin_time=now_time; - begin_clock=now_clock; - count_login=0; - count_flooding=0; -} - -enum { - FSM_ENTER, - FSM_SYNC, - FSM_LOGIN, - FSM_WRITEBACK, - FSM_EXIT -}; - -static int firstsync=0; - -struct timeval tv = {5, 0}; -struct event ev; -int clients = 0; - -#define READ_BLOCK 1024 -#define MAX_CLIENTS 10 - -void connection_client(int cfd, short event, void *arg) -{ - struct client_state *cs = arg; - int cmd, break_out = 0; - int uid = 0, index = 0; - - // ignore clients that timeout - if (event & EV_TIMEOUT) - cs->state = FSM_EXIT; - - if (event & EV_READ) { - if (cs->state != FSM_ENTER) { - if (evbuffer_read(cs->evb, cfd, READ_BLOCK) <= 0) - cs->state = FSM_EXIT; - } - else { - if (evbuffer_read(cs->evb, cfd, 4) <= 0) - cs->state = FSM_EXIT; - } - } - - while (!break_out) { - switch (cs->state) { - case FSM_ENTER: - if (EVBUFFER_LENGTH(cs->evb) < sizeof(int)) { - break_out = 1; - break; - } - evbuffer_remove(cs->evb, &cmd, sizeof(cmd)); - if (cmd == -1) - cs->state = FSM_SYNC; - else if (cmd == -2) { - fcntl(cfd, F_SETFL, fcntl(cfd, F_GETFL, 0) | O_NONBLOCK); - cs->state = FSM_LOGIN; - } - else if (cmd >= 0) - cs->state = FSM_EXIT; - else { - printf("unknown cmd=%d\n",cmd); - cs->state = FSM_EXIT; - } - break; - case FSM_SYNC: - syncutmp(cfd); - firstsync = 1; - cs->state = FSM_EXIT; - break; - case FSM_LOGIN: - if (firstsync) { - if (EVBUFFER_LENGTH(cs->evb) < (2 + MAX_FRIEND + MAX_REJECT) * sizeof(int)) { - break_out = 1; - break; - } - evbuffer_remove(cs->evb, &index, sizeof(index)); - evbuffer_remove(cs->evb, &uid, sizeof(uid)); - if (index >= USHM_SIZE) { - fprintf(stderr, "bad index=%d\n", index); - cs->state = FSM_EXIT; - break; - } - count_login++; - processlogin(cs, uid, index); - if (count_login >= 4000 || (time(NULL) - begin_time) > 30*60) - showstat(); - cs->state = FSM_WRITEBACK; - break_out = 1; - } - else - cs->state = FSM_EXIT; - break; - case FSM_WRITEBACK: - if (event & EV_WRITE) - if (evbuffer_write(cs->evb, cfd) <= 0 && EVBUFFER_LENGTH(cs->evb) > 0) - break_out = 1; - if (EVBUFFER_LENGTH(cs->evb) == 0) - cs->state = FSM_EXIT; - break; - case FSM_EXIT: - if (clients == MAX_CLIENTS) - event_add(&ev, NULL); - close(cfd); - evbuffer_free(cs->evb); - free(cs); - clients--; - return; - break; - } - } - if (cs->state == FSM_WRITEBACK) - event_set(&cs->ev, cfd, EV_WRITE, (void *) connection_client, cs); - event_add(&cs->ev, &tv); -} - -void connection_accept(int fd, short event, void *arg) -{ - struct sockaddr_in clientaddr; - socklen_t len = sizeof(clientaddr); - int cfd; - - if ((cfd = accept(fd, (struct sockaddr *)&clientaddr, &len)) < 0 ) - return; - - struct client_state *cs = calloc(1, sizeof(struct client_state)); - cs->state = FSM_ENTER; - cs->evb = evbuffer_new(); - - event_set(&cs->ev, cfd, EV_READ, (void *) connection_client, cs); - event_add(&cs->ev, &tv); - clients++; - - if (clients >= MAX_CLIENTS) { - event_del(&ev); - } -} - -int main(int argc, char *argv[]) -{ - int ch, port = 5120, sfd; - char *iface_ip = NULL; - -#ifdef UTMPLOG - logfp = fopen("utmp.log","a"); - if(logfp && ftell(logfp)> 500*(1<<20)) { - fclose(logfp); - logfp=NULL; - } -#endif - - Signal(SIGPIPE, SIG_IGN); - while( (ch = getopt(argc, argv, "p:i:h")) != -1 ) - switch( ch ){ - case 'p': - port = atoi(optarg); - break; - case 'i': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: utmpserver [-i interface_ip] [-p port]\n"); - return 1; - } - - if( (sfd = tobind(iface_ip, port)) < 0 ) - return 1; - - event_init(); - event_set(&ev, sfd, EV_READ | EV_PERSIST, connection_accept, &ev); - event_add(&ev, NULL); - event_dispatch(); - return 0; -} diff --git a/cacheserver/utmpsync.c b/cacheserver/utmpsync.c deleted file mode 100644 index 69d1c623..00000000 --- a/cacheserver/utmpsync.c +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include <err.h> - -extern SHM_t *SHM; - -int main(int argc, char **argv) -{ - int sfd, index, i; - attach_SHM(); - if( (sfd = toconnect(OUTTACACHEHOST, OUTTACACHEPORT)) < 0 ) { - printf("connect fail\n"); - 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].myfriend, - sizeof(SHM->uinfo[i].myfriend)) < 0 || - towrite(sfd, SHM->uinfo[i].reject, - sizeof(SHM->uinfo[i].reject)) < 0 ){ - fprintf(stderr, "sync error %d\n", i); - } - return 0; -} |