diff options
-rw-r--r-- | pttbbs/common/sys/net.c | 10 | ||||
-rwxr-xr-x | pttbbs/daemon/brcstored/brcstored.py | 89 | ||||
-rw-r--r-- | pttbbs/include/daemons.h | 13 | ||||
-rw-r--r-- | pttbbs/mbbsd/brc.c | 217 |
4 files changed, 229 insertions, 100 deletions
diff --git a/pttbbs/common/sys/net.c b/pttbbs/common/sys/net.c index 9e264b91..9f7f90af 100644 --- a/pttbbs/common/sys/net.c +++ b/pttbbs/common/sys/net.c @@ -192,7 +192,7 @@ int toconnectex(const char *addr, int timeout) serv_name.sin_port = htons(atoi(port)); serv_name.sin_family = AF_INET; - while ( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ) + while (connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0) { if (errno == EINPROGRESS) { @@ -206,8 +206,12 @@ int toconnectex(const char *addr, int timeout) if (select(sock+1, NULL, &myset, NULL, &tv) > 0) { - // success - break; + int result = 1; + socklen_t szresult = sizeof(result); + // szresult = 0: success, otherwise: failure. + getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &szresult); + if (result == 0) + break; } } diff --git a/pttbbs/daemon/brcstored/brcstored.py b/pttbbs/daemon/brcstored/brcstored.py new file mode 100755 index 00000000..9df59c26 --- /dev/null +++ b/pttbbs/daemon/brcstored/brcstored.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +import StringIO +import logging +import re +import sys +import leveldb +import eventlet +import struct + + +_SERVER_ADDR = '127.0.0.1' +_SERVER_PORT = 5133 +_DB_PATH = '/home/bbs/brcstore/db' + + +def get_data(uid): + try: + return g_db.Get(uid) + except KeyError: + return None + + +def put_data(uid, blob): + g_db.Put(uid, blob) + + +def open_database(db_path): + global g_db + g_db = leveldb.LevelDB(db_path) + + +def handle_request(sock, fd): + # WRITE: 'w' + UID + '\n' + int32_t len, BYTE[len] + # READ: 'r' + UID + '\n' + # Returns: int32_t len, BYTE[len] (len=-1 if UID does not exist) + fmt_len = '@i' + try: + command = fd.read(1) + uid = fd.readline().strip() + if command == 'r': + msg = get_data(uid) + if msg is None: + fd.write(struct.pack(fmt_len, -1)) + logging.info('Read : %s: (NOT FOUND)', uid) + else: + fd.write(struct.pack(fmt_len, len(msg))) + fd.write(msg) + logging.info('Read : %s: size=%d', uid, len(msg)) + elif command == 'w': + msglen = struct.unpack(fmt_len, + fd.read(struct.calcsize(fmt_len)))[0] + msg = fd.read(msglen) + logging.info('Write: %s: size=%d', uid, len(msg)) + put_data(uid, msg) + else: + raise ValueError('Unknown request: 0x%02X' % command) + except: + logging.exception("handle_request") + finally: + try: + fd.close() + sock.close() + except: + pass + + +def main(myname, argv): + level = logging.DEBUG + # level = logging.INFO + logging.basicConfig(level=level, format='%(asctime)-15s %(message)s') + if len(argv) not in [0, 1]: + print "Usage: %s [db_path]" % myname + exit(1) + db_path = argv[0] if len(argv) > 0 else _DB_PATH + logging.warn("Serving at %s:%s [db:%s]...", _SERVER_ADDR, _SERVER_PORT, + db_path) + open_database(db_path) + server = eventlet.listen((_SERVER_ADDR, _SERVER_PORT)) + pool = eventlet.GreenPool() + while True: + try: + new_sock, address = server.accept() + pool.spawn_n(handle_request, new_sock, new_sock.makefile('rw')) + except (SystemExit, KeyboardInterrupt): + break + +if __name__ == '__main__': + main(sys.argv[0], sys.argv[1:]) diff --git a/pttbbs/include/daemons.h b/pttbbs/include/daemons.h index 23f0162f..92908340 100644 --- a/pttbbs/include/daemons.h +++ b/pttbbs/include/daemons.h @@ -89,6 +89,19 @@ typedef struct { } angel_beats_report ; /////////////////////////////////////////////////////////////////////// +// Brc Storage Daemon + +#ifndef BRCSTORED_ADDR +#define BRCSTORED_ADDR ":5133" +#endif + +enum BRCSTORED_OPERATIONS { + BRCSTORED_REQ_INVALID = 0, + BRCSTORED_REQ_READ = 'r', + BRCSTORED_REQ_WRITE = 'w', +}; + +/////////////////////////////////////////////////////////////////////// // online friend relation daemon // typedef struct { diff --git a/pttbbs/mbbsd/brc.c b/pttbbs/mbbsd/brc.c index c345468e..9dd96b3c 100644 --- a/pttbbs/mbbsd/brc.c +++ b/pttbbs/mbbsd/brc.c @@ -1,5 +1,6 @@ /* $Id$ */ #include "bbs.h" +#include "daemons.h" /** * 關於本檔案的細節,請見 docs/brc.txt。 @@ -53,7 +54,6 @@ static int brc_currbid; static int brc_num; static brc_rec brc_list[BRC_MAXNUM]; -static char * const fn_brc2= ".brc2"; static char * const fn_brc = ".brc3"; /** @@ -246,6 +246,21 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, const brc_rec* list) brc_changed = 0; } +/* release allocated memory + * + * Do not destory brc_currbid, brc_num, brc_list. + */ +void +brc_release() +{ + if (brc_buf) { + free(brc_buf); + brc_buf = NULL; + } + brc_changed = 0; + brc_size = brc_alloc = 0; +} + /** * write \a brc_num and \a brc_list back to \a brc_buf. */ @@ -257,126 +272,108 @@ brc_update(){ } } -void -read_brc2(void) -{ - char brcfile[STRLEN]; - int fd; - size_t sz2 = 0, sz3 = 0; - char *cvt = NULL, *cvthead = NULL; - - // brc v2 is using 16 bit for brcbid_t and brcnbrd_t. - uint16_t bid2, num2; - - brcbid_t bid; - brcnbrd_t num; - time4_t create; - brc_rec rec; - - setuserfile(brcfile, fn_brc2); - - if ((fd = open(brcfile, O_RDONLY)) == -1) - return; - - sz2 = dashs(brcfile); - sz3 = sz2 * 2; // max double size - - cvthead = cvt = malloc (sz3); - memset(cvthead, 0, sz3); - // now calculate real sz3 - - while (read(fd, &bid2, sizeof(bid2)) > 0) - { - if (read(fd, &num2, sizeof(num2)) < 1) - break; - - bid = bid2; - num = num2; - - // some brc v2 contains bad structure. - // check pointer here. - if (cvt + sizeof(brcbid_t) + sizeof(brcnbrd_t) - cvthead >= sz3) - break; - - *(brcbid_t*) cvt = bid; cvt += sizeof(brcbid_t); - *(brcnbrd_t*)cvt = num; cvt += sizeof(brcnbrd_t); - - // some brc v2 contains bad structure. - // check pointer here. - for (; num > 0 && (cvt + sizeof(brc_rec) - cvthead) <= sz3 ; num--) - { - if (read(fd, &create, sizeof(create)) < 1) - break; - - rec.create = create; - rec.modified = create; +/** + * Use BRC data on remote daemon. + */ +int +load_remote_brc() { + int fd; + int8_t command = BRCSTORED_REQ_READ; + int32_t len; + char uid[PATHLEN]; + int err = 1; - *(brc_rec*)cvt = rec; cvt += sizeof(brc_rec); - } + brc_size = 0; + snprintf(uid, sizeof(uid), "%s#%d\n", cuser.userid, cuser.firstlogin); + + do { + if ((fd = toconnectex(BRCSTORED_ADDR, 10)) < 0) + break; + if (towrite(fd, &command, 1) != 1) + break; + if (towrite(fd, uid, strlen(uid)) < 0) + break; + if (toread(fd, &len, sizeof(len)) != sizeof(len)) + break; + if (len < 0) // not found + break; + brc_get_buf(len); + if (len && toread(fd, brc_buf, len) != len) + break; + brc_size = len; + err = 0; + } while (0); + + if (fd >= 0) + close(fd); + + if (err) { + brc_release(); + return 0; } - close(fd); - // now cvthead is ready for v3. - sz3 = cvt - cvthead; - brc_get_buf(sz3); - // new size maybe smaller, check brc_alloc instead - if (sz3 > brc_alloc) - sz3 = brc_alloc; - brc_size = sz3; - memcpy(brc_buf, cvthead, sz3); + return 1; +} + +int +save_remote_brc() { + int fd; + int8_t command = BRCSTORED_REQ_WRITE; + int32_t len; + char uid[PATHLEN]; + int err = 1; + + snprintf(uid, sizeof(uid), "%s#%d\n", cuser.userid, cuser.firstlogin); + len = brc_size; + + do { + if ((fd = toconnectex(BRCSTORED_ADDR, 10)) < 0) + break; + if (towrite(fd, &command, 1) != 1) + break; + if (towrite(fd, uid, strlen(uid)) < 0) + break; + if (towrite(fd, &len, sizeof(len)) != sizeof(len)) + break; + if (len && towrite(fd, brc_buf ? brc_buf : "", len) != len) + break; + err = 0; + } while (0); + + if (fd >= 0) + close(fd); + + if (err) + return 0; - free(cvthead); + return 1; } -inline static void -read_brc_buf(void) -{ +int +load_local_brc() { char brcfile[STRLEN]; int fd; struct stat brcstat; - if (brc_buf != NULL) - return; - brc_size = 0; setuserfile(brcfile, fn_brc); if ((fd = open(brcfile, O_RDONLY)) == -1) - { - read_brc2(); - return; - } + return 0; fstat(fd, &brcstat); brc_get_buf(brcstat.st_size); brc_size = read(fd, brc_buf, brc_alloc); close(fd); + return 1; } -/* release allocated memory - * - * Do not destory brc_currbid, brc_num, brc_list. - */ -void -brc_release() -{ - if (brc_buf) { - free(brc_buf); - brc_buf = NULL; - } - brc_changed = 0; - brc_size = brc_alloc = 0; -} - -void -brc_finalize(){ +int +save_local_brc() { + int ok = 1; char brcfile[STRLEN]; char tmpfile[STRLEN]; - if(!brc_initialized) - return; - - brc_update(); setuserfile(brcfile, fn_brc); snprintf(tmpfile, sizeof(tmpfile), "%s.tmp.%x", brcfile, getpid()); if (brc_buf != NULL) { @@ -392,6 +389,32 @@ brc_finalize(){ unlink(tmpfile); } } + return ok; +} + +void +read_brc_buf(void) +{ + if (brc_buf != NULL) + return; + +#ifdef USE_REMOTE_BRC + if (!load_remote_brc()) +#endif + load_local_brc(); +} + +void +brc_finalize(){ + if(!brc_initialized) + return; + + brc_update(); + +#ifdef USE_REMOTE_BRC + if (!save_remote_brc()) +#endif + save_local_brc(); brc_release(); brc_initialized = 0; |