summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile47
-rw-r--r--bank.h19
-rw-r--r--bankstuff.c51
-rw-r--r--client.c56
-rw-r--r--money.c37
-rw-r--r--server.c144
-rw-r--r--spec38
7 files changed, 392 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..c0050312
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,47 @@
+
+CFLAGS = -O2 -Os -fomit-frame-pointer -fstrength-reduce -fthread-jumps -fexpensive-optimizations -pipe -I../include -DLinux -DBANK_ONLY
+#CFLAGS = -O2 -Os -fomit-frame-pointer -fstrength-reduce -fthread-jumps -fexpensive-optimizations -Wall -pipe -I../include -DLinux -DBANK_ONLY
+
+.if defined(DEBUG)
+CFLAGS += -g
+.endif
+
+.if !defined(NOTPTT)
+CFLAGS += -DPTTBBS
+.endif
+
+SERVEROBJ = server.o bankstuff.o money.o
+CLIENTOBJ = client.o bankstuff.o
+EXTFILE = cache passwd stuff
+EXTOBJ = cache.o passwd.o stuff.o
+PROG = client server
+
+.SUFFIXES: .c .o
+.c.o: ; $(CC) $(CFLAGS) -c $*.c
+
+all: $(PROG)
+
+.if !defined(NOTPTT)
+
+cache: ../mbbsd/cache.c
+ $(CC) $(CFLAGS) -c ../mbbsd/cache.c
+
+passwd: ../mbbsd/passwd.c
+ $(CC) $(CFLAGS) -c ../mbbsd/passwd.c
+
+stuff: ../mbbsd/stuff.c
+ $(CC) $(CFLAGS) -c ../mbbsd/stuff.c
+
+.else
+# define your rules here.
+
+.endif
+
+server: $(SERVEROBJ) $(EXTFILE)
+ $(CC) $(CFLAGS) -o server $(SERVEROBJ) $(EXTOBJ)
+
+client: $(CLIENTOBJ)
+ $(CC) $(CFLAGS) -o client $(CLIENTOBJ)
+
+clean:
+ rm -rf *.o $(PROG)
diff --git a/bank.h b/bank.h
new file mode 100644
index 00000000..be331a1d
--- /dev/null
+++ b/bank.h
@@ -0,0 +1,19 @@
+#include "../include/bbs.h"
+
+#define PORT 2003
+
+#ifdef STRLEN
+ #undef STRLEN
+#endif
+#define STRLEN 128
+
+#define ERROR 0x1
+#define SUCCESS 0x2
+#define TIMEOUT 0x4
+
+typedef int response;
+
+typedef struct request{
+ int money;
+ char userid[IDLEN];
+}request;
diff --git a/bankstuff.c b/bankstuff.c
new file mode 100644
index 00000000..c1e7bff6
--- /dev/null
+++ b/bankstuff.c
@@ -0,0 +1,51 @@
+#include "bank.h"
+
+int sockfd;
+
+char* readline(char *str, int timeout){
+ int len;
+ struct timeval tv;
+ fd_set set;
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&set);
+ FD_SET(sockfd, &set);
+
+ if (select(sockfd + 1, &set, NULL, NULL,!timeout ? NULL : &tv) <= 0) { ///
+ perror("select");
+ exit(-1);
+ }
+
+ if ((len = read(sockfd, str, STRLEN * sizeof(char))) < 0){
+ herror("readline");
+ exit(-1);
+ }
+ if (len == 0)
+ return NULL;
+ str[len] = 0;
+ read(sockfd, &len, sizeof(char)); // chomp
+ return str;
+}
+
+void writeln(char *str){
+ char n = '\n';
+ write(sockfd, str, strlen(str));
+ write(sockfd, &n, sizeof(n));
+}
+
+void getcmd(char *buf, char *cmd, char *param){
+ int i;
+ for(i = 0; buf[i] && buf[i] != ' ' && i < STRLEN; i++)
+ cmd[i] = buf[i];
+ cmd[i] = 0;
+ if (!buf[i]){
+ param = NULL;
+ return;
+ }
+ buf = &buf[i + 1];
+ for(i = 0; buf[i] && i < STRLEN; i++)
+ param[i] = buf[i];
+ param[i] = 0;
+}
diff --git a/client.c b/client.c
new file mode 100644
index 00000000..926a324a
--- /dev/null
+++ b/client.c
@@ -0,0 +1,56 @@
+#include "bank.h"
+
+extern int sockfd;
+
+char* chomp(char *str){
+ int len;
+ len = strlen(str);
+ if(len > 0 && str[len - 1] == '\n')
+ str[len - 1] = 0;
+ return str;
+}
+
+void client_work(FILE *fp){
+ char buf[STRLEN];
+ while(fgets(buf, sizeof(buf), stdin) != NULL){
+ printf("before sending\n");
+ chomp(buf);
+ writeln(buf);
+ if(!strcasecmp(buf, "quit"))
+ break;
+ printf("> %s\n", readline(buf, 0));
+ }
+}
+
+void init_net(char *addr){
+ struct hostent *host = NULL;
+ struct sockaddr_in serv_addr;
+
+ if((host = gethostbyname(addr)) == NULL){
+ herror("gethostbyname");
+ exit(-1);
+ }
+ bcopy(host->h_addr, &serv_addr.sin_addr, host->h_length);
+
+ if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){
+ herror("socket");
+ }
+
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_port = htons(PORT);
+ inet_pton(AF_INET, addr, &serv_addr.sin_addr);
+
+ connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+}
+
+int main(int argc, char **argv){
+// if(argc != 3)
+// exit(-1);
+
+ init_net(argv[1]);
+ client_work(stdin);
+
+ return 0;
+}
diff --git a/money.c b/money.c
new file mode 100644
index 00000000..6dd5b21e
--- /dev/null
+++ b/money.c
@@ -0,0 +1,37 @@
+/*
+ * 若您使用的是 Current Ptt,則不必做任何的修正。
+ * 若您使用的是其他版本的 bbs,請將 Makefile 中的 -DPTTBBS 那行取消掉,
+ * 並自行於下面的 #elseif 之後加入適當的程式碼。
+ */
+
+#define RATE 0.95
+
+int bank_moneyof(int uid){
+#ifdef PTTBBS
+ printf("[server] : uid = %d\n", uid);
+ return moneyof(uid);
+#else
+ //
+#endif
+}
+
+int bank_searchuser(char *userid){
+
+#ifdef PTTBBS
+ return searchuser(userid);
+#else
+ //
+#endif
+}
+
+int bank_deumoney(char *user, int money){
+
+#ifdef PTTBBS
+
+ money *= RATE;
+ printf("give user: %s money: %d add:%d\n", user, moneyof(bank_searchuser(user)), money);
+ deumoney(bank_searchuser(user), money);
+#else
+ //
+#endif
+}
diff --git a/server.c b/server.c
new file mode 100644
index 00000000..ad9b9054
--- /dev/null
+++ b/server.c
@@ -0,0 +1,144 @@
+#include "bank.h"
+
+extern int sockfd;
+
+SHM_t *SHM;
+char *fn_passwd = ".PASSWDS";
+char flag;
+
+typedef struct map_t {
+ char *key;
+ int (*fp)(char *);
+} map_t;
+
+void sig_handler(int signo){
+ pid_t pid;
+ while( (pid = waitpid(-1, NULL, WNOHANG)) > 0)
+ fprintf(stderr, "Child %d terminated\n", pid);
+ exit(0);
+}
+
+int list(char *param){
+ printf("list: %s\n", param);
+ writemsg(SUCCESS, "list success");
+ return 1;
+}
+
+int query(char *param){
+ char buf[STRLEN];
+ sprintf(buf, "%s's money is %d", param, bank_moneyof(bank_searchuser(param)));
+ writemsg(SUCCESS, buf);
+ return 1;
+}
+
+int give(char param[STRLEN]){
+ char user[STRLEN], money[STRLEN];
+ char tmp[STRLEN];
+ printf("give: %s\n", param);
+ getcmd(param, user, money);
+ bank_deumoney(user, atoi(money));
+ sprintf(tmp, "give %s %s", user, money);
+ writemsg(SUCCESS, tmp);
+ return 1;
+}
+
+int quit(char *param){
+ printf("[server] client quit\n");
+ exit(0);
+}
+
+map_t map[] = {
+ {"list", list},
+ {"query", query},
+ {"give", give},
+ {"quit", quit},
+ {"", NULL},
+};
+
+void writemsg(int status, char *str){
+ //write(sockfd, &status. sizeof(status));
+ writeln(str);
+}
+
+void serv_work(void){
+ int i, status = ERROR;
+ char buf[STRLEN], cmd[STRLEN], param[STRLEN];
+
+ fprintf(stderr, "new child\n");
+
+ attach_SHM();
+
+ while(readline(buf, 600) != NULL){
+ printf("[server] read: ");
+ puts(buf);
+ getcmd(buf, cmd, param);
+ for (i = 0; map[i].fp; i++){
+ if (!strcasecmp(map[i].key, cmd)){
+ status = (*(map[i].fp))(param);
+ break;
+ }
+ }
+ if(!map[i].fp){
+ writemsg(ERROR, "Wrong command");
+ strcpy(param, "error");
+ }
+ printf("[server] complete\n");
+ }
+}
+
+int check_perm(char *ip){
+}
+
+int main(int argc, char **argv){
+ int listenfd;
+ pid_t pid;
+ socklen_t addr_len;
+ struct sockaddr_in serv_addr;
+
+ listenfd = socket(PF_INET, SOCK_STREAM, 0);
+
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_port = htons(PORT);
+
+ bind(listenfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr));
+ listen(listenfd, 5);
+ signal(SIGCHLD, sig_handler);
+
+ while(1){
+ addr_len = sizeof(serv_addr);
+
+ if( (sockfd = accept(listenfd,(struct sockaddr *) &serv_addr, &addr_len)) < 0){
+ if(errno == EINTR)
+ continue;
+ else
+ herror("accept");
+ }
+#define NOFORK 1
+#if NOFORK
+ if((pid = fork()) < 0)
+ perror("fork");
+
+ else if(pid == 0){
+#endif
+ int len;
+ struct sockaddr_in name;
+ close(listenfd);
+
+ if(getpeername(sockfd,(struct sockaddr *) &name, &len) < 0){
+ perror("getpeername");
+ exit(-1);
+ }
+ else{
+ printf("address: %s\n", inet_ntoa(((struct sockaddr_in *) &name)->sin_addr));
+ }
+ serv_work();
+ exit(0);
+#if NOFORK
+ }
+#endif
+ close(sockfd);
+ }
+ return 0;
+}
diff --git a/spec b/spec
new file mode 100644
index 00000000..a9b0d190
--- /dev/null
+++ b/spec
@@ -0,0 +1,38 @@
+
+Use Case:
+ list:
+ 列出所有接受轉帳的站台。
+ query site:
+ 列出 site 這個站的資訊,包括匯率等。
+ quit:
+ 切斷連線離開。
+
+
+
+
+ +-------+ +-------+
+ +-------+ | +----------+ +----------+ +-------+ |
+ | client|-+ ---| bankd(1) | <--------> | bankd(2) |---| client|-+
+ +-------+ +----------+ +----------+ +-------+
+
+ client:
+
+Note:
+ client 能夠改 source,所以請務必注意 server 一定要小心防止 client
+ 的惡搞
+
+Protocol (between banks):
+ 1.假設 bankd(1) 為 Ptt 這端的 daemon,bankd(2) 為 Ptt2 這端的。
+ 2.當 Ptt 上有人想匯錢給 Ptt2 上的人,Ptt user(mbbsd) 這邊會開啟與
+ 指定機器上 bank 的連線。[1]
+ 3.Client 先扣除自己的錢[2],再跟 server 說他要轉帳的對象跟金額。
+ 4.Server 進行確認動作
+ 1) 確定對方紀錄的匯率與自己相同。不同則回應錯誤。
+ 2) 確定此人是否存在。是,則將錢匯入,回應成功訊息;否,則回應錯
+ 誤。
+ 5.根據 server 的回應做出動作。成功則不做任何事,失敗就將自己的錢
+ 加回來。
+
+
+ [1] 不加密的原因是 ... 懶 :p 有需要的話直接拿 ssh tunnel 來用吧 :p
+ [2] 避免有人送錢之後惡意斷線,造成錢有增無減。