u413-284-si / webserv

This project is about setting up a http web server, providing a static website.
MIT License
0 stars 0 forks source link

18 response building handle cgi requests #72

Open u413-284-si opened 5 days ago

u413-284-si commented 5 days ago

Overview

  1. Introduce CGIHandler class
  2. Check for CGI in handleCompleteRequestHeader()
  3. Register CGI
  4. New Connection status: SendToCGI
  5. New Connection status: ReceiveFromCGI
  6. Signal handling in child
  7. Tests

re 1.

re 2.

re 3.

re 4.

re 5.

re 6.

re 7.

closes #18 closes #60

gwolf-011235 commented 3 days ago

[re3, last point]

this separation was required to avoid sending fds/sockets to the wrong connection...() function as several sockets and pipe fds can be triggering events at the same time

Could you elaborate on this?

I think firing for a specific connection could be

This means we could just check if the firing fd corresponds to the connection status. If not, just return. E.g. if connection_status == Connection::SendToCGI and fd == connection.clientFd -> return

This would eliminate the second dispatch function with the switch case, which could be integrated into the existing switch.

u413-284-si commented 2 days ago

[re3, last point]

this separation was required to avoid sending fds/sockets to the wrong connection...() function as several sockets and pipe fds can be triggering events at the same time

Could you elaborate on this?

I think firing for a specific connection could be

* clientFd

* pipeToCGIWriteEnd

* pipeFromCGIReadEnd

This means we could just check if the firing fd corresponds to the connection status. If not, just return. E.g. if connection_status == Connection::SendToCGI and fd == connection.clientFd -> return

This would eliminate the second dispatch function with the switch case, which could be integrated into the existing switch.

If I were to do that I would need to cover not only the two cases where a CGI action is asked for, but also all the other cases e.g. Connection::ReceiveBody where maybe a pipe fd comes in, but it should be the clientFd.

Just tried it out, it would look like this:

if ((connection.m_status == Connection::ReceiveFromCGI || connection.m_status == Connection::SendToCGI)
        && clientFd == connection.m_clientFd) {
        return;
    }

if ((connection.m_status == Connection::Idle || connection.m_status == Connection::ReceiveHeader
    || connection.m_status == Connection::ReceiveBody || connection.m_status == Connection::BuildResponse
    || connection.m_status == Connection::SendResponse)
&& clientFd != connection.m_clientFd) {
return;
}

If we were to integrate this before the switch, it would kinda render the switch useless, don't you think? Besides that it's pretty ugly. But yeah, that way we could loose the other handle function (which is honestly also ugly... not rly happy with either solutions, yet lacking an elegant one)

gwolf-011235 commented 2 days ago

I meant to add this check in the specific connection.. function.

E.g. connectionReceiveHeader() would have

if (clientFd != connection.clientfd) // if NOT equal then don't work
  return;

And likewise connectionSendToCGI() would have

if (clientFd == connection.clientfd) // if equal then don't work
  return;

This way the switch would route every connection status and each connection.. function makes sure that only correct fds are handled

u413-284-si commented 2 days ago

Ah, that makes more sense. Adapted and tested it. Works. Removed handleCGIConnections()

gwolf-011235 commented 2 days ago

Ah, that makes more sense. Adapted and tested it. Works. Removed handleCGIConnections()

After change unittest does not compile because of changed function signature

gwolf-011235 commented 2 days ago

Bug: we fork-exec but do not close file descriptors (mainly sockets, but also the epoll instance).

Reproduce: run with valgrind --trace-children=yes --track-fds=yes and execute cgi script.

Solution: "correct" way would be to mark the sockets and epoll with a "close-on-exec-flag". However we can't do it everywhere, because of limited functions allowed:

Alternative would be to just close by hand:

Note: since the destructor of ConfigFileParser() never gets called, the opened configfile also isn't closed. Should be fixed by #53, since file can be closed after read in as string

(edited)