body write to CGI now monitored by epoll
+ kermit.jpg :)
This commit is contained in:
@@ -66,6 +66,28 @@ size_t Webserv::_cgi_pos(Client *client, std::string &path, size_t pos)
|
||||
return NPOS;
|
||||
}
|
||||
|
||||
void Webserv::_cgi_open_pipes(Client *client)
|
||||
{
|
||||
#define R 0
|
||||
#define W 1
|
||||
|
||||
int fd_in[2];
|
||||
int fd_out[2];
|
||||
::pipe(fd_in);
|
||||
::pipe(fd_out);
|
||||
|
||||
client->cgi_pipe_r_from_parent = fd_in[R];
|
||||
client->cgi_pipe_w_to_child = fd_in[W];
|
||||
client->cgi_pipe_r_from_child = fd_out[R];
|
||||
client->cgi_pipe_w_to_parent = fd_out[W];
|
||||
|
||||
// epoll add for writing body to child
|
||||
_epoll_update(client->cgi_pipe_w_to_child, EPOLLOUT, EPOLL_CTL_ADD);
|
||||
// stop monitoring client->fd until we can write body
|
||||
_epoll_update(client->get_cl_fd(), 0, EPOLL_CTL_DEL);
|
||||
client->cgi_state = CGI_WAIT_TO_EXEC;
|
||||
}
|
||||
|
||||
void Webserv::_exec_cgi(Client *client)
|
||||
{
|
||||
char* env_cstr[19] = {NULL};
|
||||
@@ -152,24 +174,11 @@ void Webserv::_set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vect
|
||||
|
||||
void Webserv::_exec_script(Client *client, char *env[])
|
||||
{
|
||||
#define RD 0
|
||||
#define WR 1
|
||||
#define FD_WR_TO_CHLD fd_in[WR]
|
||||
#define FD_WR_TO_PRNT fd_out[WR]
|
||||
#define FD_RD_FR_CHLD fd_out[RD]
|
||||
#define FD_RD_FR_PRNT fd_in[RD]
|
||||
|
||||
pid_t pid;
|
||||
char * const nll[1] = {NULL};
|
||||
std::string script_output;
|
||||
std::string body = client->get_rq_body();
|
||||
int fd_in[2];
|
||||
int fd_out[2];
|
||||
std::string path;
|
||||
|
||||
::pipe(fd_in);
|
||||
::pipe(fd_out);
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
std::perror("err fork()");
|
||||
@@ -178,52 +187,57 @@ void Webserv::_exec_script(Client *client, char *env[])
|
||||
std::signal(SIGPIPE, SIG_DFL);
|
||||
std::signal(SIGINT, SIG_DFL);
|
||||
|
||||
_close_all_clients_fd();
|
||||
::close(_epfd);
|
||||
::close(FD_WR_TO_CHLD);
|
||||
::close(FD_RD_FR_CHLD);
|
||||
if (dup2(FD_RD_FR_PRNT, STDIN_FILENO) == -1)
|
||||
if (dup2(client->cgi_pipe_r_from_parent, STDIN_FILENO) == -1)
|
||||
{
|
||||
std::perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
if (::close(client->cgi_pipe_r_from_parent) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
if (::close(client->cgi_pipe_w_to_parent) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
throw ExecFail();
|
||||
}
|
||||
if (dup2(FD_WR_TO_PRNT, STDOUT_FILENO) == -1)
|
||||
if (dup2(client->cgi_pipe_w_to_parent, STDOUT_FILENO) == -1)
|
||||
{
|
||||
std::perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
if (::close(client->cgi_pipe_r_from_parent) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
if (::close(client->cgi_pipe_w_to_parent) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
throw ExecFail();
|
||||
}
|
||||
|
||||
::close(FD_RD_FR_PRNT);
|
||||
::close(FD_WR_TO_PRNT);
|
||||
_close_all_clients_fd();
|
||||
if (::close(_epfd) == -1)
|
||||
std::perror("err close");
|
||||
|
||||
path = client->get_rq_script_path(); // Wut ? Only relative path ?
|
||||
/*DEBUG*/std::cerr << "execve:[" << path << "]\n";
|
||||
if (::execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing
|
||||
{
|
||||
std::perror("err execve()");
|
||||
::close(STDIN_FILENO); // Valgind debug, not essential
|
||||
::close(STDOUT_FILENO); // Valgind debug, not essential
|
||||
if (::close(STDIN_FILENO) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
if (::close(STDOUT_FILENO) == -1) // Valgind debug, not essential
|
||||
std::perror("err close");
|
||||
throw ExecFail();
|
||||
}
|
||||
}
|
||||
else //parent
|
||||
{
|
||||
::close(FD_RD_FR_PRNT);
|
||||
::close(FD_WR_TO_PRNT);
|
||||
::write(FD_WR_TO_CHLD, body.c_str(), body.size()); // move this before the fork ?
|
||||
::close(FD_WR_TO_CHLD);
|
||||
if (::close(client->cgi_pipe_r_from_parent) == -1)
|
||||
std::perror("err close");
|
||||
if (::close(client->cgi_pipe_w_to_parent) == -1)
|
||||
std::perror("err close");
|
||||
if (::close(client->cgi_pipe_w_to_child) == -1)
|
||||
std::perror("err close");
|
||||
|
||||
// add FD_RD_FR_CHLD to epoll,
|
||||
_epoll_update(FD_RD_FR_CHLD, EPOLLIN, EPOLL_CTL_ADD);
|
||||
// add client->cgi_pipe_r_from_child to epoll,
|
||||
_epoll_update(client->cgi_pipe_r_from_child, EPOLLIN, EPOLL_CTL_ADD);
|
||||
// stop monitoring client->fd until the cgi-script as done is job
|
||||
_epoll_update(client->get_cl_fd(), 0, EPOLL_CTL_DEL);
|
||||
|
||||
client->cgi_pipe_rfd = FD_RD_FR_CHLD;
|
||||
client->cgi_pid = pid;
|
||||
client->cgi_state = CGI_WAIT_FOR_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,15 +255,15 @@ void Webserv::_check_script_output(Client *client, std::string & output)
|
||||
_check_script_status(client, output);
|
||||
if (client->status >= 400 && client->status < 600)
|
||||
return;
|
||||
/*DEBUG*/ std::cout << "\n" B_PURPLE "[script status]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script status]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
client->status = _check_script_fields(output, client->status);
|
||||
/*DEBUG*/ std::cout << "\n" B_PURPLE "[script fields]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script fields]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
_check_fields_duplicates(client, output);
|
||||
/*DEBUG*/ std::cout << "\n" B_PURPLE "[fields duplicates]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
// /*DEBUG*/ std::cout << "\n" B_PURPLE "[fields duplicates]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
_remove_body_leading_empty_lines(output);
|
||||
/*DEBUG*/ std::cout << "\n" B_PURPLE "[script empty lines]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script empty lines]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
_add_script_body_length_header(output);
|
||||
/*DEBUG*/ std::cout << "\n" B_PURPLE "[script content length]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script content length]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n";
|
||||
}
|
||||
|
||||
void Webserv::_check_script_status(Client *client, std::string & output)
|
||||
|
||||
Reference in New Issue
Block a user