diff --git a/conf/cert_store.ini b/conf/cert_store.ini index 147e201..1e1ce9b 100644 --- a/conf/cert_store.ini +++ b/conf/cert_store.ini @@ -13,7 +13,9 @@ expire_after = 30 def-ca-path = ../ca [NTC_MAAT] #ÅäÖüÓÔØÄ£Ê½£¬1ΪʹÓñ¾µØjson£¬0ΪʹÓÃÅäÖ÷ַ¢ÍøÂçÏ·¢µÄÎļþ -maat_json_switch=1 +maat_json_switch=2 +#µ±¼ÓÔØÄ£Ê½ÎªÍøÂçÏ·¢Ê±£¬ÉèÖÃɨÃèÅäÖÃÐ޸ļä¸ô(s) +effective_interval=1 #Ö¸¶¨ÅäÖÿâ±íÎļþλÖà table_info=../conf/table_info.conf #ÔöÁ¿ÅäÖÃÎļþ·¾¶ @@ -25,9 +27,12 @@ pxy_obj_keyring=../conf/pxy_obj_keyring.json [LIBEVENT] #±¾µØ¼à¿Ø¶Ë¿ÚºÅ£¬Ä¬ÈÏΪ9991 port = 9991 -[REDIS] -#Ö¸¶¨Redsi·þÎñÆ÷IPµØÖ·ºÍ¶Ë¿ÚºÅ +[CERTSTORE_REDIS] ip = 127.0.0.1 port = 6379 - +[MAAT_REDIS] +#Ö¸¶¨Redsi·þÎñÆ÷IPµØÖ·ºÍ¶Ë¿ÚºÅ +ip = 192.168.11.243 +port = 6379 +dbindex = 4 diff --git a/conf/pxy_obj_keyring.json b/conf/pxy_obj_keyring.json index 04550a5..6545772 100644 --- a/conf/pxy_obj_keyring.json +++ b/conf/pxy_obj_keyring.json @@ -73,13 +73,15 @@ { "table_name": "PXY_OBJ_KEYRING", "table_content": [ - "1\t1\tname_01\troot\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t15\trsa2048\tnull\t1", - "2\t1\tname_02\troot\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t90\trsa2048\tnull\t1", - "3\t1\tname_03\troot\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t30\trsa2048\tnull\t1", - "4\t1\tname_04\tend-entity\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t30\trsa2048\tnull\t1", - "5\t1\tname_05\tintermediate\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t30\trsa2048\tnull\t0", - "6\t1\tname_06\tintermediate\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer\t30\trsa2048\tnull\t1", - "256\t1\tinsec\troot\t/home/fengweihao/workspace/cert_store/ca/mesalab-insec-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-insec-cert.cer\t30\trsa2048\tnull\t1" + "1\t1\tname_01\troot\t/test/01\t/test/01\t15\trsa2048\tURI:http://www.test.com\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer", + "2\t1\tname_02\troot\t/test/01\t/test/01\t90\trsa2048\tnull\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer", + "3\t1\tname_03\troot\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer", + "4\t1\tname_04\troot\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer", + "5\t1\tname_05\troot\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-ca-cert.cer", + "6\t1\tname_06\tintermediate\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/01/server.key\t/home/fengweihao/workspace/01/test01.p12", + "9\t1\tname_06\tend-entity\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/01/server.key\t/home/fengweihao/workspace/01/test02.p12", + "8\t1\tname_06\tintermediate\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/01/server.key\t/home/fengweihao/workspace/01/test02.p12", + "256\t1\tinsec\troot\t/test/01\t/test/01\t30\trsa2048\tnull\t1\t/home/fengweihao/workspace/cert_store/ca/mesalab-insec-cert.key\t/home/fengweihao/workspace/cert_store/ca/mesalab-insec-cert.cer" ] } ] diff --git a/conf/table_info.conf b/conf/table_info.conf index c04b50c..e82d0f8 100644 --- a/conf/table_info.conf +++ b/conf/table_info.conf @@ -17,4 +17,4 @@ #id name type src_charset dst_charset do_merge cross_cache quick_mode 1 COMPILE compile 2 GROUP group -3 PXY_OBJ_KEYRING plugin 8 +3 PXY_OBJ_KEYRING plugin {"valid":10,"foreign":"11,12"} diff --git a/src/Makefile b/src/Makefile index 6163a7b..2f03453 100644 --- a/src/Makefile +++ b/src/Makefile @@ -51,7 +51,7 @@ OBJS += $(OBJS_$(dir)) LDFLAGS_GLOBAL += -L ./lib -lapps -lcrypto -lssl -levent -lhiredis LDFLAGS_GLOBAL += -L ./lib -lMESA_htable -lMESA_field_stat2 -lMESA_handle_logger -lMESA_prof_load LDFLAGS_GLOBAL += \ - -lpthread -lcrypt -lmaatframe -lm -lz -ldl -lstdc++ + -lpthread -lcrypt -lm -lz -ldl -lmaatframe -lstdc++ CFLAGS_LOCAL = -std=gnu99 -g -O3 -W -Wall \ -I.\ diff --git a/src/cert_conf.c b/src/cert_conf.c index c9106c3..5d7835c 100644 --- a/src/cert_conf.c +++ b/src/cert_conf.c @@ -22,7 +22,8 @@ struct config_bucket_t certConfig = { .thread_nu = 1, .expire_after = 30, .def_path = "/home/test", - .addr_t = {9995, 3336, "0.0.0.0"}, + .addr_t = {9995, 6379, "0.0.0.0", 0, 6379, "0.0.0.0"}, + .keyring = {0, 0, NULL, NULL}, }; struct config_bucket_t *cert_default_config() @@ -68,17 +69,36 @@ static int load_module_config(char *config) goto finish; } - xret = MESA_load_profile_string_nodef(config, "REDIS", "ip", rte->addr_t.r_ip, 16); + xret = MESA_load_profile_string_nodef(config, "MAAT_REDIS", "ip", rte->addr_t.maat_ip, 16); if (xret < 0){ - mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Ip invalid"); + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Maat redis ip invalid"); goto finish; } - xret = MESA_load_profile_short_nodef(config, "REDIS", "port", (short *)&(rte->addr_t.r_port)); + xret = MESA_load_profile_short_nodef(config, "MAAT_REDIS", "port", (short *)&(rte->addr_t.maat_port)); if (xret < 0){ - mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis Port invalid"); + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Maat redis port invalid"); goto finish; } + + xret = MESA_load_profile_short_nodef(config, "MAAT_REDIS", "dbindex", (short *)&(rte->addr_t.dbindex)); + if (xret < 0){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Maat redis dbindex invalid"); + goto finish; + } + + xret = MESA_load_profile_string_nodef(config, "CERTSTORE_REDIS", "ip", rte->addr_t.store_ip, 16); + if (xret < 0){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Certsotre redis ip invalid"); + goto finish; + } + + xret = MESA_load_profile_short_nodef(config, "CERTSTORE_REDIS", "port", (short *)&(rte->addr_t.store_port)); + if (xret < 0){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Certsotre redis port invalid"); + goto finish; + } + finish: return xret; } @@ -111,6 +131,10 @@ static int load_maat_config(char *config) } if (maat_t->maat_json_switch == 0){ + xret = MESA_load_profile_uint_nodef(config, "NTC_MAAT", "effective_interval", &(maat_t->effective_interval_s)); + if (xret < 0){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Reading the interval of scan failed"); + } xret = MESA_load_profile_string_nodef(config, "NTC_MAAT", "inc_cfg_dir", maat_t->inc_cfg_dir, 128); if (xret < 0 && !rt_file_exsit( maat_t->inc_cfg_dir)){ mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Read the table info failed or the (%s) does not exist", diff --git a/src/cert_conf.h b/src/cert_conf.h index 8f710e1..f7e16c8 100644 --- a/src/cert_conf.h +++ b/src/cert_conf.h @@ -40,22 +40,29 @@ struct pxy_obj_keyring{ char public_algo[256]; uint64_t expire_after; int is_valid; + STACK_OF(X509) *stack_ca; }; struct key_ring_list { + int updata_type; uint64_t sum_cnt; MESA_htable_handle htable, oldhtable; }; struct _initer_addr_t{ - uint16_t e_port; /* libevent prot*/ - uint16_t r_port; /* redis port*/ - char r_ip[16]; /* redis ip */ + uint16_t e_port; /*libevent prot*/ + uint16_t maat_port; /*maat redis port*/ + char maat_ip[16]; /*maat redis ip */ + int dbindex; /*maat redis dbindex*/ + + uint16_t store_port; /*store redis port */ + char store_ip[16]; /*store redis ip*/ }; struct ntc_maat_t{ - unsigned int maat_json_switch; + unsigned int maat_json_switch; + unsigned int effective_interval_s; char info_path[128]; char pxy_path[128]; char inc_cfg_dir[128]; diff --git a/src/cert_session.c b/src/cert_session.c index 3ae232d..fd47283 100644 --- a/src/cert_session.c +++ b/src/cert_session.c @@ -21,12 +21,14 @@ #include #include #include +#include #include "rt_string.h" #include "rt_common.h" #include "rt_stdlib.h" #include "rt_file.h" #include "rt_time.h" +#include "rt_tmr.h" #include "json.h" #include "cert_conf.h" @@ -47,11 +49,18 @@ #define WAIT_FOR_EFFECTIVE_US 1000*1000 -#define SG_DATA_SIZE 4096 +#define SG_DATA_SIZE 8192 #define SG_INSEC_ID 256 -#define DEFAULT_PRIVATEKEY_NAME "mesalab-def-cert.key" -#define DEFAULT_CA_CERTIFICATE "mesalab-def-cert.cer" +#define LOCAL_USER_PEN 1 +#define LOCAL_USER_DER 2 +#define LOCAL_USER_P12 3 + +#define DEFAULT_PRIVATEKEY_NAME "mesalab-ca-cert.key" +#define DEFAULT_CA_CERTIFICATE "mesalab-ca-cert.cer" + +#define CM_UPDATE_TYPE_FULL 1 +#define CM_UPDATE_TYPE_INC 2 static libevent_thread *threads; @@ -168,6 +177,146 @@ err: return 0; } +static X509* base_load_pkcs12(BIO *in, EVP_PKEY **pkey, X509 **x, STACK_OF(X509) **ca) +{ + PKCS12 *p12; + const char *pass = ""; + + X509 *_x = NULL; + EVP_PKEY *_pkey; + STACK_OF(X509) *_ca = NULL; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + p12 = d2i_PKCS12_bio(in, NULL); + if (p12 == NULL) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error loading PKCS12 file"); + goto finish; + } + if (!PKCS12_parse(p12, pass, &_pkey, &_x, &_ca)) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error parsing PKCS#12 file"); + goto finish; + } + + if (x) + *x = _x; + if (pkey) + *pkey = _pkey; + if (ca) + *ca = _ca; + + finish: + if (p12) + PKCS12_free(p12); + return _x; +} + +static X509 * +cert_base_load_x509 (BIO * cert, STACK_OF(X509) **stack_ca, int iFormat) +{ + X509 *x = NULL; + + switch (iFormat) + { + case LOCAL_USER_DER: + x = d2i_X509_bio (cert, NULL); + break; + case LOCAL_USER_PEN: + x = PEM_read_bio_X509 (cert, NULL, NULL, NULL); + break; + case LOCAL_USER_P12: + x = base_load_pkcs12(cert, NULL, &x, stack_ca); + break; + default: + break; + } + return x; +} + +static X509 * +cert_load_x509(char *file, STACK_OF(X509) **stack_ca) +{ + BIO *in = NULL; + X509 *x509 = NULL; + + if(!file){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Input cert file is empty."); + goto finish; + } + + if ((in = BIO_new(BIO_s_file())) == NULL) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Bio malloc failed."); + goto finish; + } + if (BIO_read_filename(in, file) <= 0) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error opening %s", file); + goto finish; + } + + /**try pem */ + if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_PEN)) != NULL) + goto end; + (void)BIO_reset (in); + if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_P12)) != NULL) + goto end; + (void)BIO_reset (in); + if ((x509 = cert_base_load_x509(in, stack_ca, LOCAL_USER_DER)) != NULL) + goto end; +end: + BIO_free (in); + in = NULL; +finish: + return x509; +} + +EVP_PKEY * cert_base_key_x509 (BIO * bio, int iFormat, char *strPwd) +{ + EVP_PKEY *pkey = NULL; + + switch (iFormat){ + case LOCAL_USER_PEN: + pkey = PEM_read_bio_PrivateKey (bio, NULL, NULL, strPwd); + break; + case LOCAL_USER_P12: + base_load_pkcs12(bio, &pkey, NULL, NULL); + break; + default: + break; + } + + return pkey; +} + +EVP_PKEY * cert_load_key(char *keyfile) +{ + EVP_PKEY *pkey = NULL; + BIO *in = NULL; + + if(!keyfile){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Input key file is empty."); + goto finish; + } + if ((in = BIO_new(BIO_s_file())) == NULL) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Bio malloc failed."); + goto finish; + } + if (BIO_read_filename(in, keyfile) <= 0) { + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Error opening %s\n", keyfile); + goto finish; + } + + if ((pkey = cert_base_key_x509 (in, LOCAL_USER_PEN, "")) != NULL) + goto finish; + (void)BIO_reset (in); + if ((pkey = cert_base_key_x509 (in, LOCAL_USER_P12, "")) != NULL) + goto finish; +finish: + if (in != NULL) + BIO_free (in); + return pkey; +} + static void key_ring_free(void *data) { struct pxy_obj_keyring *pxy_obj = NULL; @@ -265,6 +414,8 @@ ssl_x509_v3ext_copy_by_nid(X509 *crt, X509 *origcrt, int nid) return 1; } + +/**todo Use rules to determine if an sni exists */ static int x509_alt_name_cmp(unsigned char *name, char *extraname) { @@ -656,7 +807,7 @@ int redis_rsync_init(struct event_base *base, struct redisAsyncContext **cl_ctx) int xret = -1; struct config_bucket_t *redis = cert_default_config(); - *cl_ctx = redisAsyncConnect(redis->addr_t.r_ip, redis->addr_t.r_port); + *cl_ctx = redisAsyncConnect(redis->addr_t.store_ip, redis->addr_t.store_port); if((*cl_ctx)->err ) { mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Redis Connect error : %s", (*cl_ctx)->errstr); goto finish; @@ -825,14 +976,18 @@ err: static int x509_online_append(struct x509_object_ctx *def, X509 *origin, int id, - char *sni, char *root, char *sign, char *pkey) + char *sni, char *root, char *sign, + char *pkey, STACK_OF(X509) **stack_ca) { void *odata = NULL; int _expire = 0; char *_crl = NULL; X509 *_root = NULL; EVP_PKEY *_key = NULL; struct key_ring_list *keyring = &cert_default_config()->keyring; - + if (keyring->htable == NULL){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "The approval certificate chain is empty"); + goto finish; + } odata = MESA_htable_search(keyring->htable, (const uchar *)&id, sizeof(int)); if ( !odata ){ _root = def->root; @@ -842,19 +997,23 @@ x509_online_append(struct x509_object_ctx *def, X509 *origin, int id, } else { struct pxy_obj_keyring *pxy_obj = (struct pxy_obj_keyring *)odata; if (pxy_obj->is_valid != 1){ - id = SG_INSEC_ID; - odata = MESA_htable_search(keyring->htable, (const uchar *)&id, sizeof(int)); - if ( !odata){ - mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Read insecure certificate failed"); - goto finish; - } - pxy_obj = (struct pxy_obj_keyring *)odata; + pxy_obj->root = def->root; + pxy_obj->key = def->key; + }else{ if (!STRCMP(pxy_obj->type, "end-entity")){ + mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "The certificate(%d) type is an entity certificate", + pxy_obj->id); + *stack_ca = pxy_obj->stack_ca; x509_get_msg_from_ca(pxy_obj->root, sign); x509_get_private_key(pxy_obj->key, pkey); goto finish; } + if (!STRCMP(pxy_obj->type, "intermediate")){ + mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "The certificate(%d) type is intermediate, chain address %p", + pxy_obj->id, pxy_obj->stack_ca); + *stack_ca = pxy_obj->stack_ca; + } } _root = pxy_obj->root; _key = pxy_obj->key; @@ -994,8 +1153,9 @@ web_json_table_add(char *privatekey, char *sign, static int redis_clnt_pdu_send(struct request_t *request, redisAsyncContext *c) { - int xret = -1; + int xret = -1, i = 0; int expire_after; + STACK_OF(X509) *stack_ca = NULL; uint64_t startTime = 0, endTime = 0; libevent_thread *info = threads + request->thread_id; char sign[SG_DATA_SIZE] = {0}, pkey[SG_DATA_SIZE] = {0}; @@ -1004,7 +1164,7 @@ redis_clnt_pdu_send(struct request_t *request, redisAsyncContext *c) startTime = rt_time_ns(); expire_after = x509_online_append(&info->def, request->origin, request->keyring_id, request->sni, - root, sign, pkey); + root, sign, pkey, &stack_ca); if (sign[0] == '\0' && pkey[0] == '\0'){ mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to sign certificate"); evhttp_send_error(request->evh_req, HTTP_NOTFOUND, 0); @@ -1018,10 +1178,22 @@ redis_clnt_pdu_send(struct request_t *request, redisAsyncContext *c) FS_internal_operate(SGstats.handle, info->column_ids, SGstats.line_ids[3], FS_OP_SET, info->diffTime); FS_internal_operate(SGstats.handle, info->field_ids, 0, FS_OP_ADD, 1); - printf("%s\n", sign); - char *chain[6] ={0}; - chain[0] = root; - chain[1] = sign; + char _chain[4][SG_DATA_SIZE]; + char *chain[6] = {0}; + if (stack_ca){ + for (i = 0; i < sk_X509_num(stack_ca); i++){ + x509_get_msg_from_ca(sk_X509_value(stack_ca, i), _chain[i]); + chain[i] = _chain[i]; + } + if (root[0] != '\0'){ + chain[i] = root; + i++; + } + chain[i] = sign; + }else{ + chain[0] = root; + chain[1] = sign; + } web_json_table_add(pkey, sign, chain, &request->odata); if (NULL == c){ @@ -1095,6 +1267,23 @@ void redis_get_callback(redisAsyncContext *c, void *r, void *privdata) return; } +int x509_privatekey_init2(char * private_file, char * public_file, + EVP_PKEY **key, X509 **root, STACK_OF(X509) **stack_ca) +{ + if ((*root = cert_load_x509(public_file, stack_ca)) == NULL ){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Application for x509 failed"); + goto finish; + } + + if ((*key = cert_load_key(private_file)) == NULL){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Private key read failed"); + goto finish; + } + +finish: + return 0; +} + int x509_privatekey_init(char *private_file, char *public_file, EVP_PKEY **key, X509 **root) { @@ -1362,7 +1551,7 @@ int redis_sync_init(struct redisContext **c) struct timeval timeout = { 1, 500000 }; // 1.5 seconds - *c = redisConnectWithTimeout(redis->addr_t.r_ip, redis->addr_t.r_port, timeout); + *c = redisConnectWithTimeout(redis->addr_t.store_ip, redis->addr_t.store_port, timeout); if (*c == NULL || (*c)->err) { if (*c) { mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Sync connection error: %s", (*c)->errstr); @@ -1428,6 +1617,7 @@ static void *pthread_worker_libevent(void *arg) mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "couldn'thread create evhttp. Exiting."); goto error; } + thread->base = base; /* Context initialization */ xret = task_private_init(base, thread); @@ -1503,6 +1693,40 @@ fs_screen_preview(libevent_thread *thread) return 0; } +static void +redis_link_detection(uint32_t __attribute__((__unused__)) uid, + int __attribute__((__unused__))argc, + char **argv) +{ + int tid = 0, xret = 0; + libevent_thread *info = NULL; + libevent_thread *threads = (libevent_thread *)argv; + + unsigned int thread_nu = cert_default_config()->thread_nu; + for (tid = 0; tid < (int)thread_nu; tid++) { + info = threads + tid; + if(info->cl_ctx->err != 0){ + if (info->sync) + redisFree(info->sync); + + xret = redis_sync_init(&info->sync); + if (xret < 0 || !info->sync){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect sync redis failed", tid); + continue; + }else{ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect sync redis success", tid); + } + + xret = redis_rsync_init(info->base, &info->cl_ctx); + if (xret < 0 || !info->cl_ctx){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect rsync redis failed", tid); + }else{ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "[%d]trying to connect rsync redis success", tid); + } + } + } +} + static int libevent_socket_init() { @@ -1549,7 +1773,17 @@ libevent_socket_init() goto finish; } } - +#ifdef RT_TMR_ADVANCED + /*Create timers to monitor redis connections **/ + uint32_t tm_link_detetion = 0; + tm_link_detetion = tmr_create(1, "Redis link detection", + redis_link_detection, 1, (char **)threads, 5); + if (((int32_t)tm_link_detetion < 0)){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "%s", + "Can not create link-detection timer for redis\n"); + } + tmr_start(tm_link_detetion); +#endif FOREVER{ sleep(1); } @@ -1585,8 +1819,10 @@ void sigproc(int __attribute__((__unused__))sig) thread = threads + tid; if (thread->sync){ redisAsyncDisconnect(thread->cl_ctx); + free(thread->cl_ctx); redisFree(thread->sync); } + event_base_free(thread->base); key_ring_list_destroy(rte->keyring.htable); key_ring_list_destroy(rte->keyring.oldhtable); } @@ -1641,12 +1877,12 @@ static int mesa_fiel_stat_init() void Maat_read_entry_start_cb(int update_type, void* u_para) { -#define CM_UPDATE_TYPE_FULL 1 -#define CM_UPDATE_TYPE_INC 2 struct key_ring_list *keyring = (struct key_ring_list *)u_para; - if (update_type != CM_UPDATE_TYPE_FULL) + if (update_type != CM_UPDATE_TYPE_FULL){ + keyring->updata_type = 2; goto finish; + } if (keyring->oldhtable) key_ring_list_destroy(keyring->oldhtable); @@ -1654,6 +1890,7 @@ void Maat_read_entry_start_cb(int update_type, void* u_para) /*Keyring list initialization **/ keyring->oldhtable = key_ring_list_create(); keyring->sum_cnt = 0; + keyring->updata_type = 1; mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "The initial key ring list was successful, addr is %p", keyring->oldhtable); finish: @@ -1666,6 +1903,9 @@ Maat_read_entry_cb(int __attribute__((__unused__))table_id, const char* table_li { int xret = 0; struct pxy_obj_keyring *pxy_obj = NULL; + MESA_htable_handle htable = NULL; + char __attribute__((__unused__))_priv_file[512] = {0}; + char __attribute__((__unused__))_publi_file[512] = {0}; char private_file[512] = {0}, public_file[512] = {0}; struct key_ring_list *keyring = (struct key_ring_list *)u_para; @@ -1676,19 +1916,34 @@ Maat_read_entry_cb(int __attribute__((__unused__))table_id, const char* table_li goto finish; } memset(pxy_obj, 0, sizeof(struct pxy_obj_keyring)); - sscanf(table_line, "%d\t%d\t%s\t%s\t%s\t%s\t%lu\t%s\t%s\t%d", &pxy_obj->id, &pxy_obj->service, pxy_obj->name, - pxy_obj->type, private_file, public_file, &pxy_obj->expire_after, pxy_obj->public_algo, - pxy_obj->ctl, &pxy_obj->is_valid); - xret = x509_privatekey_init(private_file, public_file, &pxy_obj->key, &pxy_obj->root); - if (xret < 0 || !pxy_obj->key || !pxy_obj->root){ - mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to initialize the x509 certificate, the keyring id is %d", - pxy_obj->id); - goto finish; + if (keyring->updata_type == CM_UPDATE_TYPE_FULL){ + htable = keyring->oldhtable; + }else{ + htable = keyring->htable; } - MESA_htable_add(keyring->oldhtable, (const uchar *)(&(pxy_obj->id)), sizeof(int), pxy_obj); - keyring->sum_cnt++; + sscanf(table_line, "%d\t%d\t%s\t%s\t%s\t%s\t%lu\t%s\t%s\t%d\t%s\t%s", &pxy_obj->id, &pxy_obj->service, pxy_obj->name, + pxy_obj->type, _priv_file, _publi_file, &pxy_obj->expire_after, pxy_obj->public_algo, + pxy_obj->ctl, &pxy_obj->is_valid, private_file, public_file); + + if (pxy_obj->is_valid){ + xret = x509_privatekey_init2(private_file, public_file, &pxy_obj->key, &pxy_obj->root, &pxy_obj->stack_ca); + if (xret < 0 || !pxy_obj->key || !pxy_obj->root){ + mesa_runtime_log(RLOG_LV_FATAL, MODULE_NAME, "Failed to initialize the x509 certificate, the keyring id is %d", + pxy_obj->id); + goto finish; + } + mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "initialize the x509 certificate, the keyring id is %d", + pxy_obj->id); + + MESA_htable_add(htable, (const uchar *)(&(pxy_obj->id)), sizeof(int), pxy_obj); + keyring->sum_cnt++; + }else{ + mesa_runtime_log(RLOG_LV_INFO, MODULE_NAME, "Unapprove keyring id is %d", + pxy_obj->id); + MESA_htable_del(htable, (const uchar *)(&(pxy_obj->id)), sizeof(int), key_ring_free); + } finish: return; @@ -1699,9 +1954,11 @@ void Maat_read_entry_finish_cb(void* u_para) MESA_htable_handle tmphtable = NULL; struct key_ring_list *keyring = (struct key_ring_list *)u_para; - tmphtable = keyring->htable; - keyring->htable = keyring->oldhtable; - keyring->oldhtable = tmphtable; + if (keyring->updata_type == CM_UPDATE_TYPE_FULL){ + tmphtable = keyring->htable; + keyring->htable = keyring->oldhtable; + keyring->oldhtable = tmphtable; + } return; } @@ -1727,13 +1984,14 @@ int sample_plugin_table(Maat_feather_t feather,const char* table_name, int maat_feather_init() { - int wait_second = 0; Maat_feather_t feather = NULL; - int scan_interval_ms = 1, effective_interval_ms = 0; + int scan_interval_ms = 1000; struct config_bucket_t *rte = cert_default_config(); struct ntc_maat_t *maat_t = &rte->maat_t; + int effective_interval_ms = maat_t->effective_interval_s * 1000; + feather = Maat_inter_feather(rte->thread_nu, maat_t->info_path, logging_sc_lid.run_log_handle); Maat_inter_set_feather_opt(feather, MAAT_OPT_INSTANCE_NAME, "certstore", strlen("certstore") + 1); @@ -1744,11 +2002,18 @@ int maat_feather_init() if (maat_t->maat_json_switch == 0){ Maat_inter_set_feather_opt(feather, MAAT_OPT_FULL_CFG_DIR, maat_t->full_cfg_dir, strlen(maat_t->full_cfg_dir)+1); Maat_inter_set_feather_opt(feather, MAAT_OPT_INC_CFG_DIR, maat_t->inc_cfg_dir, strlen(maat_t->inc_cfg_dir)+1); - wait_second = 14; + } + if (maat_t->maat_json_switch == 2){ + Maat_inter_set_feather_opt(feather, MAAT_OPT_REDIS_IP, rte->addr_t.maat_ip, strlen(rte->addr_t.maat_ip)+1); + Maat_inter_set_feather_opt(feather, MAAT_OPT_REDIS_PORT, &rte->addr_t.maat_port, sizeof(rte->addr_t.maat_port)); + Maat_inter_set_feather_opt(feather, MAAT_OPT_REDIS_INDEX, &rte->addr_t.dbindex, sizeof(rte->addr_t.dbindex)); } Maat_inter_set_feather_opt(feather, MAAT_OPT_SCANDIR_INTERVAL_MS,&scan_interval_ms, sizeof(scan_interval_ms)); Maat_inter_set_feather_opt(feather, MAAT_OPT_EFFECT_INVERVAL_MS,&effective_interval_ms, sizeof(effective_interval_ms)); + /***/ + const char* foregin_dir="./foreign_files/"; + Maat_inter_set_feather_opt(feather, MAAT_OPT_FOREIGN_CONT_DIR,foregin_dir, strlen(foregin_dir)+1); Maat_inter_initiate_feather(feather); sample_plugin_table(feather, "PXY_OBJ_KEYRING", @@ -1757,7 +2022,6 @@ int maat_feather_init() Maat_read_entry_finish_cb, &rte->keyring, NULL); - sleep(wait_second); return 0; } diff --git a/src/cert_session.h b/src/cert_session.h index 2a86128..c0c5850 100644 --- a/src/cert_session.h +++ b/src/cert_session.h @@ -27,6 +27,8 @@ typedef struct { rt_pthread_attr *attr; + struct event_base *base; + struct x509_object_ctx def; struct redisAsyncContext *cl_ctx; diff --git a/src/cert_store.c b/src/cert_store.c index 5b1ae0d..90a41a7 100644 --- a/src/cert_store.c +++ b/src/cert_store.c @@ -25,7 +25,7 @@ /* Configure Path */ #if 0 -#define CERT_BASIC_CFG "/usr/local/etc/cert_store.yaml" +#define CERT_BASIC_CFG "/home/ceiec/certstore_run/conf/cert_store.ini" #else #define CERT_BASIC_CFG "../conf/cert_store.ini" #endif @@ -81,8 +81,11 @@ void cert_preview () printf("\r\nBasic Configuration of CertStore \n"); printf("%30s:%45d\n", "The Threads", rte->thread_nu); - printf("%30s:%45s\n", "Redis Ip", rte->addr_t.r_ip); - printf("%30s:%45d\n", "Redis Port", rte->addr_t.r_port); + printf("%30s:%45s\n", "Store Redis Ip", rte->addr_t.store_ip); + printf("%30s:%45d\n", "Store Redis Port", rte->addr_t.store_port); + printf("%30s:%45s\n", "Maat Redis Ip", rte->addr_t.maat_ip); + printf("%30s:%45d\n", "Maat Redis Port", rte->addr_t.maat_port); + printf("%30s:%45d\n", "Maat Redis index", rte->addr_t.dbindex); printf("%30s:%45d\n", "Libevent Port", rte->addr_t.e_port); printf("%30s:%45s\n", "Def Cert Path", rte->def_path); printf("%30s:%45s\n", "Log Directory", logging_sc_lid.run_log_path); @@ -91,6 +94,7 @@ void cert_preview () printf("%30s:%45s\n", "Pxy Obj Keyring", rte->maat_t.pxy_path); } if (rte->maat_t.maat_json_switch == 0){ + printf("%30s:%45d\n", "Scan Interval", rte->maat_t.effective_interval_s); printf("%30s:%45s\n", "Full Cfg Path", rte->maat_t.full_cfg_dir); printf("%30s:%45s\n", "Inc Cfg Path", rte->maat_t.inc_cfg_dir); diff --git a/src/inc/Maat_command.h b/src/inc/Maat_command.h index fbdd9a1..ec4796f 100644 --- a/src/inc/Maat_command.h +++ b/src/inc/Maat_command.h @@ -156,6 +156,8 @@ int Maat_cmd_set_group(Maat_feather_t feather, int group_id, const struct Maat_r //Return -1 for failed. int Maat_cmd_set_line(Maat_feather_t feather,const struct Maat_line_t* line_rule, enum MAAT_OPERATION op); int Maat_cmd_set_lines(Maat_feather_t feather,const struct Maat_line_t** line_rule, int line_num ,enum MAAT_OPERATION op); +int Maat_cmd_set_file(Maat_feather_t feather,const char* key, const char* value, size_t size, enum MAAT_OPERATION op); + //Return the value of key after the increment. //If the key does not exist, it is set to 0 before performing the operation. long long Maat_cmd_incrby(Maat_feather_t feather,const char* key, int increment); diff --git a/src/inc/Maat_rule.h b/src/inc/Maat_rule.h index bcb1546..91d373c 100644 --- a/src/inc/Maat_rule.h +++ b/src/inc/Maat_rule.h @@ -2,11 +2,11 @@ /* *****************Maat Network Flow Rule Manage Framework******** * Maat is the Goddess of truth and justice in ancient Egyptian concept. -* Her feather was the measure that determined whether the souls (considered +* Her feather was the measure that determined whether the souls (considered * to reside in the heart) of the departed would reach the paradise of afterlife * successfully. * Author: zhengchao@iie.ac.cn,MESA -* Version 2018-07-27 huge service_define +* Version 2018-09-25 foreign key and rule tags. * NOTE: MUST compile with G++ * All right reserved by Institute of Infomation Engineering,Chinese Academic of Science 2014~2018 ********************************************************* @@ -105,17 +105,17 @@ struct sub_item_pos_t struct Maat_region_pos_t { - + int region_id; int sub_item_num; - struct sub_item_pos_t sub_item_pos[MAAT_MAX_EXPR_ITEM_NUM]; + struct sub_item_pos_t sub_item_pos[MAAT_MAX_EXPR_ITEM_NUM]; }; struct Maat_hit_detail_t { int config_id;//set <0 if half hit; int hit_region_cnt; - struct Maat_region_pos_t region_pos[MAAT_MAX_HIT_RULE_NUM]; + struct Maat_region_pos_t region_pos[MAAT_MAX_HIT_RULE_NUM]; }; //--------------------HITTING DETAIL DESCRIPTION END @@ -125,7 +125,7 @@ Maat_feather_t Maat_summon_feather(int max_thread_num, const char* ful_cfg_dir, const char* inc_cfg_dir, void*logger);//MESA_handle_logger -//Abondon interface ,left for compatible. +//Abondon interface ,left for compatible. Maat_feather_t Maat_summon_feather_json(int max_thread_num, const char* table_info_path, const char* json_rule, @@ -141,10 +141,10 @@ enum MAAT_INIT_OPT MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. MAAT_OPT_INC_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. MAAT_OPT_JSON_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. - MAAT_OPT_STAT_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. - MAAT_OPT_PERF_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_STAT_ON, //VALUE is NULL, SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_PERF_ON, //VALUE is NULL, SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. MAAT_OPT_STAT_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT: no default. - MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping; + MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping. // 2 return hit pos and regex grouping pos;DEFAULT:0 MAAT_OPT_INSTANCE_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1, no more than 11 bytes.DEFAULT: MAAT_$tableinfo_path$. MAAT_OPT_DECRYPT_KEY, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. @@ -154,15 +154,18 @@ enum MAAT_INIT_OPT MAAT_OPT_CMD_AUTO_NUMBERING, //VALUE is a interger *, 1 or 0, SIZE=sizeof(int). DEFAULT: 1. MAAT_OPT_DEFERRED_LOAD, //VALUE is NULL,SIZE is 0. Default: Deffered initialization OFF. MAAT_OPT_CUMULATIVE_UPDATE_OFF, //VALUE is NULL,SIZE is 0. Default: CUMMULATIVE UPDATE ON. - MAAT_OPT_LOAD_VERSION_FROM, //VALUE is a long long, SIZE=sizeof(long long). Default: Load the Latest. Only valid in redis mode, and maybe failed for too old. + MAAT_OPT_LOAD_VERSION_FROM, //VALUE is a long long, SIZE=sizeof(long long). Default: Load the Latest. Only valid in redis mode, and maybe failed for too old. //This option also disables background update. - MAAT_OPT_ENABLE_UPDATE //VALUE is interger, SIZE=sizeof(int). 1: Enabled, 0:Disabled. DEFAULT: Backgroud update is enabled. Runtime setting is allowed. -}; + MAAT_OPT_ENABLE_UPDATE, //VALUE is interger, SIZE=sizeof(int). 1: Enabled, 0:Disabled. DEFAULT: Backgroud update is enabled. Runtime setting is allowed. + MAAT_OPT_ACCEPT_TAGS, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. Format is a JSON, e.g.{"tags":[{"tag":"location","value":"Beijing/ChaoYang/Huayan/22A"},{"tag":"isp","value":"telecom"}]} + MAAT_OPT_FOREIGN_CONT_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. Specifies a local diretory to store foreign content. Default: []table_info_path]_files + MAAT_OPT_FOREIGN_CONT_LINGER //VALUE is interger *, SIZE=sizeof(int). Greater than 0: delete after VALUE seconds; 0: delete foreign content right after the notification callbacks; Less than 0: NEVER delete. Default: 0. + }; //return -1 if failed, return 0 on success; int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size); enum MAAT_STATE_OPT { - MAAT_STATE_VERSION=1, //Get current maat version. VALUE is long long, SIZE=sizeof(long long). + MAAT_STATE_VERSION=1, //Get current maat version. VALUE is long long, SIZE=sizeof(long long). MAAT_STATE_LAST_UPDATING_TABLE //Query at Maat_finish_callback_t to determine whether this table is the last one to update. VALUE is interger, SIZE=sizeof(int), 1:yes, 0: no }; int Maat_read_state(Maat_feather_t feather, enum MAAT_STATE_OPT type, void* value, int size); @@ -237,7 +240,7 @@ int Maat_similar_scan_string(Maat_feather_t feather,int table_id void Maat_clean_status(scan_status_t* mid); enum MAAT_RULE_OPT { - MAAT_RULE_SERV_DEFINE //VALUE is a char* buffer,SIZE= buffer size. + MAAT_RULE_SERV_DEFINE //VALUE is a char* buffer,SIZE= buffer size. }; int Maat_read_rule(Maat_feather_t feather, const struct Maat_rule_t* rule, enum MAAT_RULE_OPT type, void* value, int size); #endif // H_MAAT_RULE_H_INCLUDE diff --git a/src/inc/moodycamel_maat_rule.h b/src/inc/moodycamel_maat_rule.h index bc8ea8c..3251e09 100644 --- a/src/inc/moodycamel_maat_rule.h +++ b/src/inc/moodycamel_maat_rule.h @@ -17,10 +17,10 @@ enum MAAT_INIT_OPT MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. MAAT_OPT_INC_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. MAAT_OPT_JSON_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default. - MAAT_OPT_STAT_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. - MAAT_OPT_PERF_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_STAT_ON, //VALUE is NULL, SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. + MAAT_OPT_PERF_ON, //VALUE is NULL, SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF. MAAT_OPT_STAT_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT: no default. - MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping; + MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping. // 2 return hit pos and regex grouping pos;DEFAULT:0 MAAT_OPT_INSTANCE_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1, no more than 11 bytes.DEFAULT: MAAT_$tableinfo_path$. MAAT_OPT_DECRYPT_KEY, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT. @@ -32,8 +32,11 @@ enum MAAT_INIT_OPT MAAT_OPT_CUMULATIVE_UPDATE_OFF, //VALUE is NULL,SIZE is 0. Default: CUMMULATIVE UPDATE ON. MAAT_OPT_LOAD_VERSION_FROM, //VALUE is a long long, SIZE=sizeof(long long). Default: Load the Latest. Only valid in redis mode, and maybe failed for too old. //This option also disables background update. - MAAT_OPT_ENABLE_UPDATE //VALUE is interger, SIZE=sizeof(int). 1: Enabled, 0:Disabled. DEFAULT: Backgroud update is enabled. Runtime setting is allowed. -}; + MAAT_OPT_ENABLE_UPDATE, //VALUE is interger, SIZE=sizeof(int). 1: Enabled, 0:Disabled. DEFAULT: Backgroud update is enabled. Runtime setting is allowed. + MAAT_OPT_ACCEPT_TAGS, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. Format is a JSON, e.g.{"tags":[{"tag":"location","value":"Beijing/ChaoYang/Huayan/22A"},{"tag":"isp","value":"telecom"}]} + MAAT_OPT_FOREIGN_CONT_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. Specifies a local diretory to store foreign content. Default: []table_info_path]_files + MAAT_OPT_FOREIGN_CONT_LINGER //VALUE is interger *, SIZE=sizeof(int). Greater than 0: delete after VALUE seconds; 0: delete foreign content right after the notification callbacks; Less than 0: NEVER delete. Default: 0. + }; enum MAAT_STATE_OPT { diff --git a/src/lib/libMESA_htable.so b/src/lib/libMESA_htable.so deleted file mode 100644 index ff7f10b..0000000 Binary files a/src/lib/libMESA_htable.so and /dev/null differ diff --git a/src/rt/rt.mk b/src/rt/rt.mk index 5a4a16d..36480c8 100644 --- a/src/rt/rt.mk +++ b/src/rt/rt.mk @@ -11,6 +11,7 @@ OBJS_$(d) :=\ $(OBJ_DIR)/rt_file.o\ $(OBJ_DIR)/rt_stdlib.o\ $(OBJ_DIR)/rt_string.o\ + $(OBJ_DIR)/rt_tmr.o\ $(OBJ_DIR)/rt_time.o CFLAGS_LOCAL += -I$(d) diff --git a/src/rt/rt_tmr.c b/src/rt/rt_tmr.c new file mode 100644 index 0000000..e47a5e2 --- /dev/null +++ b/src/rt/rt_tmr.c @@ -0,0 +1,212 @@ +/************************************************************************* + > File Name: rt_tmr.c + > Author: + > Mail: + > Created Time: 2018å¹´09月19æ—¥ 星期三 15æ—¶57分58ç§’ + ************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt_stdlib.h" +#include "rt_sync.h" +#include "rt_string.h" +#include "rt_common.h" + +static int init; + +enum { + ALLOWED, + FORBIDDEN +}; + +struct tmr_task{ + rt_pthread pid; + + rt_pthread_attr *attr; + + void * (*routine)(void *); +}; + +struct timer_t{ + +#define TMR_INVALID -1 + + int module; + + /** unique id */ + uint32_t uid; + + /** Make sure that allocate desc member with malloc like function. */ + char *desc; + + /** in ms */ + int64_t interval; + + int64_t curr_ticks; + + enum {TMR_PERIODIC, TMR_ASHOT} type; + + enum {TMR_STOPPED, TMR_STARTED} status; + + void (*routine)(uint32_t uid, int argc, char **argv); + + int argc; + + char **argv; + + int recycle; +}; + +struct timer_t *_this; + +static volatile atomic64_t g_sys_cur_ticks = ATOMIC_INIT(0); + +struct timer_t * +tmr_set(uint32_t uid, + void (*proc)(struct timer_t *t)) +{ + uid = uid; + + if(likely(proc)) + proc(_this); + + return _this; +} + +static void tmr_enable(struct timer_t *t) +{ + t->status = TMR_STARTED; +} + +static void tmr_disable(struct timer_t *t) +{ + t->status = TMR_STOPPED; +} + +void tmr_start(uint32_t uid) +{ + tmr_set(uid, tmr_enable); +} + +void tmr_stop(uint32_t uid) +{ + tmr_set(uid, tmr_disable); +} + +static void tmr_handler() +{ + int64_t old_ticks = 0; + + old_ticks = atomic64_add(&g_sys_cur_ticks, 1); + if (likely(_this->status == TMR_STARTED)){ + if (likely(old_ticks >= _this->curr_ticks)) { + _this->routine(_this->uid, _this->argc, _this->argv); + if (likely(TMR_ASHOT == _this->type)) + _this->status= TMR_STOPPED; + else + _this->curr_ticks = old_ticks + _this->interval; + } + } +} + +static void realtimer_init() +{ + static struct itimerval tmr; + + signal(SIGALRM, (void *) tmr_handler); + tmr.it_interval.tv_sec = 1; + tmr.it_interval.tv_usec = 0; + tmr.it_value.tv_sec = 1; + tmr.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &tmr, NULL); + +} + +static void +tmr_default_routine(uint32_t uid, int __attribute__((__unused__))argc, + char __attribute__((__unused__))**argv) +{ + static int count[2] = {0}; + + count[uid%2] ++; + printf ("default timer [%u, %d] routine has occured\n", uid, count[uid%2]); +} + +static __rt_always_inline__ void * +tmr_alloc() +{ + struct timer_t *t; + + t = kmalloc(sizeof(struct timer_t), MPF_CLR, -1); + if(likely(t)){ + t->uid = TMR_INVALID; + t->routine = tmr_default_routine; + t->interval = 3; //tmr_internal_trans(3); + t->recycle = ALLOWED; + t->type = TMR_ASHOT; + t->status = TMR_STOPPED; + } + return t; +} + +static void * +tmr_daemon(void __attribute__((__unused__))*pv_par ) +{ + FOREVER{ + sleep(86400); + } + return NULL; +} + +uint32_t tmr_create(int module, + const char *desc, + void (*routine)(uint32_t, int, char **), int argc, char **argv, int sec) +{ + uint32_t uid = -1; + + if(unlikely(!desc)){ + goto finish; + } + + _this = (struct timer_t *)tmr_alloc(); + if(unlikely(!_this)){ + goto finish; + } + + _this->module = module; + _this->desc = strdup(desc); + _this->curr_ticks = 0; + _this->interval = sec; + _this->routine = routine ? routine : tmr_default_routine; + _this->type = TMR_PERIODIC; + _this->uid = uid = 1; + _this->recycle = ALLOWED; + _this->status = TMR_STOPPED; + _this->argc = argc; + _this->argv = argv; + + if(likely(init == 0)){ + struct tmr_task *task = (struct tmr_task*)kmalloc(sizeof(struct tmr_task), MPF_CLR, -1); + if (likely(task)){ + if (pthread_create(&task->pid, task->attr, tmr_daemon, NULL)){ + goto finish; + } + if (pthread_detach(task->pid)){ + goto finish; + } + } + init = 1; + realtimer_init(); + } + +finish: + return uid; +} + diff --git a/src/rt/rt_tmr.h b/src/rt/rt_tmr.h new file mode 100644 index 0000000..27318bd --- /dev/null +++ b/src/rt/rt_tmr.h @@ -0,0 +1,25 @@ +/************************************************************************* + > File Name: rt_tmr.h + > Author: + > Mail: + > Created Time: 2018å¹´09月19æ—¥ 星期三 15æ—¶58分04ç§’ + ************************************************************************/ + +#ifndef _RT_TMR_H +#define _RT_TMR_H + +//#define RT_TMR_ADVANCED + +extern void tmr_start(uint32_t uid); +extern void tmr_stop(uint32_t uid); + +/** +* routine: must be a reentrant function. +* An unknown error ocurrs if a thread-safe function called as a routione. +*/ +extern uint32_t tmr_create(int module, + const char *desc, + void (*routine)(uint32_t, int, char **), int argc, char **argv, int sec); + +#endif +