static int processs_write(client_t *client) { VALUE iterator; VALUE v_body; VALUE item; char *buf; size_t buflen; write_bucket *bucket; int ret; // body iterator = client->response_iter; if(iterator != Qnil){ if (TYPE(iterator) != T_ARRAY || RARRAY_LEN(iterator) != 3){ return -1; } v_body = rb_ary_entry(iterator, 2); if(!rb_respond_to(v_body, i_each)){ return -1; } VALUE v_body_str = rb_str_new2(""); rb_block_call(v_body, i_each, 0, NULL, collect_body, v_body_str); if(rb_respond_to(v_body, i_close)) { rb_funcall(v_body, i_close, 0); } buf = StringValuePtr(v_body_str); buflen = RSTRING_LEN(v_body_str); bucket = new_write_bucket(client->fd, 1); set2bucket(bucket, buf, buflen); ret = writev_bucket(bucket); if(ret <= 0){ return ret; } //mark client->write_bytes += buflen; //check write_bytes/content_length if(client->content_length_set){ if(client->content_length <= client->write_bytes){ // all done /* break; */ } } close_response(client); } return 1; }
static inline void close_conn(client_t *cli, picoev_loop* loop) { client_t *new_client; if(!cli->response_closed){ close_response(cli); } picoev_del(loop, cli->fd); clean_cli(cli); #ifdef DEBUG printf("start close client:%p fd:%d status_code %d \n", cli, cli->fd, cli->status_code); printf("picoev_del client:%p fd:%d \n", cli, cli->fd); printf("remain http pipeline size :%d \n", cli->request_queue->size); #endif if(cli->request_queue->size > 0){ if(check_status_code(cli) > 0){ //process pipeline prepare_call_wsgi(cli); call_wsgi_app(cli, loop); } return ; } if(cli->http != NULL){ PyMem_Free(cli->http); } free_request_queue(cli->request_queue); if(!cli->keep_alive){ close(cli->fd); #ifdef DEBUG printf("close client:%p fd:%d status_code %d \n", cli, cli->fd, cli->status_code); #endif }else{ disable_cork(cli); new_client = new_client_t(cli->fd, cli->remote_addr, cli->remote_port); new_client->keep_alive = 1; init_parser(new_client, server_name, server_port); picoev_add(main_loop, new_client->fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)new_client); } //PyMem_Free(cli); dealloc_client(cli); #ifdef DEBUG printf("********************\n\n"); #endif }
static response_status process_sendfile(client_t *client) { PyObject *filelike = NULL; FileWrapperObject *filewrap = NULL; int in_fd, ret; filewrap = (FileWrapperObject *)client->response; filelike = filewrap->filelike; in_fd = PyObject_AsFileDescriptor(filelike); if (in_fd == -1) { PyErr_Clear(); return STATUS_OK; } while(client->content_length > client->write_bytes){ ret = write_sendfile(client->fd, in_fd, client->write_bytes, client->content_length); DEBUG("process_sendfile send %d", ret); switch (ret) { case 0: break; case -1: /* error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* try again later */ //next DEBUG("process_sendfile EAGAIN %d", ret); return STATUS_SUSPEND; } else { /* fatal error */ client->keep_alive = 0; /* client->bad_request_code = 500; */ client->status_code = 500; //close return STATUS_ERROR; } default: client->write_bytes += ret; } } //all send //disable_cork(client); return close_response(client); }
void Response::after_fork_child(STATE) { close_response(); }
void Response::stop_thread(STATE) { MachineThread::stop_thread(state); close_response(); }
static response_status process_write(client_t *client) { PyObject *iterator = NULL; PyObject *item, *chunk_data = NULL; char *buf = NULL, *lendata = NULL; Py_ssize_t buflen, len; write_bucket *bucket = NULL; response_status ret; DEBUG("process_write start"); iterator = client->response_iter; if(iterator != NULL){ while((item = PyIter_Next(iterator))){ if(PyBytes_Check(item)){ //TODO CHECK PyBytes_AsStringAndSize(item, &buf, &buflen); //write if(client->chunked_response){ bucket = new_write_bucket(client->fd, 4); if(bucket == NULL){ /* write_error_log(__FILE__, __LINE__); */ call_error_logger(); Py_DECREF(item); return STATUS_ERROR; } lendata = NULL; len = 0; chunk_data = get_chunk_data(buflen); //TODO CHECK ERROR PyBytes_AsStringAndSize(chunk_data, &lendata, &len); set_chunked_data(bucket, lendata, len, buf, buflen); bucket->chunk_data = chunk_data; }else{ bucket = new_write_bucket(client->fd, 1); if(bucket == NULL){ /* write_error_log(__FILE__, __LINE__); */ call_error_logger(); Py_DECREF(item); return STATUS_ERROR; } set2bucket(bucket, buf, buflen); } bucket->temp1 = item; ret = writev_bucket(bucket); if(ret != STATUS_OK){ client->bucket = bucket; /* Py_DECREF(item); */ return ret; } free_write_bucket(bucket); //mark client->write_bytes += buflen; //check write_bytes/content_length if(client->content_length_set){ if(client->content_length <= client->write_bytes){ // all done /* Py_DECREF(item); */ break; } } /* Py_DECREF(item); */ }else{ PyErr_SetString(PyExc_TypeError, "response item must be a byte string"); Py_DECREF(item); if (PyErr_Occurred()){ /* client->bad_request_code = 500; */ client->status_code = 500; /* write_error_log(__FILE__, __LINE__); */ call_error_logger(); return STATUS_ERROR; } } } if(PyErr_Occurred()){ return STATUS_ERROR; } if(client->chunked_response){ DEBUG("write last chunk"); //last packet bucket = new_write_bucket(client->fd, 3); if(bucket == NULL){ /* write_error_log(__FILE__, __LINE__); */ call_error_logger(); return STATUS_ERROR; } set_last_chunked_data(bucket); writev_bucket(bucket); free_write_bucket(bucket); } return close_response(client); } return STATUS_OK; }