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 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 network_be_read ( se_ptr_t *ptr ) { epdata_t *epd = ptr->data; if ( !epd ) { return 0; } int n = 0; update_timeout ( epd->timeout_ptr, STEP_READ_TIMEOUT ); if ( epd->headers == NULL ) { epd->headers = &epd->iov; epd->buf_size = sizeof ( epd->iov ); } else if ( epd->data_len == epd->buf_size ) { if ( epd->headers == &epd->iov ) { epd->headers = malloc ( 4096 * 2 ); memcpy ( epd->headers, &epd->iov, sizeof ( epd->iov ) ); epd->buf_size = 4096 * 2; } else { char *_t = ( char * ) realloc ( epd->headers, epd->buf_size + 4096 ); if ( _t != NULL ) { epd->headers = _t; } else { epd->iov[0].iov_base = NULL; epd->iov[0].iov_len = 0; epd->iov[1].iov_base = NULL; epd->iov[1].iov_len = 0; network_send_error ( epd, 503, "memory error!" ); close_client ( epd ); serv_status.reading_counts--; return 0; } epd->buf_size += 4096; } } while ( ( n = recv ( epd->fd, epd->headers + epd->data_len, epd->buf_size - epd->data_len, 0 ) ) >= 0 ) { if ( n == 0 ) { close_client ( epd ); epd = NULL; break; } if ( epd->data_len + n >= epd->buf_size ) { if ( epd->headers == &epd->iov ) { epd->headers = malloc ( 4096 * 2 ); memcpy ( epd->headers, &epd->iov, sizeof ( epd->iov ) ); epd->buf_size = 4096 * 2; } else { char *_t = ( char * ) realloc ( epd->headers, epd->buf_size + 4096 ); if ( _t != NULL ) { epd->headers = _t; } else { epd->iov[0].iov_base = NULL; epd->iov[0].iov_len = 0; epd->iov[1].iov_base = NULL; epd->iov[1].iov_len = 0; network_send_error ( epd, 503, "memory error!" ); close_client ( epd ); serv_status.reading_counts--; return 0; } epd->buf_size += 4096; } } if ( epd->status != STEP_READ ) { serv_status.reading_counts++; epd->status = STEP_READ; epd->data_len = n; epd->start_time = longtime(); } else { epd->data_len += n; } if ( epd->_header_length < 1 && epd->data_len >= 4 && epd->headers ) { int _get_content_length = 0; if ( epd->headers[epd->data_len - 1] == '\n' && ( epd->headers[epd->data_len - 2] == '\n' || ( epd->headers[epd->data_len - 4] == '\r' && epd->headers[epd->data_len - 2] == '\r' ) ) ) { epd->_header_length = epd->data_len; } else { _get_content_length = 1; unsigned char *fp2 = stristr ( epd->headers, "\r\n\r\n", epd->data_len ); if ( fp2 ) { epd->_header_length = ( fp2 - epd->headers ) + 4; } else { fp2 = stristr ( epd->headers, "\n\n", epd->data_len ); if ( fp2 ) { epd->_header_length = ( fp2 - epd->headers ) + 2; } } } if ( epd->_header_length > 0 && epd->content_length < 0 ) { /// not POST or PUT request if ( _get_content_length == 0 && epd->headers[0] != 'P' && epd->headers[0] != 'p' ) { epd->content_length = 0; } else { int flag = 0; unsigned char *fp = stristr ( epd->headers, "\ncontent-length:", epd->data_len ); if ( fp ) { int fp_at = fp - epd->headers + 16; int i = 0, _oc; for ( i = fp_at; i < epd->data_len; i++ ) { if ( epd->headers[i] == '\r' || epd->headers[i] == '\n' ) { flag = 1; fp = epd->headers + fp_at; _oc = epd->headers[i]; epd->headers[i] = '\0'; break; } } if ( flag ) { epd->content_length = atoi ( fp ); epd->headers[i] = _oc; } if ( stristr ( epd->headers + ( epd->_header_length - 60 ), "100-continue", epd->_header_length ) ) { network_raw_send ( epd->fd, "HTTP/1.1 100 Continue\r\n\r\n", 25 ); } } } } if ( epd->_header_length > 0 && epd->_header_length < epd->data_len && epd->content_length < 1 ) { epd->iov[0].iov_base = NULL; epd->iov[0].iov_len = 0; epd->iov[1].iov_base = NULL; epd->iov[1].iov_len = 0; network_send_error ( epd, 411, "" ); close_client ( epd ); epd = NULL; serv_status.reading_counts--; break; } } //printf("data_len = %d header_length = %d content_length = %d\n", epd->data_len, epd->_header_length, epd->content_length); if ( epd->_header_length > 0 && ( ( epd->content_length < 1 && epd->_header_length > 0 ) || epd->content_length <= epd->data_len - epd->_header_length ) ) { /// start job epd->header_len = epd->_header_length; epd->headers[epd->data_len] = '\0'; epd->header_len -= 1; epd->headers[epd->header_len] = '\0'; if ( epd->header_len + 1 < epd->data_len ) { epd->contents = epd->headers + epd->header_len + 1; } else { epd->content_length = 0; } if ( USE_KEEPALIVE == 1 && ( epd->keepalive == 1 || ( stristr ( epd->headers, "keep-alive", epd->header_len ) ) ) ) { epd->keepalive = 1; } epd->response_header_length = 0; epd->iov_buf_count = 0; epd->response_content_length = 0; epd->response_sendfile_fd = -1; /// output server status !!!!!!!!!! { int i, len; char *uri = NULL; uri = epd->headers; for ( i = 0; i < epd->header_len; i++ ) if ( uri[i] == ' ' ) { break; } for ( ; i < epd->header_len; i++ ) if ( uri[i] != ' ' ) { break; } uri = epd->headers + i; len = strlen ( uri ); for ( i = 0; i < len; i++ ) { if ( uri[i] == '\r' || uri[i] == '\n' || uri[i] == ' ' ) { break; } } if ( i > 11 && strncmp ( "/serv-status", uri, i ) == 0 ) { epd->process_timeout = 0; epd->iov[0].iov_base = NULL; epd->iov[0].iov_len = 0; epd->iov[1].iov_base = NULL; epd->iov[1].iov_len = 0; network_send_status ( epd ); serv_status.reading_counts--; break; } } /// end. se_be_pri ( epd->se_ptr, NULL ); // be wait if ( epd->status == STEP_READ ) { serv_status.reading_counts--; epd->status = STEP_PROCESS; serv_status.sec_process_counts[ ( now ) % 5]++; serv_status.process_counts++; epd->method = NULL; epd->uri = NULL; epd->host = NULL; epd->query = NULL; epd->http_ver = NULL; epd->referer = NULL; epd->user_agent = NULL; if ( process_func ( epd, 0 ) != 0 ) { close_client ( epd ); epd = NULL; } } break; } } if ( epd && n < 0 && errno != EAGAIN && errno != EWOULDBLOCK ) { //printf("error fd %d (%d) %s\n", epd->fd, errno, strerror(errno)); close_client ( epd ); epd = NULL; return 0; } return 1; }
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 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 _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; } }