static int be_read(se_ptr_t *ptr) { epdata_t *epd = ptr->data; int n = recv(epd->fd, &buf_4096, 4096, 0); if(n > 0) { update_timeout(epd->timeout_ptr, 1000); if(network_raw_send(epd->fd, (const char *)&buf_4096, n)) { if(buf_4096[n - 1] == '\n') { buf_4096[n - 1] = '\0'; } LOGF(INFO, "%s", buf_4096); } else { LOGF(ERR, "send error!\n"); se_delete(epd->se_ptr); if(epd->fd > -1) { close(epd->fd); epd->fd = -1; } free(epd); } } else if(n == 0 || (n < 0 && NOAGAIN)) { // close connection se_delete(epd->se_ptr); if(epd->fd > -1) { close(epd->fd); epd->fd = -1; } free(epd); } else { LOGF(ERR, "read error!\n"); } return 1; }
static int lua_co_dup_setpeername(lua_State *L) { if(!lua_isuserdata(L, 1) || !lua_isstring(L, 2)) { lua_pushnil(L); lua_pushstring(L, "Error params!"); return 2; } cosocket_t *c*k = (cosocket_t *) lua_touserdata(L, 1); if(c*k->fd > -1) { se_delete(c*k->ptr); c*k->ptr = NULL; close(c*k->fd); } if(lua_isnumber(L, 3)) { int fd = 0, slen = sizeof(c*k->addr); bzero(&c*k->addr, slen); c*k->addr.sin_family = AF_INET; c*k->addr.sin_port = htons(lua_tonumber(L, 3)); const char *host = lua_tostring(L, 2); if(inet_aton(host, &c*k->addr.sin_addr) == 0) { struct hostent *hp = NULL; if((hp = gethostbyname(host)) == 0) { lua_pushnil(L); lua_pushstring(L, "Nslookup Error!"); return 2; } memcpy(&c*k->addr.sin_addr.s_addr, hp->h_addr, hp->h_length); } if((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { lua_pushnil(L); lua_pushstring(L, "Connect Error!"); return 2; } if(!se_set_nonblocking(fd , 1)) { close(fd); lua_pushnil(L); lua_pushstring(L, "Connect Error!"); return 2; } c*k->ptr = se_add(_loop_fd, fd, c*k); c*k->fd = fd; c*k->status = 2; lua_pushboolean(L, 1); return 1; } return 0; }
static void close_client(epdata_t *epd) { se_delete(epd->se_ptr); delete_timeout(epd->timeout_ptr); close(epd->fd); smp_free(epd); }
static int cosocket_be_close(se_ptr_t *ptr) { //printf("cosocket_be_close %d\n", ptr->fd); int fd = ptr->fd; cosocket_connection_pool_t *n = ptr->data; int k = n->pool_key % 64; if(n == connect_pool_p[0][k]) { connect_pool_p[0][k] = n->next; if(n->next) { ((cosocket_connection_pool_t *) n->next)->uper = NULL; } } else if(n == connect_pool_p[1][k]) { connect_pool_p[1][k] = n->next; if(n->next) { ((cosocket_connection_pool_t *) n->next)->uper = NULL; } } else { ((cosocket_connection_pool_t *) n->uper)->next = n->next; if(n->next) { ((cosocket_connection_pool_t *) n->next)->uper = n->uper; } } se_delete(n->ptr); n->ptr = NULL; if(n->ssl) { SSL_free(n->ssl); n->ssl = NULL; SSL_CTX_free(n->ctx); n->ctx = NULL; } connection_pool_counter_operate(n->pool_key, -1); close(fd); free(n); return 1; }
void close_client(epdata_t *epd) { if(!epd) { return; } if(epd->ssl && epd->fd > -1) { if(!SSL_shutdown(epd->ssl)) { shutdown(epd->fd, 1); SSL_shutdown(epd->ssl); } SSL_free(epd->ssl); epd->ssl = NULL; } if(epd->L) { if(epd->status == STEP_PROCESS) { LOGF(ERR, "at working!!!"); } release_lua_thread(epd->L); epd->L = NULL; } if(epd->status == STEP_READ) { serv_status.reading_counts--; } else if(epd->status == STEP_SEND) { serv_status.sending_counts--; } se_delete(epd->se_ptr); delete_timeout(epd->timeout_ptr); epd->timeout_ptr = NULL; if(epd->fd > -1) { serv_status.active_counts--; close(epd->fd); epd->fd = -1; } free_epd(epd); }
void close_client ( epdata_t *epd ) { if ( !epd ) { return; } if ( epd->status == STEP_READ ) { serv_status.reading_counts--; } else if ( epd->status == STEP_SEND ) { serv_status.sending_counts--; } se_delete ( epd->se_ptr ); delete_timeout ( epd->timeout_ptr ); epd->timeout_ptr = NULL; if ( epd->fd > -1 ) { serv_status.active_counts--; close ( epd->fd ); epd->fd = -1; } if ( epd->websocket ) { if ( epd->websocket->websocket_handles > 0 ) { luaL_unref ( epd->websocket->ML, LUA_REGISTRYINDEX, epd->websocket->websocket_handles ); } lua_resume ( epd->websocket->ML, 0 ); free ( epd->websocket ); epd->websocket = NULL; } free_epd ( epd ); }
static int _lua_co_close(lua_State *L, cosocket_t *c*k) { 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; } if(c*k->pool_wait) { delete_in_waiting_get_connection(c*k->pool_wait); c*k->pool_wait = NULL; } delete_timeout(c*k->timeout_ptr); c*k->timeout_ptr = NULL; c*k->status = 0; if(c*k->fd > -1) { ((se_ptr_t *) c*k->ptr)->fd = c*k->fd; if(c*k->pool_size < 1 || add_connection_to_pool(_loop_fd, c*k->pool_key, c*k->pool_size, c*k->ptr, c*k->ssl, c*k->ctx, c*k->ssl_pw) == 0) { se_delete(c*k->ptr); c*k->ptr = NULL; connection_pool_counter_operate(c*k->pool_key, -1); close(c*k->fd); if(c*k->ssl) { SSL_free(c*k->ssl); c*k->ssl = NULL; } if(c*k->ctx) { SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; } if(c*k->ssl_pw) { free(c*k->ssl_pw); c*k->ssl_pw = NULL; } } c*k->ssl = NULL; c*k->ctx = NULL; c*k->ssl_pw = NULL; c*k->ptr = NULL; c*k->fd = -1; } }
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 _be_connect(cosocket_t *c*k, int fd, int yielded) { int flag = 1; int ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); c*k->fd = fd; c*k->ptr = se_add(_loop_fd, fd, c*k); c*k->status = 2; c*k->in_read_action = 0; if(c*k->use_ssl) { if(c*k->ctx == NULL) { c*k->ctx = SSL_CTX_new(SSLv23_client_method()); if(c*k->ctx == NULL) { connection_pool_counter_operate(c*k->pool_key, -1); se_delete(c*k->ptr); close(c*k->fd); c*k->ptr = NULL; c*k->fd = -1; c*k->status = 0; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_CTX_new Error"); return 2; } } c*k->ssl = SSL_new(c*k->ctx); if(c*k->ssl == NULL) { connection_pool_counter_operate(c*k->pool_key, -1); se_delete(c*k->ptr); close(c*k->fd); c*k->ptr = NULL; c*k->fd = -1; c*k->status = 0; SSL_CTX_free(c*k->ctx); c*k->ctx = NULL; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "SSL_new Error"); return 2; } SSL_set_fd(c*k->ssl, c*k->fd); se_be_read(c*k->ptr, cosocket_be_ssl_connected); if(SSL_connect(c*k->ssl) == 1) { se_be_pri(c*k->ptr, NULL); lua_pushboolean(c*k->L, 1); c*k->inuse = 0; return 1; } c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle); return -2; } se_be_pri(c*k->ptr, NULL); lua_pushboolean(c*k->L, 1); c*k->inuse = 0; return 1; }
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; } }
se_ptr_t *get_connection_in_pool(int loop_fd, unsigned long pool_key, cosocket_t *c*k) { int k = pool_key % 64; int p = (now / connect_pool_ttl) % 2; cosocket_connection_pool_t *n = NULL, *m = NULL, *nn = NULL; se_ptr_t *ptr = NULL; /// clear old caches int q = (p + 1) % 2; int i = 0; for(i = 0; i < 64; i++) { n = connect_pool_p[q][i]; while(n) { m = n; n = n->next; ptr = m->ptr; if(m->z == 0) { m->z = 1; nn = connect_pool_p[p][m->pool_key % 64]; if(nn == NULL) { connect_pool_p[p][m->pool_key % 64] = m; m->next = NULL; m->uper = NULL; } else { m->uper = NULL; m->next = nn; nn->uper = m; connect_pool_p[p][m->pool_key % 64] = m; } } else { int fd = ptr->fd; se_delete(ptr); connection_pool_counter_operate(m->pool_key, -1); close(fd); free(m); } } connect_pool_p[q][i] = NULL; } /// end if(pool_key == 0) { resume_in_waiting_get_connection(loop_fd); return NULL; /// only do clear job } regetfd: n = connect_pool_p[p][k]; while(n != NULL) { if(n->pool_key == pool_key) { break; } n = (cosocket_connection_pool_t *) n->next; } if(n) { if(n == connect_pool_p[p][k]) { /// at top m = n->next; if(m) { m->uper = NULL; connect_pool_p[p][k] = m; } else { connect_pool_p[p][k] = NULL; } } else { ((cosocket_connection_pool_t *) n->uper)->next = n->next; if(n->next) { ((cosocket_connection_pool_t *) n->next)->uper = n->uper; } } ptr = n->ptr; if(c*k) { if(c*k->ctx) { SSL_CTX_free(c*k->ctx); } if(c*k->ssl_pw) { free(c*k->ssl_pw); } c*k->ctx = n->ctx; c*k->ssl = n->ssl; c*k->ssl_pw = n->ssl_pw; } free(n); //printf ( "get fd in pool%d %d key:%d\n", p, ptr->fd, k ); return ptr; } if(p != q) { p = q; goto regetfd; } return NULL; }
static int lua_co_send(lua_State *L) { cosocket_t *c*k = NULL; { if(lua_gettop(L) < 2) { return 0; } int t = lua_type(L, 2); if(!lua_isuserdata(L, 1) || (t != LUA_TSTRING && t != LUA_TTABLE)) { lua_pushboolean(L, 0); lua_pushstring(L, "Error params!"); return 2; } c*k = (cosocket_t *) lua_touserdata(L, 1); if(c*k->status != 2 || c*k->fd == -1 || !c*k->ptr) { lua_pushboolean(L, 0); lua_pushstring(L, "Not connected!"); return 2; } if(c*k->inuse == 1) { lua_pushnil(L); lua_pushstring(L, "socket busy!"); return 2; } c*k->L = L; c*k->send_buf_ed = 0; if(t == LUA_TTABLE) { c*k->send_buf_len = lua_calc_strlen_in_table(L, 2, 2, 1 /* strict */); if(c*k->send_buf_len > 0) { if(c*k->send_buf_len < _SENDBUF_SIZE) { c*k->send_buf_need_free = NULL; lua_copy_str_in_table(L, 2, c*k->_send_buf); c*k->send_buf = c*k->_send_buf; } else { c*k->send_buf_need_free = large_malloc(c*k->send_buf_len); if(!c*k->send_buf_need_free) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } lua_copy_str_in_table(L, 2, c*k->send_buf_need_free); c*k->send_buf = c*k->send_buf_need_free; } } } else { const char *p = lua_tolstring(L, 2, &c*k->send_buf_len); c*k->send_buf_need_free = NULL; if(c*k->send_buf_len < _SENDBUF_SIZE) { memcpy(c*k->_send_buf, p, c*k->send_buf_len); c*k->send_buf = c*k->_send_buf; } else { c*k->send_buf_need_free = large_malloc(c*k->send_buf_len); if(!c*k->send_buf_need_free) { LOGF(ERR, "malloc error @%s:%d\n", __FILE__, __LINE__); exit(1); } memcpy(c*k->send_buf_need_free, p, c*k->send_buf_len); c*k->send_buf = c*k->send_buf_need_free; } } if(c*k->send_buf_len < 1) { lua_pushboolean(L, 0); lua_pushstring(L, "content empty!"); return 2; } c*k->inuse = 0; int ret = cosocket_be_write(c*k->ptr); if(ret > 0) { if( se_be_write(c*k->ptr, cosocket_be_write) == -1) { se_delete(c*k->ptr); close(c*k->fd); c*k->ptr = NULL; c*k->fd = -1; c*k->status = 0; lua_pushnil(c*k->L); lua_pushstring(c*k->L, "Network Error"); return 2; } else { c*k->timeout_ptr = add_timeout(c*k, c*k->timeout, timeout_handle); c*k->inuse = 1; return lua_yield(L, 0); } } else { return 0 - ret; } } }