diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c8c51f..7691c0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,31 @@ ELSE() add_definitions("-DCPUBIT32") ENDIF() +if($ENV{DICTKEYSZ}) + message("custom dict key size: $ENV{DICTKEYSZ}") + add_definitions("-DDICTKEYSZ=$ENV{DICTKEYSZ}") +endif() +if($ENV{DICTDATSZ}) + message("custom dict data size: $ENV{DICTDATSZ}") + add_definitions("-DDICTDATSZ=$ENV{DICTDATSZ}") +endif() +if($ENV{CRYPTO_SUMTABLE}) + message("custom suntable: $ENV{CRYPTO_SUMTABLE}") + add_definitions("-DCRYPTO_SUMTABLE=$ENV{CRYPTO_SUMTABLE}") +endif() +if($ENV{THREADCNT}) + message("custom suntable: $ENV{THREADCNT}") + add_definitions("-DTHREADCNT=$ENV{THREADCNT}") +endif() +if($ENV{MAXWAITSEC}) + message("custom suntable: $ENV{MAXWAITSEC}") + add_definitions("-DMAXWAITSEC=$ENV{MAXWAITSEC}") +endif() +if($ENV{DICTPOOLBIT}) + message("custom suntable: $ENV{DICTPOOLBIT}") + add_definitions("-DDICTPOOLBIT=$ENV{DICTPOOLBIT}") +endif() + include_directories("/usr/local/include") link_directories("/usr/local/lib") @@ -32,4 +57,4 @@ target_link_libraries(cfgwriter libspb.a) INSTALL(TARGETS simple-dict-server RUNTIME DESTINATION bin) #INSTALL(TARGETS simple-dict-client RUNTIME DESTINATION bin) -#INSTALL(TARGETS cfgwriter RUNTIME DESTINATION bin) \ No newline at end of file +#INSTALL(TARGETS cfgwriter RUNTIME DESTINATION bin) diff --git a/client.c b/client.c index 6f2c29e..bbc5564 100644 --- a/client.c +++ b/client.c @@ -31,8 +31,6 @@ static uint32_t file_size; static int recv_bin = 0; static config_t conf; -#define DEBUG - void getMessage(void *p) { int c = 0, offset = 0; cmdpacket_t cp = (cmdpacket_t)bufr; @@ -75,13 +73,14 @@ void getMessage(void *p) { //fwrite(data, datalen, 1, fp); //fclose(fp); off_t tmp = datalen; - char* newdata = raw_decrypt(data, &tmp, 0, conf.pwd); + char* ptr; + char* newdata = raw_decrypt(data, &tmp, 0, conf.pwd, &ptr); if(newdata) { printf("raw data len after decode: %d\n", (int)tmp); FILE* fp = fopen(savepath, "wb+"); fwrite(newdata, (size_t)tmp, 1, fp); fclose(fp); - free(newdata); + free(ptr); puts("recv raw data succeed."); } else puts("decode raw data error."); } else puts("recv raw data error."); @@ -110,7 +109,7 @@ void getMessage(void *p) { #ifdef DEBUG printf("[handle] Decrypt %d bytes data...\n", (int)cp->datalen); #endif - if(cmdpacket_decrypt(cp, 0, conf.pwd)) { + if(!cmdpacket_decrypt(cp, 0, conf.pwd)) { cp->data[cp->datalen] = 0; #ifdef DEBUG printf("[normal] Get %u bytes packet with data: %s\n", offset, cp->data); diff --git a/config.h b/config.h index 8496a57..11a48ec 100644 --- a/config.h +++ b/config.h @@ -7,4 +7,4 @@ struct config_t { }; typedef struct config_t config_t; -#endif \ No newline at end of file +#endif diff --git a/crypto.h b/crypto.h index 1ff697b..3d0d79d 100644 --- a/crypto.h +++ b/crypto.h @@ -11,25 +11,29 @@ #include #include "crypto.h" +#ifndef CRYPTO_SUMTABLE +#define CRYPTO_SUMTABLE {\ + 0x9e3579b9,\ + 0x3c6ef172,\ + 0xd2a66d2b,\ + 0x78dd36e4,\ + 0x17e5609d,\ + 0xb54fda56,\ + 0x5384560f,\ + 0xf1bb77c8,\ + 0x8ff24781,\ + 0x2e4ac13a,\ + 0xcc653af3,\ + 0x6a9964ac,\ + 0x08d12965,\ + 0xa708081e,\ + 0x451221d7,\ + 0xe37793d0 \ +} +#endif + // TEA encoding sumtable -static const uint32_t sumtable[0x10] = { - 0x9e3579b9, - 0x3c6ef172, - 0xd2a66d2b, - 0x78dd36e4, - 0x17e5609d, - 0xb54fda56, - 0x5384560f, - 0xf1bb77c8, - 0x8ff24781, - 0x2e4ac13a, - 0xcc653af3, - 0x6a9964ac, - 0x08d12965, - 0xa708081e, - 0x451221d7, - 0xe37793d0, -}; +static const uint32_t sumtable[0x10] = CRYPTO_SUMTABLE; static uint8_t seqs[THREADCNT]; // 消息序号 @@ -54,66 +58,64 @@ static void reset_seq(int index) { } static char* raw_encrypt(const char* buf, off_t* len, int index, const char pwd[64]) { - TEADAT tin = {*len, (uint8_t*)buf}; - TEADAT tout; - TEA tea[4]; + TEA tea; - ((uint64_t*)tea)[0] = ((uint64_t*)pwd)[0]; - ((uint64_t*)tea)[1] = ((uint64_t*)pwd)[1]; - ((uint8_t*)tea)[15] = seqs[index]++; - tea_encrypt_native_endian(tea, sumtable, &tin, &tout); - - *len = tout.len; - char* encbuf = (char*)malloc(*len); - memcpy(encbuf, tout.data, *len); - free(tout.ptr); + ((uint64_t*)tea.t)[0] = ((uint64_t*)pwd)[0]; + ((uint64_t*)tea.t)[1] = ((uint64_t*)pwd)[1]; + ((uint8_t*)tea.t)[15] = seqs[index]++; + int64_t dstlen = tea_encrypt_len(*len); + char* encbuf = (char*)malloc(dstlen); + if(!encbuf) return NULL; + *len = tea_encrypt_native_endian(tea, sumtable, (const uint8_t*)buf, *len, (uint8_t*)encbuf); return encbuf; } -static char* raw_decrypt(const char* buf, off_t* len, int index, const char pwd[64]) { - TEADAT tin = {*len, (uint8_t*)buf}; - TEADAT tout; - TEA tea[4]; +// raw_decrypt buf: in->src out->dstptr +static char* raw_decrypt(const char* buf, off_t* len, int index, const char pwd[64], char** ptr) { + TEA tea; - ((uint64_t*)tea)[0] = ((uint64_t*)pwd)[0]; - ((uint64_t*)tea)[1] = ((uint64_t*)pwd)[1]; - ((uint8_t*)tea)[15] = seqs[index]; - if(!tea_decrypt_native_endian(tea, sumtable, &tin, &tout)) return NULL; - else if(tout.len <= 0) { - free(tout.ptr); - return NULL; - } else seqs[index]++; + ((uint64_t*)tea.t)[0] = ((uint64_t*)pwd)[0]; + ((uint64_t*)tea.t)[1] = ((uint64_t*)pwd)[1]; + ((uint8_t*)tea.t)[15] = seqs[index]; - *len = tout.len; char* decbuf = (char*)malloc(*len); - memcpy(decbuf, tout.data, *len); - free(tout.ptr); + if(!decbuf) return NULL; + char* out = (char*)tea_decrypt_native_endian(tea, sumtable, (const uint8_t*)buf, *len, (uint8_t*)decbuf); + if(!out) { + free(decbuf); + return NULL; + } - return decbuf; + seqs[index]++; + + *len = tea_decrypt_len(*len, decbuf[0]); + *ptr = decbuf; + + return out; } -static void cmdpacket_encrypt(cmdpacket_t p, int index, const char pwd[64], const char* data) { - TEADAT tin = {p->datalen, (uint8_t *)data}; - TEADAT tout; - TEA tea[4]; +static int cmdpacket_encrypt(cmdpacket_t p, int index, const char pwd[64], const char* data) { + TEA tea; #ifdef DEBUG printf("encrypt len: %d, data: ", p->datalen); for(int i = 0; i < p->datalen; i++) printf("%02x", data[i]); putchar('\n'); #endif - ((uint64_t*)tea)[0] = ((uint64_t*)pwd)[0]; - ((uint64_t*)tea)[1] = ((uint64_t*)pwd)[1]; - ((uint8_t*)tea)[15] = seqs[index]++; + ((uint64_t*)tea.t)[0] = ((uint64_t*)pwd)[0]; + ((uint64_t*)tea.t)[1] = ((uint64_t*)pwd)[1]; + ((uint8_t*)tea.t)[15] = seqs[index]++; #ifdef DEBUG printf("encrypt tea: "); - for(int i = 0; i < 16; i++) printf("%02x", ((uint8_t*)tea)[i]); + for(int i = 0; i < 16; i++) printf("%02x", ((uint8_t*)tea.t)[i]); putchar('\n'); #endif - tea_encrypt_native_endian(tea, sumtable, &tin, &tout); + int64_t outlen = tea_encrypt_len(p->datalen); + + char out[outlen]; md5((const uint8_t *)data, p->datalen, p->md5); #ifdef DEBUG @@ -122,63 +124,62 @@ static void cmdpacket_encrypt(cmdpacket_t p, int index, const char pwd[64], cons putchar('\n'); #endif - p->datalen = tout.len; - memcpy(p->data, tout.data, p->datalen); + p->datalen = tea_encrypt_native_endian(tea, sumtable, (const uint8_t*)data, p->datalen, (uint8_t*)out); + memcpy(p->data, out, p->datalen); + #ifdef DEBUG printf("encrypted data len: %d, data: ", p->datalen); for(int i = 0; i < p->datalen; i++) printf("%02x", p->data[i]); putchar('\n'); #endif - free(tout.ptr); - return; + return 0; } static int cmdpacket_decrypt(cmdpacket_t p, int index, const char pwd[64]) { - TEADAT tin = {p->datalen, p->data}; - TEADAT tout; - TEA tea[4]; + TEA tea; #ifdef DEBUG printf("decrypt len: %d, data: ", p->datalen); for(int i = 0; i < p->datalen; i++) printf("%02x", p->data[i]); putchar('\n'); #endif - ((uint64_t*)tea)[0] = ((uint64_t*)pwd)[0]; - ((uint64_t*)tea)[1] = ((uint64_t*)pwd)[1]; - ((uint8_t*)tea)[15] = seqs[index]; + ((uint64_t*)tea.t)[0] = ((uint64_t*)pwd)[0]; + ((uint64_t*)tea.t)[1] = ((uint64_t*)pwd)[1]; + ((uint8_t*)tea.t)[15] = seqs[index]; #ifdef DEBUG printf("decrypt tea: "); - for(int i = 0; i < 16; i++) printf("%02x", ((uint8_t*)tea)[i]); + for(int i = 0; i < 16; i++) printf("%02x", ((uint8_t*)tea.t)[i]); putchar('\n'); #endif - if(!tea_decrypt_native_endian(tea, sumtable, &tin, &tout)) return 0; - if(tout.len <= 0) { - free(tout.ptr); - return 0; - } + char outbuf[p->datalen]; + + char* out = (char*)tea_decrypt_native_endian(tea, sumtable, (const uint8_t*)p->data, p->datalen, (uint8_t*)outbuf); + if(!out) return 2; + + p->datalen = tea_decrypt_len(p->datalen, outbuf[0]); + uint8_t datamd5[16]; - md5(tout.data, tout.len, datamd5); + md5((const uint8_t*)out, p->datalen, datamd5); + #ifdef DEBUG printf("decrypt md5: "); for(int i = 0; i < 16; i++) printf("%02x", datamd5[i]); putchar('\n'); - printf("decrypted data len: %u, data: ", (unsigned int)tout.len); - for(int i = 0; i < tout.len; i++) printf("%02x", tout.data[i]); + printf("decrypted data len: %u, data: ", (unsigned int)p->datalen); + for(int i = 0; i < p->datalen; i++) printf("%02x", out[i]); putchar('\n'); #endif + if(is_md5_equal((uint8_t*)datamd5, p->md5)) { seqs[index]++; - p->datalen = tout.len; - memcpy(p->data, tout.data, p->datalen); - free(tout.ptr); - return 1; + memcpy(p->data, out, p->datalen); + return 0; } - free(tout.ptr); - return 0; + + return 3; } - #endif /* _CRYPTO_H_ */ diff --git a/dict.h b/dict.h index 30ebd65..7fa089c 100644 --- a/dict.h +++ b/dict.h @@ -11,8 +11,13 @@ #include "dict.h" #include "server.h" -#define DICTKEYSZ 127 -#define DICTDATSZ 127 +#ifndef DICTKEYSZ + #define DICTKEYSZ 127 +#endif +#ifndef DICTDATSZ + #define DICTDATSZ 127 +#endif + struct dict_t { char key[DICTKEYSZ]; char data[DICTDATSZ]; @@ -145,4 +150,4 @@ static inline int is_dict_md5_equal(uint8_t* digest) { #endif } -#endif \ No newline at end of file +#endif diff --git a/old_dict.h b/old_dict.h index 7a06ab2..e2edbd6 100644 --- a/old_dict.h +++ b/old_dict.h @@ -12,4 +12,4 @@ struct DICTBLK{ typedef struct DICTBLK DICTBLK; #define DICTBLKSZ sizeof(DICTBLK) -#endif \ No newline at end of file +#endif diff --git a/server.c b/server.c index 08eea5f..3b551c8 100644 --- a/server.c +++ b/server.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,11 @@ struct thread_timer_t { ssize_t numbytes; char *dat; pthread_t thread; - uint8_t buf[BUFSIZ-sizeof(uint32_t)-sizeof(int)-sizeof(time_t)-sizeof(ssize_t)-sizeof(char*)-sizeof(pthread_t)]; + pthread_cond_t c; + pthread_mutex_t mc; + pthread_rwlock_t mb; + uint8_t isbusy; + uint8_t buf[CMDPACKET_LEN_MAX]; }; typedef struct thread_timer_t thread_timer_t; static thread_timer_t timers[THREADCNT]; @@ -123,20 +128,23 @@ static inline uint32_t last_nonnull(const char* p, uint32_t max_size) { static int send_data(int accept_fd, int index, server_ack_t cmd, const char *data, size_t length) { char buf[CMDPACKET_LEN_MAX]; - cmdpacket_t p = (cmdpacket_t)buf; - p->cmd = (uint8_t)cmd; - p->datalen = length; - cmdpacket_encrypt(p, index, cfg.pwd, data); - int total = CMDPACKET_HEAD_LEN+p->datalen; - if(!~send(accept_fd, buf, total, 0)) { - perror("Send data error"); - return 0; - } else { + if(length <= UINT8_MAX) { + cmdpacket_t p = (cmdpacket_t)buf; + p->cmd = (uint8_t)cmd; + p->datalen = length; + cmdpacket_encrypt(p, index, cfg.pwd, data); + int total = CMDPACKET_HEAD_LEN+p->datalen; + if(!~send(accept_fd, buf, total, 0)) { + perror("Send data error"); + return 0; + } printf("Send %d bytes data: ", total); for(int i = 0; i < length; i++) putchar(data[i]); putchar('\n'); return 1; } + fputs("Send data: length too long.", stderr); + return 0; } static int send_all(thread_timer_t *timer) { @@ -565,6 +573,10 @@ static void accept_timer(void *p) { sleep(MAXWAITSEC / 4); while(timer->thread && !pthread_kill(timer->thread, 0)) { + pthread_rwlock_rdlock(&timer->mb); + uint8_t isbusy = timer->isbusy; + pthread_rwlock_unlock(&timer->mb); + if(!isbusy) break; if(is_dict_opening) touch_timer(p); time_t waitsec = time(NULL) - timer->touch; printf("Wait sec: %u, max: %u\n", (unsigned int)waitsec, MAXWAITSEC); @@ -593,12 +605,19 @@ static void cleanup_thread(thread_timer_t* timer) { } close_dict(timer->index); timer->thread = 0; + timer->isbusy = 0; + pthread_cond_destroy(&timer->c); + pthread_mutex_destroy(&timer->mc); + pthread_rwlock_destroy(&timer->mb); setdicts[timer->index].data[0] = 0; puts("Finish cleaning"); } static void handle_int(int signo) { puts("Keyboard interrupted"); + for(int i = 0; i < THREADCNT; i++) { + if(timers[i].thread) pthread_kill(timers[i].thread, SIGQUIT); + } pthread_exit(NULL); } @@ -608,108 +627,125 @@ static void handle_pipe(int signo) { } static void handle_accept(void *p) { - puts("Handling accept..."); - pthread_t thread; - if (pthread_create(&thread, &attr, (void *)&accept_timer, p)) { - perror("Error creating timer thread"); - cleanup_thread(timer_pointer_of(p)); - return; - } - puts("Creating timer thread succeeded"); + pthread_cond_init(&timer_pointer_of(p)->c, NULL); + pthread_mutex_init(&timer_pointer_of(p)->mc, NULL); + pthread_rwlock_init(&timer_pointer_of(p)->mb, NULL); pthread_cleanup_push((void*)&cleanup_thread, p); - int accept_fd = timer_pointer_of(p)->accept_fd; - uint32_t index = timer_pointer_of(p)->index; - uint8_t *buff = timer_pointer_of(p)->buf; - cmdpacket_t cp = (cmdpacket_t)buff; - ssize_t numbytes = 0, offset = 0; - while( - offset >= CMDPACKET_HEAD_LEN - || (numbytes = recv(accept_fd, buff+offset, CMDPACKET_HEAD_LEN-offset, MSG_WAITALL)) > 0 - ) { - touch_timer(p); - offset += numbytes; - #ifdef DEBUG - printf("[handle] Get %zd bytes, total: %zd.\n", numbytes, offset); - #endif - if(offset < CMDPACKET_HEAD_LEN) break; - if(offset < CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen)) { - ssize_t toread = CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen)-offset; - numbytes = recv(accept_fd, buff+offset, toread, MSG_WAITALL); - if(numbytes != toread) break; - else { - offset += numbytes; - #ifdef DEBUG - printf("[handle] Get %zd bytes, total: %zd.\n", numbytes, offset); - #endif - } + while(1) { + puts("Handling accept..."); + pthread_t thread; + pthread_rwlock_unlock(&timer_pointer_of(p)->mb); + pthread_rwlock_wrlock(&timer_pointer_of(p)->mb); + timer_pointer_of(p)->isbusy = 1; + pthread_rwlock_unlock(&timer_pointer_of(p)->mb); + if (pthread_create(&thread, &attr, (void *)&accept_timer, p)) { + perror("Error creating timer thread"); + //cleanup_thread(timer_pointer_of(p)); + pthread_rwlock_unlock(&timer_pointer_of(p)->mb); + return; } - numbytes = CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen); // 暂存 packet len - if(offset < numbytes) break; - #ifdef DEBUG - printf("[handle] Decrypt %d bytes data...\n", (int)cp->datalen); - #endif - if(cp->cmd <= CMDEND) { - if(cmdpacket_decrypt(cp, index, cfg.pwd)) { - cp->data[cp->datalen] = 0; - timer_pointer_of(p)->dat = (char*)cp->data; - timer_pointer_of(p)->numbytes = (ssize_t)(cp->datalen); - printf("[normal] Get %zd bytes packet with cmd: %d, data: %s\n", offset, cp->cmd, cp->data); - switch(cp->cmd) { - case CMDGET: - if(!has_dict_opened && !s1_get(timer_pointer_of(p))) goto CONV_END; + puts("Creating timer thread succeeded"); + int accept_fd = timer_pointer_of(p)->accept_fd; + uint32_t index = timer_pointer_of(p)->index; + uint8_t *buff = timer_pointer_of(p)->buf; + cmdpacket_t cp = (cmdpacket_t)buff; + ssize_t numbytes = 0, offset = 0; + while( + offset >= CMDPACKET_HEAD_LEN + || (numbytes = recv(accept_fd, buff+offset, CMDPACKET_HEAD_LEN-offset, MSG_WAITALL)) > 0 + ) { + touch_timer(p); + offset += numbytes; + #ifdef DEBUG + printf("[handle] Get %zd bytes, total: %zd.\n", numbytes, offset); + #endif + if(offset < CMDPACKET_HEAD_LEN) break; + if(offset < CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen)) { + ssize_t toread = CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen)-offset; + numbytes = recv(accept_fd, buff+offset, toread, MSG_WAITALL); + if(numbytes != toread) break; + else { + offset += numbytes; + #ifdef DEBUG + printf("[handle] Get %zd bytes, total: %zd.\n", numbytes, offset); + #endif + } + } + numbytes = CMDPACKET_HEAD_LEN+(ssize_t)(cp->datalen); // 暂存 packet len + if(offset < numbytes) break; + #ifdef DEBUG + printf("[handle] Decrypt %d bytes data...\n", (int)cp->datalen); + #endif + if(cp->cmd <= CMDEND) { + if(!cmdpacket_decrypt(cp, index, cfg.pwd)) { + cp->data[cp->datalen] = 0; + timer_pointer_of(p)->dat = (char*)cp->data; + timer_pointer_of(p)->numbytes = (ssize_t)(cp->datalen); + printf("[normal] Get %zd bytes packet with cmd: %d, data: %s\n", offset, cp->cmd, cp->data); + switch(cp->cmd) { + case CMDGET: + if(!has_dict_opened && !s1_get(timer_pointer_of(p))) goto CONV_END; + break; + case CMDCAT: + if(!has_dict_opened && !send_all(timer_pointer_of(p))) goto CONV_END; + break; + case CMDMD5: + if(!has_dict_opened && !s5_md5(timer_pointer_of(p))) goto CONV_END; + break; + case CMDACK: + case CMDEND: + default: goto CONV_END; break; + } + } else { + puts("Decrypt normal data failed"); break; - case CMDCAT: - if(!has_dict_opened && !send_all(timer_pointer_of(p))) goto CONV_END; + } + } else if(cp->cmd <= CMDDAT) { + if(!cmdpacket_decrypt(cp, index, cfg.sps)) { + cp->data[cp->datalen] = 0; + timer_pointer_of(p)->dat = (char*)cp->data; + timer_pointer_of(p)->numbytes = (ssize_t)(cp->datalen); + printf("[super] Get %zd bytes packet with data: %s\n", offset, cp->data); + switch(cp->cmd) { + case CMDSET: + if(!has_dict_opened && !s2_set(timer_pointer_of(p))) goto CONV_END; + break; + case CMDDEL: + if(!has_dict_opened && !s4_del(timer_pointer_of(p))) goto CONV_END; + break; + case CMDDAT: + if(!has_dict_opened && !s3_set_data(timer_pointer_of(p))) goto CONV_END; + break; + default: goto CONV_END; break; + } + } else { + puts("Decrypt super data failed"); break; - case CMDMD5: - if(!has_dict_opened && !s5_md5(timer_pointer_of(p))) goto CONV_END; - break; - case CMDACK: - case CMDEND: - default: goto CONV_END; break; } } else { - puts("Decrypt normal data failed"); + puts("Invalid command"); break; } - } else if(cp->cmd <= CMDDAT) { - if(cmdpacket_decrypt(cp, index, cfg.sps)) { - cp->data[cp->datalen] = 0; - timer_pointer_of(p)->dat = (char*)cp->data; - timer_pointer_of(p)->numbytes = (ssize_t)(cp->datalen); - printf("[super] Get %zd bytes packet with data: %s\n", offset, cp->data); - switch(cp->cmd) { - case CMDSET: - if(!has_dict_opened && !s2_set(timer_pointer_of(p))) goto CONV_END; - break; - case CMDDEL: - if(!has_dict_opened && !s4_del(timer_pointer_of(p))) goto CONV_END; - break; - case CMDDAT: - if(!has_dict_opened && !s3_set_data(timer_pointer_of(p))) goto CONV_END; - break; - default: goto CONV_END; break; - } - } else { - puts("Decrypt super data failed"); - break; - } - } else { - puts("Invalid command"); - break; + if(offset > numbytes) { + offset -= numbytes; + memmove(buff, buff+numbytes, offset); + numbytes = 0; + } else offset = 0; + #ifdef DEBUG + printf("Offset after analyzing packet: %zd\n", offset); + #endif } - if(offset > numbytes) { - offset -= numbytes; - memmove(buff, buff+numbytes, offset); - numbytes = 0; - } else offset = 0; - #ifdef DEBUG - printf("Offset after analyzing packet: %zd\n", offset); - #endif + CONV_END: puts("Conversation end"); + puts("Thread job finished normally"); + pthread_rwlock_wrlock(&timer_pointer_of(p)->mb); + timer_pointer_of(p)->isbusy = 0; + pthread_mutex_lock(&timer_pointer_of(p)->mc); + pthread_rwlock_unlock(&timer_pointer_of(p)->mb); + pthread_cond_wait(&timer_pointer_of(p)->c, &timer_pointer_of(p)->mc); + pthread_mutex_unlock(&timer_pointer_of(p)->mc); + puts("Thread wakeup"); } - CONV_END: puts("Conversation end"); pthread_cleanup_pop(1); - puts("Thread exited normally"); } static void accept_client(int fd) { @@ -737,7 +773,12 @@ static void accept_client(int fd) { while(1) { puts("Ready for accept, waitting..."); int p = 0; - while(p < THREADCNT && timers[p].thread) p++; + while(p < THREADCNT) { + pthread_rwlock_rdlock(&timers[p].mb); + if(!timers[p].isbusy) break; + pthread_rwlock_unlock(&timers[p].mb); + p++; + } if(p >= THREADCNT) { puts("Max thread cnt exceeded"); sleep(1); @@ -769,12 +810,17 @@ static void accept_client(int fd) { timer->index = p; timer->touch = time(NULL); reset_seq(p); - if (pthread_create(&timer->thread, &attr, (void *)&handle_accept, timer)) { + if(timer->thread) { + pthread_mutex_lock(&timer->mc); + pthread_cond_signal(&timer->c); // wakeup thread + pthread_mutex_unlock(&timer->mc); + puts("Pick thread from pool"); + } else if (pthread_create(&timer->thread, &attr, (void *)&handle_accept, timer)) { perror("Error creating thread"); cleanup_thread(timer); + pthread_rwlock_unlock(&timer->mb); continue; - } - puts("Creating thread succeeded"); + } else puts("Creating thread succeeded"); } } diff --git a/server.h b/server.h index 7ea25db..7217c83 100644 --- a/server.h +++ b/server.h @@ -3,11 +3,16 @@ #include -#define THREADCNT 32 -#define MAXWAITSEC 8 - +#ifndef THREADCNT + #define THREADCNT 32 +#endif +#ifndef MAXWAITSEC + #define MAXWAITSEC 8 +#endif +#ifndef DICTPOOLBIT // DICTPOOLBIT must be lower than 4*8 = 32 -#define DICTPOOLBIT 16 + #define DICTPOOLBIT 16 +#endif enum server_cmd_t {CMDGET, CMDCAT, CMDMD5, CMDACK, CMDEND, CMDSET, CMDDEL, CMDDAT}; enum server_ack_t {ACKNONE=0b0000011, ACKSUCC=0b0010011, ACKDATA=0b0100011, ACKNULL=0b0110011, ACKNEQU=0b1000011, ACKERRO=0b1010011}; @@ -16,7 +21,7 @@ typedef enum server_cmd_t server_cmd_t; typedef enum server_ack_t server_ack_t; struct cmdpacket_t { - uint8_t cmd; // SERVERCMD or SERVERACK + uint8_t cmd; // high 1bit: undefined; low 7 bits: SERVERCMD or SERVERACK uint8_t datalen; // data len is less than 255 uint8_t md5[16]; // md5 digest of data below uint8_t data[]; // with TEA encoding, 64 bytes will be 160 bytes @@ -24,6 +29,6 @@ struct cmdpacket_t { typedef struct cmdpacket_t* cmdpacket_t; #define CMDPACKET_HEAD_LEN (1+1+16) -#define CMDPACKET_LEN_MAX (CMDPACKET_HEAD_LEN+255) +#define CMDPACKET_LEN_MAX (CMDPACKET_HEAD_LEN+UINT8_MAX) #endif /* _SERVER_H_ */