static void be_connect(void *data, int fd) { cosocket_t *c*k = data; if(fd < 0) { connection_pool_counter_operate(c*k->pool_key, -1); lua_pushnil(c*k->L); if(se_errno == SE_DNS_QUERY_TIMEOUT) { lua_pushstring(c*k->L, "Connect error!(dns query timeout)"); } else if(se_errno == SE_CONNECT_TIMEOUT) { lua_pushstring(c*k->L, "Connect error!(timeout)"); } else { lua_pushstring(c*k->L, "Connect error!(unknow)"); } c*k->status = 0; c*k->inuse = 0; lua_f_lua_uthread_resume_in_c(c*k->L, 2); return; } int ret = _be_connect(c*k, fd, 1); if(ret == -2) { return; } lua_f_lua_uthread_resume_in_c(c*k->L, ret); }
int coevnet_module_do_other_jobs() { swop_counter = swop_counter / 2; get_connection_in_pool(_loop_fd, 0, NULL); check_lua_sleep_timeouts(); /// resume swops cosocket_swop_t *swop = NULL; if(swop_top->next != NULL) { swop = swop_top->next; swop_top->next = swop->next; if(swop_top->next == NULL) { swop_lat = NULL; } lua_State *L = swop->L; free(swop); swop = NULL; if(lua_status(L) == LUA_YIELD) { //lua_pushboolean ( L, 1 ); lua_f_lua_uthread_resume_in_c(L, 0); } } }
void resume_in_waiting_get_connection(int loop_fd) { int k = 0; for(k = 0; k < 64; k++) { if(waiting_get_connections[k]) { cosocket_t *c*k = ((cosocket_waiting_get_connection_t *)waiting_get_connections[k])->c*k; c*k->ptr = get_connection_in_pool(loop_fd, c*k->pool_key, c*k); if(c*k->ptr) { c*k->pool_wait = NULL; delete_in_waiting_get_connection(waiting_get_connections[k]); ((se_ptr_t *) c*k->ptr)->data = c*k; c*k->status = 2; c*k->inuse = 0; c*k->reusedtimes = 1; c*k->in_read_action = 0; c*k->fd = ((se_ptr_t *) c*k->ptr)->fd; //printf("reuse %d\n", c*k->fd); delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; se_be_pri(c*k->ptr, NULL); lua_pushboolean(c*k->L, 1); lua_f_lua_uthread_resume_in_c(c*k->L, 1); return; } } } }
int check_lua_sleep_timeouts() { l_now = longtime() / 10; if(now_4sleep == 0) { now_4sleep = l_now - 5; } do { int k = now_4sleep % TIME_BUCKET_SIZE; sleep_timeout_t *m = timeout_links[k], *n = NULL; lua_State *L = NULL; while(m) { n = m; m = m->next; if(l_now >= n->timeout) { // timeout { if(n->uper) { ((sleep_timeout_t *) n->uper)->next = n->next; } else { timeout_links[k] = n->next; } if(n->next) { ((sleep_timeout_t *) n->next)->uper = n->uper; } else { timeout_link_ends[k] = n->uper; } L = n->L; free(n); } if(L) { lua_f_lua_uthread_resume_in_c(L, 0); l_now = longtime() / 10; } L = NULL; } } if(now_4sleep < l_now) { now_4sleep++; continue; } } while(now_4sleep < l_now); return 1; }
int cosocket_be_ssl_connected(se_ptr_t *ptr) { cosocket_t *c*k = ptr->data; if(SSL_connect(c*k->ssl)) { delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; se_be_pri(c*k->ptr, NULL); lua_pushboolean(c*k->L, 1); c*k->inuse = 0; lua_f_lua_uthread_resume_in_c(c*k->L, 1); return 1; } return 0; }
static int send_then_send(se_ptr_t *ptr) { epdata_t *epd = ptr->data; epd->next_proc = NULL; char *buf = epd->next_out; int len = epd->next_out_len; epd->next_out_len = 0; int have = network_send(epd, buf, len); if(have > 0) { epd->next_out = malloc(have); if(epd->next_out) { memcpy(epd->next_out, buf + (len - have), have); free(buf); if(network_flush(epd) == 1) { epd->next_proc = send_then_send; epd->next_out_len = have; return have; } else { LOGF(ERR, "flush error"); free(epd->next_out); epd->next_out = NULL; return 0; } return 0; } } free(buf); lua_f_lua_uthread_resume_in_c(epd->L, 0); return 0; }
static void timeout_handle(void *ptr) { cosocket_t *c*k = ptr; delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; if(c*k->pool_wait) { delete_in_waiting_get_connection(c*k->pool_wait); c*k->pool_wait = NULL; } lua_pushnil(c*k->L); if(c*k->ptr) { if(c*k->status == 3) { lua_pushstring(c*k->L, "Connect error!(wait pool timeout)"); } else if(((se_ptr_t *) c*k->ptr)->wfunc == cosocket_be_ssl_connected) { lua_pushstring(c*k->L, "SSL Connect timeout!"); } else if(((se_ptr_t *) c*k->ptr)->wfunc == cosocket_be_write) { lua_pushstring(c*k->L, "Send timeout!"); } else if(((se_ptr_t *) c*k->ptr)->rfunc == cosocket_be_read) { lua_pushstring(c*k->L, "Read timeout!"); } else { lua_pushstring(c*k->L, "Timeout!"); } } else { if(c*k->status == 3) { lua_pushstring(c*k->L, "Connect error!(wait pool timeout)"); } else { lua_pushstring(c*k->L, "Timeout!"); } } { se_delete(c*k->ptr); c*k->ptr = NULL; if(c*k->fd > -1) { connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); c*k->fd = -1; } c*k->status = 0; } if(c*k->ssl) { SSL_shutdown(c*k->ssl); SSL_free(c*k->ssl); c*k->ssl = NULL; SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; } if(c*k->read_buf) { cosocket_link_buf_t *fr = c*k->read_buf; cosocket_link_buf_t *nb = NULL; while(fr) { nb = fr->next; free(fr->buf); free(fr); fr = nb; } c*k->read_buf = NULL; } if(c*k->send_buf_need_free) { free(c*k->send_buf_need_free); c*k->send_buf_need_free = NULL; } c*k->inuse = 0; lua_f_lua_uthread_resume_in_c(c*k->L, 2); }
int cosocket_be_read(se_ptr_t *ptr) { cosocket_t *c*k = ptr->data; int n = 0, ret = 0; init_read_buf: if(!c*k->read_buf || (c*k->last_buf->buf_len >= c*k->last_buf->buf_size)) { /// init read buf cosocket_link_buf_t *nbuf = NULL; nbuf = malloc(sizeof(cosocket_link_buf_t)); if(nbuf == NULL) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } nbuf->buf = large_malloc(4096); if(!nbuf->buf) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } nbuf->buf_size = 4096; nbuf->buf_len = 0; nbuf->next = NULL; if(c*k->read_buf) { c*k->last_buf->next = nbuf; } else { c*k->read_buf = nbuf; } c*k->last_buf = nbuf; } if(!c*k->ssl) { while((n = recv(c*k->fd, c*k->last_buf->buf + c*k->last_buf->buf_len, c*k->last_buf->buf_size - c*k->last_buf->buf_len, 0)) > 0) { c*k->last_buf->buf_len += n; c*k->total_buf_len += n; if(c*k->last_buf->buf_len >= c*k->last_buf->buf_size) { goto init_read_buf; } } } else { while((n = SSL_read(c*k->ssl, c*k->last_buf->buf + c*k->last_buf->buf_len, c*k->last_buf->buf_size - c*k->last_buf->buf_len)) > 0) { c*k->last_buf->buf_len += n; c*k->total_buf_len += n; if(c*k->last_buf->buf_len >= c*k->last_buf->buf_size) { goto init_read_buf; } } } if(n == 0 || (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { int rfd = c*k->fd; /// socket closed delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; { c*k->status = 0; se_delete(c*k->ptr); c*k->ptr = NULL; connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); c*k->fd = -1; c*k->status = 0; } if(c*k->in_read_action == 1) { c*k->in_read_action = 0; int rt = lua_co_read_(c*k); c*k->inuse = 0; if(rt > 0) { ret = lua_f_lua_uthread_resume_in_c(c*k->L, rt); } else if(n == 0) { lua_pushnil(c*k->L); ret = lua_f_lua_uthread_resume_in_c(c*k->L, 1); } if(ret == LUA_ERRRUN) { se_delete(c*k->ptr); c*k->ptr = NULL; connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); c*k->fd = -1; c*k->status = 0; } } } else { if(c*k->in_read_action == 1) { int rt = lua_co_read_(c*k); if(rt > 0) { c*k->in_read_action = 0; delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; c*k->inuse = 0; ret = lua_f_lua_uthread_resume_in_c(c*k->L, rt); if(ret == LUA_ERRRUN) { se_delete(c*k->ptr); c*k->ptr = NULL; connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); c*k->fd = -1; c*k->status = 0; } } } } return 0; }
int cosocket_be_write(se_ptr_t *ptr) { cosocket_t *c*k = ptr->data; int n = 0, ret = 0; c*k->in_read_action = 0; if(!c*k->ssl) { while((n = send(c*k->fd, c*k->send_buf + c*k->send_buf_ed, c*k->send_buf_len - c*k->send_buf_ed, MSG_DONTWAIT)) > 0) { c*k->send_buf_ed += n; } } else { while((n = SSL_write(c*k->ssl, c*k->send_buf + c*k->send_buf_ed, c*k->send_buf_len - c*k->send_buf_ed)) > 0) { c*k->send_buf_ed += n; } } if(c*k->send_buf_ed == c*k->send_buf_len || (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { se_delete(c*k->ptr); c*k->ptr = NULL; connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); c*k->fd = -1; c*k->status = 0; c*k->send_buf_ed = 0; } /* else { se_be_pri(c*k->ptr, NULL); }*/ if(c*k->send_buf_need_free) { free(c*k->send_buf_need_free); c*k->send_buf_need_free = NULL; } delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; int rc = 1; if(c*k->send_buf_ed >= c*k->send_buf_len) { lua_pushnumber(c*k->L, c*k->send_buf_ed); } else if(c*k->fd == -1) { lua_pushnil(c*k->L); lua_pushstring(c*k->L, "connection closed!"); rc = 2; } else { lua_pushboolean(c*k->L, 0); } if(c*k->inuse == 1) { se_be_pri(c*k->ptr, NULL); c*k->inuse = 0; lua_f_lua_uthread_resume_in_c(c*k->L, rc); return 0; } else { return 0 - rc; } } return c*k->send_buf_len - c*k->send_buf_ed; }
static int network_be_read_request_body(se_ptr_t *ptr) { //printf("network_be_read_request_body\n"); epdata_t *epd = ptr->data; if(!epd) { return 0; } int n = 0, readed = 0; char *buf = malloc(65536); int buf_size = 65536; if(!buf) { serv_status.active_counts--; se_delete(epd->se_ptr); epd->se_ptr = NULL; close(epd->fd); epd->fd = -1; if(epd->status == STEP_READ) { serv_status.reading_counts--; epd->status = STEP_PROCESS; } lua_pushnil(epd->L); lua_pushstring(epd->L, "memory error"); LOGF(ERR, "memory error!"); lua_f_lua_uthread_resume_in_c(epd->L, 2); return 0; } while((n = recv(epd->fd, buf + readed, buf_size - readed, 0)) >= 0) { if(n == 0) { serv_status.active_counts--; se_delete(epd->se_ptr); epd->se_ptr = NULL; close(epd->fd); epd->fd = -1; if(epd->status == STEP_READ) { serv_status.reading_counts--; epd->status = STEP_PROCESS; } break; } epd->data_len += n; readed += n; //printf("readed: %d\n", n); if(readed >= buf_size) { char *p = realloc(buf, buf_size + 65536); if(p) { buf = p; buf_size += 65536; } else { break; } } } if(readed > 0) { if(epd->status == STEP_READ) { serv_status.reading_counts--; epd->status = STEP_PROCESS; } se_be_pri(epd->se_ptr, NULL); // be wait lua_pushlstring(epd->L, buf, readed); free(buf); lua_f_lua_uthread_resume_in_c(epd->L, 1); } else if(n == 0) { n = -1; errno = 1; } if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { serv_status.active_counts--; se_delete(epd->se_ptr); epd->se_ptr = NULL; close(epd->fd); epd->fd = -1; if(epd->status == STEP_READ) { serv_status.reading_counts--; epd->status = STEP_PROCESS; } lua_pushnil(epd->L); lua_pushstring(epd->L, "socket closed"); lua_f_lua_uthread_resume_in_c(epd->L, 2); return 0; } }
int worker_process(epdata_t *epd, int thread_at) { //printf("worker_process\n"); working_at_fd = epd->fd; //network_send_error(epd, 503, "Lua Error: main function not found !!!");return 0; //network_send(epd, "aaa", 3);network_be_end(epd);return 0; if(epd->ssl && !epd->ssl_verify) { network_send_error(epd, 400, "No required SSL certificate was send"); return 0; } lua_State *L = epd->L; if(!L) { epd->L = new_lua_thread(_L); if(!epd->L) { network_send_error(epd, 503, "Lua Error: Thread pool full !!!"); LOGF(ERR, "Lua Error: Thread pool full !!!"); return 0; } lua_pushlightuserdata(epd->L, epd); lua_setglobal(epd->L, "__epd__"); L = epd->L; } lua_getglobal(L, "process"); update_timeout(epd->timeout_ptr, STEP_PROCESS_TIMEOUT + 100); int init_tables = 0; char *pt1 = NULL, *pt2 = NULL, *t1 = NULL, *t2 = NULL, *t3 = NULL; int is_form_post = 0; char *cookies = NULL; pt1 = epd->headers; if(pt1[0] == '\0') { pt1 = pt1 + 1; } int i = 0; epd->uri = NULL; epd->host = NULL; epd->query = NULL; epd->http_ver = NULL; epd->referer = NULL; epd->user_agent = NULL; epd->if_modified_since = NULL; //epd->start_time = longtime(); while(t1 = strtok_r(pt1, "\n", &pt1)) { if(++i == 1) { /// first line t2 = strtok_r(t1, " ", &t1); t3 = strtok_r(t1, " ", &t1); epd->http_ver = strtok_r(t1, " ", &t1); if(!epd->http_ver) { network_send_error(epd, 400, "Bad Request"); return 0; } else { if(init_tables == 0) { lua_createtable(L, 0, 20); //headers init_tables = 1; } } int len = strlen(epd->http_ver); if(epd->http_ver[len - 1] == 13) { // CR == 13 epd->http_ver[len - 1] = '\0'; } if(t2 && t3) { for(t1 = t2 ; *t1 ; *t1 = toupper(*t1), t1++); epd->method = t2; lua_pushstring(L, t2); lua_setfield(L, -2, "method"); t1 = strtok_r(t3, "?", &t3); t2 = strtok_r(t3, "?", &t3); epd->uri = t1; lua_pushstring(L, t1); lua_setfield(L, -2, "uri"); if(t2) { epd->query = (t2 - 1); epd->query[0] = '?'; lua_pushstring(L, epd->query); lua_setfield(L, -2, "query"); } } continue; } t2 = strtok_r(t1, ":", &t1); if(t2) { if(t2[0] == '\r') { break; } for(t3 = t2; *t3; ++t3) { *t3 = *t3 >= 'A' && *t3 <= 'Z' ? *t3 | 0x60 : *t3; } t3 = t2 + strlen(t2) + 1; //strtok_r ( t1, ":", &t1 ) if(t3) { int len = strlen(t3); if(t3[len - 1] == 13) { /// 13 == CR t3[len - 1] = '\0'; len -= 1; } if(len < 1) { break; } lua_pushstring(L, t3 + (t3[0] == ' ' ? 1 : 0)); lua_setfield(L, -2, t2); /// check content-type if(t2[0] == 'h' && epd->host == NULL && strcmp(t2, "host") == 0) { char *_t = strstr(t3, ":"); if(_t) { _t[0] = '\0'; } epd->host = t3 + (t3[0] == ' ' ? 1 : 0); } else if(t2[1] == 'o' && strcmp(t2, "content-type") == 0) { if(stristr(t3, "x-www-form-urlencoded", len)) { is_form_post = 1; } else if(stristr(t3, "multipart/form-data", len)) { epd->boundary = (char *)stristr(t3, "boundary=", len - 2); if(epd->boundary) { epd->boundary += 9; } } } else if(!cookies && t2[1] == 'o' && strcmp(t2, "cookie") == 0) { cookies = t3 + (t3[0] == ' ' ? 1 : 0); } else if(!epd->user_agent && t2[1] == 's' && strcmp(t2, "user-agent") == 0) { epd->user_agent = t3 + (t3[0] == ' ' ? 1 : 0); } else if(!epd->referer && t2[1] == 'e' && strcmp(t2, "referer") == 0) { epd->referer = t3 + (t3[0] == ' ' ? 1 : 0); } else if(!epd->if_modified_since && t2[1] == 'f' && strcmp(t2, "if-modified-since") == 0) { epd->if_modified_since = t3 + (t3[0] == ' ' ? 1 : 0); } } } } if(init_tables == 0) { network_send_error(epd, 400, "Bad Request"); return 0; } const char *client_ip = cached_ntoa(epd->client_addr); lua_pushstring(L, client_ip); lua_setfield(L, -2, "remote-addr"); lua_pushstring(L, cached_ntoa(epd->server_addr)); lua_setfield(L, -2, "server-addr"); lua_setglobal(L, "headers"); lua_createtable(L, 0, 20); /// _GET if(epd->query) { /// parse query string /?a=1&b=2 char *last = NULL; int plen = 0; int qlen = strlen(epd->query) - 1; t1 = (char *)strsplit(epd->query + 1, qlen, "&", &last, &plen); while(t1) { char *last2 = NULL; int plen2 = 0; int plen3 = 0; t2 = (char *)strsplit(t1, plen, "=", &last2, &plen2); t3 = (char *)strsplit(t1, plen, "=", &last2, &plen3); if(t2 && plen2 > 0 && plen3 > 0 && plen2 <= 4096 && plen3 <= 4096) { size_t dlen = 0; u_char *p = 0; u_char *src = NULL, *dst = NULL; p = (u_char *)&buf_4096; p[0] = '\0'; dst = p; dlen = urldecode(&p, (u_char **)&t3, plen3, RAW_UNESCAPE_URL); lua_pushlstring(L, (char *) p, dlen); p[0] = '\0'; dst = p; dlen = urldecode(&dst, (u_char **)&t2, plen2, RAW_UNESCAPE_URL); p[dlen] = '\0'; lua_setfield(L, -2, p); } t1 = (char *)strsplit(epd->query + 1, qlen, "&", &last, &plen); } } lua_setglobal(L, "_GET"); lua_createtable(L, 0, 20); /// _COOKIE if(cookies) { while(t1 = strtok_r(cookies, ";", &cookies)) { t2 = strtok_r(t1, "=", &t1); t3 = strtok_r(t1, "=", &t1); if(t2 && t3) { size_t t2_len = strlen(t2), t3_len = strlen(t3); if(t2_len > 0 && t3_len > 0) { size_t dlen = 0, mlen = (t3_len > t2_len ? t3_len : t2_len); u_char *p = (u_char *)&buf_4096; u_char *src = NULL, *dst = NULL; if(mlen > 4096) { p = malloc(mlen); } p[0] = '\0'; dst = p; dlen = urldecode(&dst, (u_char **)&t3, t3_len, RAW_UNESCAPE_URL); lua_pushlstring(L, (char *) p, dlen); p[0] = '\0'; dst = p; dlen = urldecode(&dst, (u_char **)&t2, t2_len, RAW_UNESCAPE_URL); p[dlen] = '\0'; lua_setfield(L, -2, p + (p[0] == ' ' ? 1 : 0)); if(mlen > 4096) { free(p); } } } } } lua_setglobal(L, "_COOKIE"); epd->vhost_root = get_vhost_root(epd->host, &epd->vhost_root_len); memcpy(buf_4096, epd->vhost_root, epd->vhost_root_len + 1); sprintf(buf_4096 + epd->vhost_root_len + 1, "?.lua;%s/lua-libs/?.lua;%s", process_chdir, lua_path); lua_pushstring(L, buf_4096); lua_getglobal(L, "package"); lua_insert(L, -2); //-1 bufres -2 package lua_setfield(L, -2, "path"); //-1: path -2: package lua_pop(L, 1); //void lua_pushlstring(L, epd->vhost_root, epd->vhost_root_len); /// host root lua_setglobal(L, "__root"); lua_pushstring(L, epd->vhost_root + epd->vhost_root_len); /// index-route.lua file epd->iov[0].iov_base = NULL; epd->iov[0].iov_len = 0; epd->iov[1].iov_base = NULL; epd->iov[1].iov_len = 0; lua_routed = 0; if(lua_f_lua_uthread_resume_in_c(L, 1) == LUA_ERRRUN) { if(lua_isstring(L, -1)) { LOGF(ERR, "Lua:error %s", lua_tostring(L, -1)); network_send_error(epd, 503, lua_tostring(L, -1)); } else { network_send_error(epd, 503, "UNKNOW!"); } lua_pop(L, 1); } return 0; }