boolean nx_config_cache_get_string(const char *module, const char *key, const char **result) { nx_ctx_t *ctx; nx_cc_item_t *item; char ckey[NX_CONFIG_CACHE_MAX_KEYLEN]; ASSERT(module != NULL); ASSERT(key != NULL); ctx = nx_ctx_get(); if ( apr_snprintf(ckey, sizeof(ckey), "%s/%s", module, key) == sizeof(ckey) ) { nx_panic("config cache key too long, limit is %d bytes", NX_CONFIG_CACHE_MAX_KEYLEN); } CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex)); item = (nx_cc_item_t *) apr_hash_get(ctx->config_cache, ckey, APR_HASH_KEY_STRING); CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex)); if ( item == NULL ) { return ( FALSE ); } if ( (strcmp(item->key, ckey) == 0) && (item->value->type == NX_VALUE_TYPE_STRING) ) { ASSERT(item->value->string != NULL); *result = item->value->string->buf; item->used = TRUE; return ( TRUE ); } return ( FALSE ); }
static void im_ssl_event(nx_module_t *module, nx_event_t *event) { nx_module_input_t *input = NULL; ASSERT(event != NULL); switch ( event->type ) { case NX_EVENT_READ: im_ssl_read(module, event); break; case NX_EVENT_WRITE: im_ssl_write(module, event); break; case NX_EVENT_DISCONNECT: CHECKERR_MSG(apr_socket_data_get((void **) &input, "input", (apr_socket_t *) event->data), "couldn't get input data from socket"); im_ssl_disconnect(input); break; case NX_EVENT_POLL: if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING ) { nx_module_pollset_poll(module, TRUE); } break; default: nx_panic("invalid event type: %d", event->type); } }
static void im_exec_event(nx_module_t *module, nx_event_t *event) { nx_im_exec_conf_t *imconf; nx_exception_t e; ASSERT(event != NULL); imconf = (nx_im_exec_conf_t *) module->config; switch ( event->type ) { case NX_EVENT_DISCONNECT: // FIXME: restart if imconf->restart == TRUE log_warn("im_exec process %s exited", imconf->cmd); imconf->running = FALSE; im_exec_add_restart_event(module); break; case NX_EVENT_READ: try { im_exec_read(module); } catch(e) { log_exception(e); im_exec_add_restart_event(module); } break; case NX_EVENT_POLL: #ifdef WIN32 nx_panic("pollset based im_exec implementation doesn't work on windows"); #else if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING ) { nx_module_pollset_poll(module, TRUE); } break; #endif default: nx_panic("invalid event type: %d", event->type); } }
static void xm_exec_event(nx_module_t *module, nx_event_t *event) { ASSERT(event != NULL); switch ( event->type ) { case NX_EVENT_MODULE_SPECIFIC: xm_exec_reap(module); break; default: nx_panic("invalid event type: %d", event->type); } }
static void pm_norepeat_event(nx_module_t *module, nx_event_t *event) { ASSERT(event != NULL); switch ( event->type ) { case NX_EVENT_DATA_AVAILABLE: pm_norepeat_data_available(module); break; case NX_EVENT_WRITE: pm_norepeat_write(module); break; default: nx_panic("invalid event type: %d", event->type); } }
void nx_config_cache_set_string(const char *module, const char *key, const char *value) { nx_ctx_t *ctx; nx_cc_item_t *item; char ckey[NX_CONFIG_CACHE_MAX_KEYLEN]; ASSERT(module != NULL); ASSERT(key != NULL); ASSERT(value != NULL); ctx = nx_ctx_get(); if ( apr_snprintf(ckey, sizeof(ckey), "%s/%s", module, key) == sizeof(ckey) ) { nx_panic("config cache key too long, limit is %d bytes", NX_CONFIG_CACHE_MAX_KEYLEN); } CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex)); item = (nx_cc_item_t *) apr_hash_get(ctx->config_cache, ckey, APR_HASH_KEY_STRING); CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex)); if ( item != NULL ) { ASSERT(item->value->type == NX_VALUE_TYPE_STRING); nx_value_free(item->value); item->value = nx_value_new_string(value); item->used = TRUE; item->needflush = TRUE; } else { item = malloc(sizeof(nx_cc_item_t)); memset(item, 0, sizeof(nx_cc_item_t)); item->key = strdup(ckey); item->value = nx_value_new_string(value); item->used = TRUE; item->needflush = TRUE; CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex)); apr_hash_set(ctx->config_cache, item->key, APR_HASH_KEY_STRING, (void *) item); CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex)); } }
static void im_tcp_event(nx_module_t *module, nx_event_t *event) { ASSERT(event != NULL); switch ( event->type ) { case NX_EVENT_READ: im_tcp_read(module, event); break; case NX_EVENT_DISCONNECT: im_tcp_got_disconnect(module, event); break; case NX_EVENT_POLL: if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING ) { nx_module_pollset_poll(module, TRUE); } break; default: nx_panic("invalid event type: %d", event->type); } }
static void om_kafka_event(nx_module_t *module, nx_event_t *event) { log_debug("Kafka module event entrypoint"); nx_exception_t e; ASSERT(module != NULL); ASSERT(event != NULL); nx_om_kafka_conf_t* modconf; modconf = (nx_om_kafka_conf_t*) module->config; switch (event->type) { case NX_EVENT_DATA_AVAILABLE: log_debug("Output buflen: %d, bufstart: %d", (int) module->output.buflen, (int) module->output.bufstart); try { om_kafka_write(module); } catch (e) { io_err_handler(module, &e); } break; case NX_EVENT_READ: break; case NX_EVENT_WRITE: break; case NX_EVENT_RECONNECT: break; case NX_EVENT_DISCONNECT: break; case NX_EVENT_TIMEOUT: break; case NX_EVENT_POLL: if (nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING) { nx_module_pollset_poll(module, FALSE); } break; default: nx_panic("invalid event type: %d", event->type); } }
static void parse_kvp(nx_logdata_t *logdata, nx_kvp_ctx_t *ctx, const char *src, size_t len) { nx_string_t *valuestr = NULL; nx_exception_t e; nx_kvp_state_t state = NX_KVP_STATE_KEY_START; char keyname[256]; int keylen = 0; volatile boolean got_keyquote = FALSE; try { int pos = 0; boolean got_valquote = FALSE; for ( pos = 0; pos < (int) len; pos++ ) { // log_info("parse [%c] state: %d", src[pos], state); switch ( state ) { case NX_KVP_STATE_KEY: if ( src[pos] == ctx->keyquotechar ) { if ( got_keyquote == TRUE ) { state = NX_KVP_STATE_KV_DELIMITER; } else { throw_msg("invalid key quotation in key-value pair"); } } else if ( (ctx->kvdelimiter == '\0') && IS_KVDELIMITERCHAR(src[pos]) ) { ctx->kvdelimiter = src[pos]; state = NX_KVP_STATE_VALUE_START; } else if ( src[pos] == ctx->kvdelimiter ) { state = NX_KVP_STATE_VALUE_START; } else if ( src[pos] == ctx->escapechar ) { state = NX_KVP_STATE_KEY_ESCAPE; } /* Unquoted keys containing space don't work with this, so instead we trim the space at the end else if ( (src[pos] == ' ') && (got_keyquote != TRUE) ) { state = NX_KVP_STATE_KV_DELIMITER; } */ else { if ( keylen < (int) sizeof(keyname) - 1 ) { keyname[keylen] = src[pos]; keylen++; } } break; case NX_KVP_STATE_VALUE_START: if ( src[pos] == ' ' ) { // skip leading space break; } got_valquote = FALSE; ASSERT(valuestr == NULL); valuestr = nx_string_new(); if ( (ctx->valquotechar == '\0') && IS_QUOTECHAR(src[pos]) ) { // auto-detected quotechar ctx->valquotechar = src[pos]; got_valquote = TRUE; } else if ( src[pos] == ctx->valquotechar ) { got_valquote = TRUE; } else { pos--; // handle character in STATE_VALUE } state = NX_KVP_STATE_VALUE; break; case NX_KVP_STATE_VALUE: if ( src[pos] == ctx->valquotechar ) { state = NX_KVP_STATE_KVP_DELIMITER; if ( got_valquote == TRUE ) { } else { if ( valuestr->len > 0) { throw_msg("invalid value quotation in key-value pair: %s", valuestr->buf); } } } else if ( (ctx->kvpdelimiter == '\0') && IS_KVPDELIMITERCHAR(src[pos]) && (got_valquote == FALSE) ) { ctx->kvpdelimiter = src[pos]; // add field-value add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr); valuestr = NULL; state = NX_KVP_STATE_KEY_START; } else if ( (src[pos] == ctx->kvpdelimiter) && (got_valquote == FALSE) ) { // add field-value add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr); valuestr = NULL; state = NX_KVP_STATE_KEY_START; } else if ( src[pos] == ctx->escapechar ) { state = NX_KVP_STATE_VALUE_ESCAPE; } else { // append character to value nx_string_append(valuestr, src + pos, 1); } break; case NX_KVP_STATE_VALUE_ESCAPE: unescape_value(ctx, src[pos], valuestr, got_valquote); state = NX_KVP_STATE_VALUE; break; case NX_KVP_STATE_KV_DELIMITER: if ( src[pos] == ' ' ) { // skip space break; } if ( (ctx->kvdelimiter == '\0') && IS_KVDELIMITERCHAR(src[pos]) ) { ctx->kvdelimiter = src[pos]; state = NX_KVP_STATE_VALUE_START; } else if ( src[pos] == ctx->kvdelimiter ) { state = NX_KVP_STATE_VALUE_START; } break; case NX_KVP_STATE_KVP_DELIMITER: if ( (ctx->kvpdelimiter == '\0') && IS_KVPDELIMITERCHAR(src[pos]) ) { ctx->kvpdelimiter = src[pos]; state = NX_KVP_STATE_KEY_START; add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr); valuestr = NULL; } else if ( src[pos] == ctx->kvpdelimiter ) { state = NX_KVP_STATE_KEY_START; add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr); valuestr = NULL; } break; case NX_KVP_STATE_KEY_START: keylen = 0; got_keyquote = FALSE; if ( src[pos] == ' ' ) { // skip space break; } else if ( (ctx->keyquotechar == '\0') && IS_QUOTECHAR(src[pos]) ) { // auto-detected quotechar ctx->keyquotechar = src[pos]; got_keyquote = TRUE; state = NX_KVP_STATE_KEY; } else if ( src[pos] == ctx->keyquotechar ) { got_keyquote = TRUE; state = NX_KVP_STATE_KEY; } else if ( src[pos] == ctx->escapechar ) { state = NX_KVP_STATE_KEY_ESCAPE; } else if ( src[pos] == ctx->kvpdelimiter ) { // double delimiter, no value for kvp, skip } else { // first character of unquoted key state = NX_KVP_STATE_KEY; if ( keylen < (int) sizeof(keyname) - 1 ) { keyname[keylen] = src[pos]; keylen++; } } break; case NX_KVP_STATE_KEY_ESCAPE: if ( (src[pos] == ctx->escapechar) || (src[pos] == ctx->keyquotechar) ) { if ( keylen < (int) sizeof(keyname) - 1 ) { keyname[keylen] = src[pos]; keylen++; } } else { if ( keylen < (int) sizeof(keyname) - 2 ) { keyname[keylen] = ctx->escapechar; keylen++; keyname[keylen] = src[pos]; keylen++; } } state = NX_KVP_STATE_KEY; break; default: nx_panic("invalid state %d", state); } } } catch(e) { if ( valuestr != NULL ) { nx_string_free(valuestr); } rethrow(e); } switch ( state ) { case NX_KVP_STATE_VALUE: case NX_KVP_STATE_KVP_DELIMITER: add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr); break; case NX_KVP_STATE_KEY_START: ASSERT(valuestr == NULL); break; case NX_KVP_STATE_KV_DELIMITER: case NX_KVP_STATE_KEY: case NX_KVP_STATE_KEY_ESCAPE: case NX_KVP_STATE_VALUE_START: case NX_KVP_STATE_VALUE_ESCAPE: if ( valuestr != NULL ) { nx_string_free(valuestr); } throw_msg("invalid KVP input: '%s' [state: %d]", src, state); break; default: nx_panic("invalid state %d", state); } }
static boolean match_line(nx_value_t *pattern, const char *subject, size_t len) { int pcre_result; if ( pattern->type == NX_VALUE_TYPE_STRING ) { if ( len < pattern->string->len ) { len = pattern->string->len; } if ( strncmp(subject, pattern->string->buf, len) == 0 ) { return ( TRUE ); } } else // REGEXP { int ovector[NX_EXPR_MAX_CAPTURED_FIELDS * 3]; ASSERT(pattern->type == NX_VALUE_TYPE_REGEXP); pcre_result = pcre_exec(pattern->regexp.pcre, NULL, subject, (int) len, 0, 0, ovector, NX_EXPR_MAX_CAPTURED_FIELDS * 3); if ( pcre_result >= 0 ) { // got match return ( TRUE ); } else { switch ( pcre_result ) { case PCRE_ERROR_NOMATCH: log_debug("regexp [%s] doesn't match subject string [%s]", pattern->regexp.str, subject); break; case PCRE_ERROR_NULL: nx_panic("invalid arguments (code, ovector or ovecsize are invalid)"); case PCRE_ERROR_BADOPTION: nx_panic("invalid option in options parameter"); case PCRE_ERROR_BADMAGIC: nx_panic("invalid pcre magic value"); case PCRE_ERROR_UNKNOWN_NODE: case PCRE_ERROR_INTERNAL: nx_panic("pcre bug or buffer overflow error"); case PCRE_ERROR_NOMEMORY: nx_panic("pcre_malloc() failed"); case PCRE_ERROR_MATCHLIMIT: log_error("pcre match_limit reached"); break; case PCRE_ERROR_BADUTF8: log_error("invalid pcre utf-8 byte sequence"); break; case PCRE_ERROR_BADUTF8_OFFSET: log_error("invalid pcre utf-8 byte sequence offset"); break; case PCRE_ERROR_PARTIAL: break; case PCRE_ERROR_BADPARTIAL: nx_panic("PCRE_ERROR_BADPARTIAL"); case PCRE_ERROR_BADCOUNT: nx_panic("negative ovecsize"); default: log_error("unknown pcre error in pcre_exec(): %d", pcre_result); break; } } } return ( FALSE ); }
static boolean nx_patterndb_match_matchfields(nx_logdata_t *logdata, nx_pattern_matchfields_t *matchfields, nx_logdata_field_list_t *addfields, boolean isgroup, const char *name) { nx_pattern_matchfield_t *matchfield; nx_logdata_field_t *logfield; nx_exception_t e; ASSERT(matchfields != NULL); for ( matchfield = NX_DLIST_FIRST(matchfields); matchfield != NULL; matchfield = NX_DLIST_NEXT(matchfield, link) ) { logfield = nx_logdata_get_field(logdata, matchfield->name); if ( logfield == NULL ) { // logdata does not have field //log_debug("logdata does not have '%s' field", matchfield->name); return ( FALSE ); } if ( logfield->value->defined == FALSE ) { // undef does not match return ( FALSE ); } if ( logfield->value->type == NX_VALUE_TYPE_STRING ) { switch ( matchfield->type ) { case NX_PATTERN_MATCH_TYPE_EXACT: //log_debug("exact match for '%s' against '%s'", matchfield->value, logfield->value->string->buf); if ( strcmp(matchfield->value, logfield->value->string->buf) != 0 ) { return ( FALSE ); } break; case NX_PATTERN_MATCH_TYPE_REGEXP: if ( patterndb_regexp_match(logfield->value->string->buf, matchfield, addfields, isgroup, name) == FALSE ) { //log_debug("logdata field didn't match regexp"); return ( FALSE ); } break; default: nx_panic("invalid match type: %d", matchfield->type); } } else if ( logfield->value->type == NX_VALUE_TYPE_INTEGER ) { char intstr[32]; char *strval; volatile boolean retval = FALSE; switch ( matchfield->type ) { case NX_PATTERN_MATCH_TYPE_EXACT: //log_debug("exact match for '%s' against '%ld'", matchfield->value, logfield->value->integer); apr_snprintf(intstr, sizeof(intstr), "%"APR_INT64_T_FMT, logfield->value->integer); if ( strcmp(matchfield->value, intstr) != 0 ) { return ( FALSE ); } break; case NX_PATTERN_MATCH_TYPE_REGEXP: strval = nx_value_to_string(logfield->value); try { if ( patterndb_regexp_match(strval, matchfield, addfields, isgroup, name) == TRUE ) { retval = TRUE; } } catch(e) { free(strval); rethrow(e); } free(strval); return ( retval ); default: nx_panic("invalid match type: %d", matchfield->type); } } else if ( logfield->value->type == NX_VALUE_TYPE_BOOLEAN ) { switch ( matchfield->type ) { case NX_PATTERN_MATCH_TYPE_EXACT: if ( (strcasecmp(matchfield->value, "true") == 0) && (logfield->value->boolean == FALSE) ) { return ( FALSE ); } else if ( (strcasecmp(matchfield->value, "false") == 0) && (logfield->value->boolean == TRUE) ) { return ( FALSE ); } break; case NX_PATTERN_MATCH_TYPE_REGEXP: log_error("invalid use of REGEXP match with BOOLEAN type %s", logfield->key); return ( FALSE ); default: nx_panic("invalid match type: %d", matchfield->type); } } else { // other logdata field type char *strval; boolean retval = FALSE; strval = nx_value_to_string(logfield->value); try { switch ( matchfield->type ) { case NX_PATTERN_MATCH_TYPE_EXACT: if ( strcmp(matchfield->value, strval) == 0 ) { retval = TRUE; } break; case NX_PATTERN_MATCH_TYPE_REGEXP: if ( patterndb_regexp_match(strval, matchfield, addfields, isgroup, name) == TRUE ) { retval = TRUE; } break; default: nx_panic("invalid match type: %d", matchfield->type); } } catch(e) { free(strval); rethrow(e); } free(strval); return ( retval ); } } return ( TRUE ); }
static boolean patterndb_regexp_match(const char *subject, nx_pattern_matchfield_t *matchfield, nx_logdata_field_list_t *addfields, boolean isgroup, const char *name) { int result; nx_pattern_capturedfield_t * volatile capturedfield; int ovector[NX_PATTERNDB_MAX_CAPTURED_FIELDS * 3]; volatile int i; nx_value_t *value; nx_logdata_field_t *setfield; nx_exception_t e; result = pcre_exec(matchfield->regexp, NULL, subject, (int) strlen(subject), 0, 0, ovector, NX_PATTERNDB_MAX_CAPTURED_FIELDS * 3); if ( result < 0 ) { switch ( result ) { case PCRE_ERROR_NOMATCH: break; case PCRE_ERROR_PARTIAL: // The subject string did not match, but it did match partially. // Treat the same as NOMATCH break; case PCRE_ERROR_NULL: nx_panic("invalid arguments (code, ovector or ovecsize are invalid)"); case PCRE_ERROR_BADOPTION: nx_panic("invalid option in options parameter"); case PCRE_ERROR_BADMAGIC: nx_panic("invalid pcre magic value"); case PCRE_ERROR_UNKNOWN_NODE: case PCRE_ERROR_INTERNAL: nx_panic("pcre bug or buffer overflow error"); case PCRE_ERROR_NOMEMORY: nx_panic("pcre_malloc() failed"); case PCRE_ERROR_MATCHLIMIT: log_error("pcre match_limit reached in pattern '%s' for regexp '%s'", name, matchfield->value); break; case PCRE_ERROR_BADUTF8: log_error("invalid pcre utf-8 byte sequence in pattern '%s' for regexp '%s'", name, matchfield->value); break; case PCRE_ERROR_BADUTF8_OFFSET: log_error("invalid pcre utf-8 byte sequence offset in pattern '%s' for regexp '%s'", name, matchfield->value); break; case PCRE_ERROR_BADPARTIAL: nx_panic("PCRE_ERROR_BADPARTIAL"); case PCRE_ERROR_BADCOUNT: nx_panic("negative ovecsize"); default: log_error("unknown pcre error in pcre_exec(): %d", result); break; } log_debug("regexp '%s' did not match against '%s'", matchfield->value, subject); return ( FALSE ); } log_debug("regexp '%s' matched on '%s'", matchfield->value, subject); if ( matchfield->capturedfield_cnt > 0 ) { if ( result != matchfield->capturedfield_cnt + 1 ) { throw_msg("regexp match returned %d captured substrings, matchfield in pattern has %d defined", result - 1, matchfield->capturedfield_cnt); } // add captured fields into setfields variable, these will be added to the // logdata if all matchfields match (=the pattern matches) for ( capturedfield = NX_DLIST_FIRST(matchfield->capturedfields), i = 2; capturedfield != NULL; capturedfield = NX_DLIST_NEXT(capturedfield, link), i += 2 ) { ASSERT(matchfield->capturedfield_cnt * 2 >= i); try { size_t len = (size_t) (ovector[i + 1] - ovector[i]); if ( capturedfield->type == NX_VALUE_TYPE_STRING ) { value = nx_value_new(NX_VALUE_TYPE_STRING); value->string = nx_string_create(subject + ovector[i], (int) len); } else { char tmpstr[len + 1]; memcpy(tmpstr, subject + ovector[i], len); tmpstr[len] = '\0'; value = nx_value_from_string(tmpstr, capturedfield->type); } setfield = malloc(sizeof(nx_logdata_field_t)); setfield->value = value; setfield->key = strdup(capturedfield->name); ASSERT(addfields != NULL); NX_DLIST_INSERT_TAIL(addfields, setfield, link); //log_debug("added %s to logdata", capturedfield->name); } catch(e) { log_exception_msg(e, "error setting field '%s' in %s '%s'", capturedfield->name, isgroup == TRUE ? "pattern group" : "pattern", name); } } } return ( TRUE ); }