void send_error_response(pConnInfo conn_info) {/*{{{*/ int status_code = conn_info->status_code; bool with_page; int return_page_status[4] = {404, 502, 500, 403}; if(in_int_array(return_page_status, status_code, 4) != -1) { with_page = true; } else { with_page = false; } char** error_pages = conn_info->running_server->error_page; int i; char *error_path = NULL; char *error_file_path; conn_info->status_code = status_code; while(*error_pages != NULL) { for(i = 0; i < strlen(*error_pages); i++) { if((*error_pages)[i] == '=') { (*error_pages)[i] = '\0'; if(atoi(*error_pages) == status_code) { error_path = uws_strdup(*error_pages + i + 1); (*error_pages)[i] = '='; break; } (*error_pages)[i] = '='; } } if(error_path != NULL) break; error_pages++; } int content_len; char *content; if(with_page) { error_file_path = uws_strdup("/dev/null"); //just for test if(error_path != NULL) { char *tmp_path = strlcat(conn_info->running_server->root, error_path); if(access(tmp_path, F_OK) == 0) { uws_free(error_file_path); error_file_path = tmp_path; uws_free(error_path); } else { uws_free(tmp_path); } } FILE* file = fopen(error_file_path, "r"); fseek(file, 0, SEEK_END); content_len = ftell(file); rewind(file); content = (char*) uws_malloc (content_len * sizeof(char)); size_t read_size = fread(content, sizeof(char), content_len, file); fclose(file); } else { content_len = 0; content = uws_strdup(""); } //go here char *time_string = get_time_string(NULL); conn_info->response_header->http_ver = "HTTP/1.1"; conn_info->response_header->status_code = status_code; conn_info->response_header->status = get_by_code(status_code); add_header_param("Cache-Control", "private", conn_info->response_header); add_header_param("Connection", "Keep-Alive", conn_info->response_header); add_header_param("Server", UWS_SERVER, conn_info->response_header); add_header_param("Date", time_string, conn_info->response_header); add_header_param("Content-Type", "text/html", conn_info->response_header); if(with_page) { char *content_len_str = itoa(content_len); add_header_param("Content-Length", content_len_str, conn_info->response_header); uws_free(content_len_str); } struct response header_body; header_body.header = conn_info->response_header; header_body.content = content; header_body.content_len = content_len; uws_free(time_string); write_response(conn_info, &header_body); free_header_params(header_body.header); //uws_free(header_body.header); don't free this!! uws_free(header_body.content); //longjmp(conn_info->error_jmp_buf, 1); }/*}}}*/
/** * Sets up a non-blocking socket */ static int socket_setup(struct server *s, struct server_cfg **servers) { int servers_num = 0; int i = 0; int ports_num = 0; // stat server conf num while (servers[servers_num++] != NULL); servers_num--; // stat distinct listen port num int *servers_port = (int *)malloc(sizeof(int) * servers_num); for(i = 0; i < servers_num; i++) { int listen_port = servers[i]->listen; if(in_int_array(servers_port, listen_port, ports_num) == -1) { servers_port[ports_num++] = listen_port; } } for(i = 0; i < ports_num; i++) { int reuse = 1; struct sockaddr_in addr; int fd, ret; memset(&addr, 0, sizeof(addr)); #if defined __BSD__ addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_family = AF_INET; addr.sin_port = htons(servers_port[i]); addr.sin_addr.s_addr = INADDR_ANY; /* create socket */ fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == fd) { slog(s, LOG_ERROR, strerror(errno), 0); free(servers_port); return -1; } /* reuse address if we've bound to it before. */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { slog(s, LOG_ERROR, strerror(errno), 0); free(servers_port); return -1; } /* set socket as non-blocking. */ ret = fcntl(fd, F_SETFD, O_NONBLOCK); if (0 != ret) { slog(s, LOG_ERROR, strerror(errno), 0); free(servers_port); return -1; } /* bind */ ret = bind(fd, (struct sockaddr*) &addr, sizeof(addr)); if (0 != ret) { slog(s, LOG_ERROR, "bind", 4); slog(s, LOG_ERROR, strerror(errno), 0); free(servers_port); return -1; } /* listen */ ret = listen(fd, SOMAXCONN); if (0 != ret) { slog(s, LOG_ERROR, strerror(errno), 0); free(servers_port); return -1; } /* set keepalive socket option to do with half connection */ int keep_alive = 1; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *) &keep_alive, sizeof(keep_alive)); /* start http server */ struct event *ev = event_new(s->base, fd, EV_READ | EV_PERSIST, server_can_accept, (void*) s); ret = event_add(ev, NULL); if (ret < 0) { slog(s, LOG_ERROR, "Error calling event_add on socket", 0); free(servers_port); return -1; } } free(servers_port); return 0; }