summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pttbbs/common/sys/net.c10
-rwxr-xr-xpttbbs/daemon/brcstored/brcstored.py89
-rw-r--r--pttbbs/include/daemons.h13
-rw-r--r--pttbbs/mbbsd/brc.c217
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;