int lua_co_setkeepalive(lua_State *L) { if(!lua_isuserdata(L, 1) || !lua_isnumber(L, 2)) { lua_pushnil(L); lua_pushstring(L, "Error params!"); return 2; } cosocket_t *c*k = (cosocket_t *) lua_touserdata(L, 1); c*k->pool_size = lua_tonumber(L, 2); if(c*k->pool_size < 0) { c*k->pool_size = 0; } else if(c*k->pool_size > 4096) { c*k->pool_size = 4096; } cosocket_connection_pool_counter_t *pool_counter = get_connection_pool_counter(c*k->pool_key); if(c*k->pool_size > pool_counter->size) { pool_counter->size = c*k->pool_size; } if(lua_gettop(L) == 3 && lua_isstring(L, 3)) { size_t len = 0; const char *key = lua_tolstring(L, 3, &len); c*k->pool_key = fnv1a_32(key, len); } _lua_co_close(L, c*k); lua_pushboolean(L, 1); return 1; }
int lua_f_file_exists(lua_State *L) { epdata_t *epd = get_epd(L); if(!epd) { lua_pushnil(L); lua_pushstring(L, "miss epd!"); return 2; } if(!lua_isstring(L, 1)) { lua_pushnil(L); lua_pushstring(L, "Need a file path!"); return 2; } size_t len = 0; const char *fname = lua_tolstring(L, 1, &len); char *full_fname = (char *)&temp_buf; memcpy(full_fname, epd->vhost_root, epd->vhost_root_len); memcpy(full_fname + epd->vhost_root_len, fname, len); full_fname[epd->vhost_root_len + len] = '\0'; lua_pushboolean(L, cached_access(fnv1a_32(full_fname, epd->vhost_root_len + len), full_fname) != -1); return 1; }
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) { #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #endif #ifdef CHAISCRIPT_MSVC #pragma warning(push) #pragma warning(disable : 4307) #endif return (*s == 0) ? h : fnv1a_32(s + 1, ((h ^ (*s)) * 0x01000193)); #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif }
static int lua_co_connect(lua_State *L) { cosocket_t *c*k = NULL; { if(!lua_isuserdata(L, 1) || !lua_isstring(L, 2)) { lua_pushnil(L); lua_pushstring(L, "Error params!"); return 2; } c*k = (cosocket_t *) lua_touserdata(L, 1); if(c*k->status > 0) { lua_pushnil(L); lua_pushstring(L, "Aleady connected!"); return 2; } if(c*k->inuse == 1) { lua_pushnil(L); lua_pushstring(L, "socket busy!"); return 2; } //printf(" 0x%p connect to %s\n", L, lua_tostring(L, 2)); size_t host_len = 0; const char *host = lua_tolstring(L, 2, &host_len); if(host_len > (host[0] == '/' ? 108 : 60)) { lua_pushnil(L); lua_pushstring(L, "hostname length must be <= 60!"); return 2; } int port = 0; int pn = 3; if(host[0] != '/') { port = lua_tonumber(L, 3); if(port < 1) { lua_pushnil(L); lua_pushstring(L, "port must be > 0"); return 2; } pn = 4; } if(lua_gettop(L) >= pn) { /// set keepalive options if(lua_isnumber(L, pn)) { c*k->pool_size = lua_tonumber(L, pn); if(c*k->pool_size < 0) { c*k->pool_size = 0; } else if(c*k->pool_size > 4096) { c*k->pool_size = 4096; } pn++; } if(c*k->pool_size > 0) { size_t len = 0; if(lua_gettop(L) == pn && lua_isstring(L, pn)) { const char *key = lua_tolstring(L, pn, &len); c*k->pool_key = fnv1a_32(key, len); } } } if(c*k->pool_key == 0) { /// create a normal key int len = snprintf(temp_buf, 4096, "%s%s:%d:%ld", port > 0 ? "tcp://" : "unix://", host, port, c*k->ssl_sign); c*k->pool_key = fnv1a_32(temp_buf, len); } c*k->status = 1; c*k->L = L; c*k->read_buf = NULL; c*k->last_buf = NULL; c*k->total_buf_len = 0; c*k->buf_read_len = 0; /// check pool count cosocket_connection_pool_counter_t *pool_counter = get_connection_pool_counter(c*k->pool_key); if(pool_counter->size > c*k->pool_size) { c*k->pool_size = pool_counter->size; } if(c*k->pool_size > 0) { c*k->ptr = get_connection_in_pool(_loop_fd, c*k->pool_key, c*k); if(c*k->ptr) { ((se_ptr_t *) c*k->ptr)->data = c*k; c*k->status = 2; c*k->reusedtimes = 1; c*k->fd = ((se_ptr_t *) c*k->ptr)->fd; //printf("reuse %d\n", c*k->fd); se_be_pri(c*k->ptr, NULL); lua_pushboolean(L, 1); return 1; } if(pool_counter->count > 0 && pool_counter->count >= c*k->pool_size / _process_count) { /// pool full if((c*k->pool_wait = add_waiting_get_connection(c*k))) { c*k->status = 3; c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle); //printf("wait %d\n", c*k->fd); c*k->inuse = 1; return lua_yield(L, 0); } else { lua_pushnil(L); lua_pushstring(L, "pool error"); return 2; } } } int fd = se_connect(_loop_fd, host, port, c*k->timeout > 0 ? c*k->timeout : 30000, be_connect, c*k); if(fd != -2) { if(fd > -1) { connection_pool_counter_operate(c*k->pool_key, 1); int ret = _be_connect(c*k, fd, 0); if(ret == -2) { return lua_yield(L, 0); } return ret; } else { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; } } connection_pool_counter_operate(c*k->pool_key, 1); } return lua_yield(L, 0); }
static int lua_co_tcp(lua_State *L) { cosocket_t *c*k = (cosocket_t *) lua_newuserdata(L, sizeof(cosocket_t)); if(!c*k) { lua_pushnil(L); lua_pushstring(L, "stack error!"); return 2; } bzero(c*k, sizeof(cosocket_t)); if(lua_isstring(L, 1) && lua_isstring(L, 2)) { if(c*k->ctx) { SSL_CTX_free(c*k->ctx); } c*k->ctx = SSL_CTX_new(SSLv23_client_method()); if(c*k->ctx == NULL) { lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_CTX_new Error"); return 2; } if(lua_isstring(L, 3)) { if(c*k->ssl_pw) { free(c*k->ssl_pw); } size_t len = 0; const char *p1 = lua_tolstring(L, 3, &len); c*k->ssl_pw = malloc(len + 1); if(c*k->ssl_pw) { memcpy(c*k->ssl_pw, p1, len); c*k->ssl_pw[len] = '\0'; SSL_CTX_set_default_passwd_cb_userdata(c*k->ctx, (void *)c*k->ssl_pw); SSL_CTX_set_default_passwd_cb(c*k->ctx, ssl_password_cb); } int l = snprintf(temp_buf, 4096, "%s:%s:%s", lua_tostring(L, 1), lua_tostring(L, 2), p1); c*k->ssl_sign = fnv1a_32(temp_buf, l); } else { int l = snprintf(temp_buf, 4096, "%s:%s:", lua_tostring(L, 1), lua_tostring(L, 2)); c*k->ssl_sign = fnv1a_32(temp_buf, l); } if(SSL_CTX_use_certificate_file(c*k->ctx, lua_tostring(L, 1), SSL_FILETYPE_PEM) != 1) { SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_CTX_use_certificate_file Error"); return 2; } if(SSL_CTX_use_PrivateKey_file(c*k->ctx, lua_tostring(L, 2), SSL_FILETYPE_PEM) != 1) { SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_CTX_use_PrivateKey_file Error"); return 2; } if(!SSL_CTX_check_private_key(c*k->ctx)) { SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_CTX_check_private_key Error"); return 2; } c*k->use_ssl = 1; } else if(lua_isboolean(L, 1) && lua_toboolean(L, 1) == 1) { c*k->use_ssl = 1; } else { c*k->use_ssl = 0; } c*k->L = L; c*k->fd = -1; c*k->timeout = 30000; /* if(luaL_newmetatable(L, "cosocket")) { //luaL_checkstack(L, 1, "not enough stack to register connection MT"); lua_pushvalue(L, lua_upvalueindex(1)); setfuncs(L, M, 1); lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); }*/ luaL_getmetatable(L, "cosocket:tcp"); lua_setmetatable(L, -2); return 1; }
static int is_match(const char *rule, const char *uri) { static regex_t *re = NULL; static regmatch_t pm[100]; int m = strlen(rule); char *nr = malloc(m * 2 + 10); int i = 0, gk = 0, nr_len = 0, fck = 0; v_p_count2 = 1; if(rule[0] != '^') { nr[0] = '^'; nr_len++; } for(i = 0; i < m; i++) { if(rule[i] == ':') { gk = 1; v_p2[v_p_count2] = (char *)rule + (i + 1); if(fck == 0) { fck = nr_len - 1; } } else { if((rule[i] == '(' || rule[i] == '[' || rule[i] == '$' || rule[i] == '/')) { if(fck == 0 && rule[i] != '/') { fck = nr_len - 1; } if(gk == 1) { gk = 0; v_p_len2[v_p_count2] = (rule + i) - v_p2[v_p_count2]; if(rule[i] == '/') { nr[nr_len++] = '('; nr[nr_len++] = '.'; nr[nr_len++] = '+'; nr[nr_len++] = ')'; v_p_count2 ++; } } else { v_p2[v_p_count2] = NULL; } } } if(gk == 0) { nr[nr_len++] = rule[i]; } if(rule[i] == '(') { v_p_count2 ++; } } if(gk == 1) { v_p_len2[v_p_count2] = (rule + i) - v_p2[v_p_count2]; nr[nr_len++] = '('; nr[nr_len++] = '.'; nr[nr_len++] = '+'; nr[nr_len++] = ')'; v_p_count2 ++; } nr[nr_len] = '\0'; //printf("== %s %s [%d]\n", nr, uri, v_p_count2); if((fck > 1 && strncmp(uri, nr + 1, fck) != 0)) { return 0; } uint32_t key = fnv1a_32(nr, nr_len); int _key = key % REGEX_CACHE_SIZE; re = regex_cache[_key]; if(re && regex_cache_key[_key] != key) { re = NULL; regfree(regex_cache[_key]); free(regex_cache[_key]); regex_cache[_key] = NULL; } if(!re) { re = malloc(sizeof(regex_t)); if(!re || regcomp(re, nr, REG_EXTENDED | REG_ICASE) != 0) { LOGF(ERR, "Router Failed to compile regex '%s'", rule); if(re) { regfree(re); } free(nr); return 0; } regex_cache[_key] = re; regex_cache_key[_key] = key; } unsigned int g = 0; int reti = regexec(re, uri, 100, pm, 0); if(reti == 0) { for(g = 0; g < 100; g++) { if(pm[g].rm_so == (size_t) - 1) { break; // No more groups } } if(g > match_max || (g >= match_max && nr_len > match_max_len)) { for(v_p_count = 0; v_p_count < v_p_count2; v_p_count++) { free(v_c[v_p_count]); v_c[v_p_count] = NULL; v_p[v_p_count] = v_p2[v_p_count]; v_p_len[v_p_count] = v_p_len2[v_p_count]; } match_max = g; match_max_len = nr_len; for(g = 1; g < match_max; g++) { if(v_p[g]) { free(v_c[g]); v_c[g] = malloc(pm[g].rm_eo - pm[g].rm_so + 1); memcpy(v_c[g], uri + pm[g].rm_so, pm[g].rm_eo - pm[g].rm_so); if(v_c[g][pm[g].rm_eo - pm[g].rm_so - 1] == '/') { pm[g].rm_eo --; } v_c[g][pm[g].rm_eo - pm[g].rm_so] = '\0'; //printf("M: %d %d %s %d\n", pm[g].rm_so, g, v_c[g], v_p_len[g]); } else { v_c[g] = NULL; } } } else { g = 0; } } else { // char msgbuf[100]; // regerror(reti, &re, msgbuf, sizeof(msgbuf)); // fprintf(stderr, "Regex match failed: %s\n", msgbuf); } //regfree(&re); free(nr); return g; }
int lua_f_router(lua_State *L) { if(lua_routed) { lua_pushnil(L); lua_pushnil(L); return 2; } lua_routed = 1; if(!lua_isstring(L, 1)) { lua_pushnil(L); lua_pushstring(L, "excepted uri"); return 2; } if(!lua_istable(L, 2)) { lua_pushnil(L); lua_pushstring(L, "excepted router table"); return 2; } const char *uri = lua_tostring(L, 1); int uri_len = strlen(uri); if(uri_len < 1 || uri[0] != '/') { lua_pushnil(L); lua_pushstring(L, "not a uri"); return 2; } if(lua_isstring(L, 3)) { // try local lua script file epdata_t *epd = NULL; lua_getglobal(L, "__epd__"); if(lua_isuserdata(L, -1)) { epd = lua_touserdata(L, -1); } lua_pop(L, 1); if(epd) { size_t len = 0; const char *fname = lua_tolstring(L, 3, &len); char *full_fname = (char *)&temp_buf; memcpy(full_fname, epd->vhost_root, epd->vhost_root_len); memcpy(full_fname + epd->vhost_root_len, fname, len); memcpy(full_fname + epd->vhost_root_len + len , uri, uri_len); len = epd->vhost_root_len + len + uri_len; full_fname[len] = '\0'; if(full_fname[len - 4] == '.' && full_fname[len - 3] == 'l' && full_fname[len - 1] == 'a') { if(cached_access(fnv1a_32(full_fname, len), full_fname) != -1) { lua_pushnil(L); lua_pushstring(L, full_fname + (len - uri_len)); return 2; } } if(full_fname[len - 1] != '/') { memcpy(full_fname + len, ".lua", 4); full_fname[len + 4] = '\0'; //if(access(full_fname, F_OK) != -1) { if(cached_access(fnv1a_32(full_fname, len + 4), full_fname) != -1) { lua_pushnil(L); lua_pushstring(L, full_fname + (len - uri_len)); return 2; } } else { memcpy(full_fname + len, "index.lua", 9); full_fname[len + 9] = '\0'; //if(access(full_fname, F_OK) != -1) { if(cached_access(fnv1a_32(full_fname, len + 9), full_fname) != -1) { lua_pushnil(L); lua_pushstring(L, full_fname + (len - uri_len)); return 2; } memcpy(full_fname + len - 1, ".lua", 4); full_fname[len - 1 + 4] = '\0'; //if(access(full_fname, F_OK) != -1) { if(cached_access(fnv1a_32(full_fname, len + 3), full_fname) != -1) { lua_pushnil(L); lua_pushstring(L, full_fname + (len - uri_len)); return 2; } } } } int pat = 0; lua_pushvalue(L, 2); lua_pushnil(L); match_max = 0; while(lua_next(L, -2)) { if(lua_isstring(L, -2)) { //printf("== %s\n", lua_tostring(L, -2)); if(is_match(lua_tostring(L, -2), uri)) { the_match_pat = pat; } } lua_pop(L, 1); pat++; if(pat >= 100) { break; } } pat = 0; lua_pushvalue(L, 2); lua_pushnil(L); while(lua_next(L, -2)) { if(lua_isstring(L, -2)) { if(match_max > 0 && pat == the_match_pat) { //printf("== %s\n", lua_tostring(L, -2)); lua_pushvalue(L, -1); lua_pop(L, 1); lua_createtable(L, 0, match_max); int i = 0; for(i = 1; i < match_max; i++) { if(!v_p[i]) { continue; } lua_pushlstring(L, v_p[i], v_p_len[i]); lua_pushstring(L, v_c[i]); free(v_c[i]); v_c[i] = NULL; lua_settable(L, -3); /* 3rd element from the stack top */ } return 2; } } lua_pop(L, 1); pat++; if(pat >= 100) { break; } } return 0; }
static VALUE rbfnv_fnv1a_32(VALUE self, VALUE data) { return UINT2NUM(fnv1a_32(RSTRING(data)->ptr, RSTRING(data)->len)); }