diff --git a/srcs/Server/Connection.cpp b/srcs/Server/Connection.cpp new file mode 100644 index 0000000..43478df --- /dev/null +++ b/srcs/Server/Connection.cpp @@ -0,0 +1,213 @@ +#include "Connection.hpp" +#include "Request.hpp" +#include "Server.hpp" +#include "Router.hpp" +#include "CgiSocketFactory.hpp" + +Connection::Connection(ClSocket *sock) +{ + client = sock; + recvMessage = new Request(sock); +} + +Connection::~Connection() +{ +} + +#define MSG_LIMIT 10000000000 + +ssize_t clientRead(ClSocket *client, HttpMessage *m) +{ + ssize_t recv_ret; + + static char buffer[BUFFER_LEN]; + client->updateLastAccess(); + recv_ret = ::recv(client->getFd(), buffer, BUFFER_LEN, 0); + if (recv_ret == -1) + { + perror("recv::: "); + return (-1); + } + try { + m->parsing(std::string(buffer, (std::size_t)recv_ret), MSG_LIMIT); + return (recv_ret); + } + catch (const std::exception &e) { + return (-1); + } +} + +bool ClientConnectionErr(ssize_t ret, Socket *sock) +{ + if (ret > 0) + return (false); + return (ret == -1 && dynamic_cast(sock)); +} + +bool isClient(Socket *sock) +{ + return (dynamic_cast(sock) != NULL); +} + +Socket *getHandleSock(Socket *sock, HttpMessage *recvdMessage, HttpMessage *toSendMessage) +{ + ClSocket *clSock = NULL; + if (CgiSocket *cgiSock = dynamic_cast(sock)) // from cgi + { + clSock = cgiSock->moveClSocket(); + delete (sock); + } + else + clSock = dynamic_cast(sock); // from client + if (dynamic_cast(toSendMessage)) + return CgiSocketFactory::create(*recvdMessage, clSock); // to cgi + else + return (clSock); // to client +} + +sConnection setNewSendMessage(Socket *sock, HttpMessage *message) +{ + #ifdef TEST + std::cout << "setNewSendMessage [" << message->getRaw() << "]" << std::endl; + #endif + + Router router; + // ルーティング + HttpMessage *newMessage = router.routeHandler(*message, sock); + if (newMessage == NULL) + return (sConnection(NULL, NULL, ERROR)); + Socket *handleSock = getHandleSock(sock, message, newMessage); + if (handleSock == NULL) + { + delete (newMessage); + return (sConnection(NULL, NULL, ERROR)); + } + return (sConnection(handleSock, newMessage, WRITE)); +} + +ssize_t clientWrite(Socket *sock, HttpMessage *message) +{ + ssize_t ret; + const uint8_t *buffer; + + sock->updateLastAccess(); + buffer = message->getSendBuffer(); + if (buffer == NULL) + return (-1); + ret = ::send(sock->getFd(), buffer, message->getContentLengthRemain(), 0); + if (ret >= 0) // 0 も含んでるのはcgiのために超大事 + message->addSendPos(ret); + return (ret); +} + +sConnection finishSend(Socket *sock) +{ + if (CgiSocket *cgiSock = dynamic_cast(sock)) + { + (void)cgiSock; + // if ((shutdown(sock->getFd(), SHUT_WR) == -1 && errno != ENOTCONN) + // || addMapAndSockList(sock, new(std::nothrow) CgiResponse(), E_RECV)) + // { + // perror("shutdown: "); + // setCgiErrorResponse(cgiSock, false); + // socketDeleter(cgiSock); + // return (1); + // } + return (sConnection(NULL, NULL, ERROR)); + } + else + { + ClSocket *clSock = dynamic_cast(sock); + if (clSock->getMaxRequest() == 0) + return (sConnection(NULL, NULL, ERROR)); + else + return (sConnection(clSock, new Request(clSock), READ)); + } +} + +sSelectRequest Connection::handleEvent(sSelectRequest req, bool isSet) +{ + if (getFd(req) != client->getFd()) + return -1; + else if (!isSet) + { + if (client->isTimeout()) + { + // タイムアウト処理 + return -1; + } + else + return req; + } + else if (getType(req) == READ) + { + if (getFd(req) == client->getFd()) + { + ssize_t ret = clientRead(client, recvMessage); + if (ClientConnectionErr(ret, client)) + { + delete recvMessage; + delete client; + return -1; + } + else if (ret <= 0 || + (isClient(client) && (recvMessage->isCompleted() || recvMessage->isInvalid()))) + { + // createResponse + sConnection newMessage = setNewSendMessage(client, recvMessage); + delete recvMessage; + if (newMessage.type == ERROR) + { + delete client; + return -1; + } + else + { + client = dynamic_cast(newMessage.sock); + sendMessage = newMessage.message; + return createRequest(client->getFd(), newMessage.type); + } + } + } + } + else if (getType(req) == WRITE) + { + // bool isCgi = getFd(req) != cgiFd; + // cgi はまだ実装していない + bool isCgi = false; + + ssize_t ret = clientWrite(client, sendMessage); + if (isCgi == false && ret == -1) + { + delete sendMessage; + delete client; + return -1; + } + else if (sendMessage->doesSendEnd() || ret == -1) + { + finishSend(client); + delete sendMessage; + } + } + return 1; +} + +sSelectRequest Connection::createRequest(int fd, eSelectType type) +{ + return type * MAX_SOCKETS + fd; +} + +int Connection::getFd(sSelectRequest r) +{ + return r % MAX_SOCKETS; +} + +eSelectType Connection::getType(sSelectRequest r) +{ + return (eSelectType)(r / MAX_SOCKETS); +} + +int Connection::getFd() const +{ + return client->getFd(); +} \ No newline at end of file diff --git a/srcs/Server/Connection.hpp b/srcs/Server/Connection.hpp new file mode 100644 index 0000000..0feffbd --- /dev/null +++ b/srcs/Server/Connection.hpp @@ -0,0 +1,65 @@ +#ifndef CONNECTION_HPP +#define CONNECTION_HPP + +#include "Socket.hpp" +#include "HttpMessage.hpp" + +typedef int sSelectRequest; + +enum eSelectType +{ + READ, + WRITE, + ERROR, +}; + +struct sConnection { + sConnection(Socket *sock, HttpMessage *message, eSelectType type): sock(sock), message(message), type(type) {} + + Socket *sock; + HttpMessage *message; + eSelectType type; +}; + +#define MAX_SOCKETS 1024 + +/* +input: イベント(isSet) +calculate: イベント処理 +output: 監視対象のファイルディスクリプタとイベントタイプ + +イベント処理 +if read + if cgiFd + cgiFdを読み込む + else + clientFdを読み込む +else if write + if cgiFd + cgiFdを書き込む + else + clientFdを書き込む +else + エラー +*/ + + +class Connection +{ +private: + ClSocket *client; + HttpMessage *recvMessage; + HttpMessage *sendMessage; + +public: + Connection(ClSocket *sock); + ~Connection(); + sSelectRequest handleEvent(sSelectRequest req, bool isSet); + int getFd() const; + + static int getFd(sSelectRequest req); + static eSelectType getType(sSelectRequest req); + static sSelectRequest createRequest(int fd, eSelectType type); +}; + +#endif diff --git a/srcs/Server/Server.cpp b/srcs/Server/Server.cpp index 3cdb9d7..3b7d007 100644 --- a/srcs/Server/Server.cpp +++ b/srcs/Server/Server.cpp @@ -20,33 +20,13 @@ Server::Server() { } Server::~Server() { - // std::map::iterator itr1; - // for (itr1 = Recvs.begin(); itr1 != Recvs.end(); itr1++) - // delete (itr1->second); - // for (itr1 = Sends.begin(); itr1 != Sends.end(); itr1++) - // delete (itr1->second); - std::list::iterator itr2; for (itr2 = server_sockets.begin(); itr2 != server_sockets.end();) { std::list::iterator sockNode = itr2++; - socketDeleter(*sockNode); + delete ((*sockNode)); server_sockets.erase(sockNode); } - for (itr2 = recv_sockets.begin(); itr2 != recv_sockets.end();) - { - std::list::iterator sockNode = itr2++; - Socket *sock = *sockNode; - deleteMapAndSockList(sockNode, E_RECV); - socketDeleter(sock); - } - for (itr2 = send_sockets.begin(); itr2 != send_sockets.end();) - { - std::list::iterator sockNode = itr2++; - Socket *sock = *sockNode; - deleteMapAndSockList(sockNode, E_SEND); - socketDeleter(sock); - } } int Server::setup() @@ -57,8 +37,11 @@ int Server::setup() for (itr = ports.begin(); itr != ports.end(); itr++) { - if (createServerSocket(strtoi(*itr))) + Socket *sock = new SvSocket(strtoi(*itr)); + if (sock == NULL) return (1); + server_sockets.push_back(sock); + _socketCount++; } memset(&timeout, 0, sizeof(timeout)); timeout.tv_sec = 1; @@ -78,10 +61,19 @@ int Server::run() fd_set write_fds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); + std::map::iterator itr; Server::set_fd_set(read_fds, server_sockets, max_fd); - Server::set_fd_set(read_fds, recv_sockets, max_fd); - Server::set_fd_set(write_fds, send_sockets, max_fd); - + for (itr = _connections.begin(); itr != _connections.end(); itr++) + { + const int fd = Connection::getFd(itr->first); + const eSelectType type = Connection::getType(itr->first); + if (type == READ) + FD_SET(fd, &read_fds); + else + FD_SET(fd, &write_fds); + if (fd > max_fd) + max_fd = fd; + } int activity = select(max_fd + 1, &read_fds, &write_fds, NULL, &timeout); if (activity == -1 && errno != EINTR) throw ServerException("select"); @@ -89,287 +81,59 @@ int Server::run() } } -/** - * @brief サーバーソケット作成 - * - * @param port - * @return int - */ -int Server::createServerSocket(int port) throw() -{ - Socket *sock = new SvSocket(port); - if (sock == NULL) - return (1); - if (setSocket(E_SERVER, sock)) - { - delete (sock); - return (1); - } - _socketCount++; - return (0); -} - -bool ClientConnectionErr(ssize_t ret, Socket *sock) -{ - if (ret > 0) - return (false); - return (ret == -1 && dynamic_cast(sock)); -} - bool ClientClosedConnection(ssize_t ret, Socket *sock) { return (ret == 0 && dynamic_cast(sock) && shutdown(sock->getFd(), SHUT_RD) == -1 && errno == ENOTCONN); } -bool isClient(Socket *sock) -{ - return (dynamic_cast(sock) != NULL); -} - -int Server::setCgiErrorResponse(CgiSocket *cgiSock, bool timeout) -{ - if (timeout && cgiSock->killCgi()) - perror("kill: "); - if (ClSocket *clSock = cgiSock->moveClSocket()) - { - clSock->updateLastAccess(); - if (addMapAndSockList(clSock, IHandler::handleError("500", clSock->getLocalPort()), E_SEND)) - { - socketDeleter(clSock); - return (1); - } - } - return (0); -} - -int Server::handleConnectionErr(E_TYPE type, std::list::iterator sockNode, bool timeout) -{ - Socket *sock = *sockNode; - CgiSocket *cgiSock = dynamic_cast(sock); - if (cgiSock) - setCgiErrorResponse(cgiSock, timeout); - deleteMapAndSockList(sockNode, type); - socketDeleter(sock); - return (0); -} - int Server::handleSockets(fd_set *read_fds, fd_set *write_fds, int activity) { std::list::iterator itr; std::list::iterator sockNode; Socket *sock; + std::map newConnections; // サーバーソケット受信 - for (itr = server_sockets.begin(); activity && itr != server_sockets.end();) { sockNode = itr++; sock = *sockNode; if (FD_ISSET(((sock)->getFd()), read_fds)) { - accept(sock); + Connection *newConnection = accept(sock); + sSelectRequest req = Connection::createRequest(newConnection->getFd(), READ); + newConnections[req] = newConnection; + _socketCount++; --activity; } } - // クライアントソケット受信 - for (itr = recv_sockets.begin(); itr != recv_sockets.end();) - { - sockNode = itr++; - sock = *sockNode; - if (FD_ISSET(sock->getFd(), read_fds) == false) - { - if (sock->isTimeout()) - handleConnectionErr(E_RECV, sockNode, true); - continue ; - } - --activity; - ssize_t ret = recv(sock, Recvs[sock]); - if (ClientConnectionErr(ret, sock)) - handleConnectionErr(E_RECV, sockNode, false); - else if (ret <= 0 || - (isClient(sock) && (Recvs[sock]->isCompleted() || Recvs[sock]->isInvalid()))) - { - setNewSendMessage(sock, Recvs[sock]); - deleteMapAndSockList(sockNode, E_RECV); - } - } - // クライアントソケット送信 - for (itr = send_sockets.begin(); itr != send_sockets.end();) + std::map::iterator itr2; + for (itr2 = _connections.begin(); activity && itr2 != _connections.end();) { - sockNode = itr++; - sock = *sockNode; - if (FD_ISSET(sock->getFd(), write_fds) == false) - { - if (sock->isTimeout()) - handleConnectionErr(E_SEND, sockNode, true); - continue ; - } - --activity; - bool isCgi = (dynamic_cast(sock) != NULL); - ssize_t ret = send(sock, Sends[sock]); - if (isCgi == false && ret == -1) - { - deleteMapAndSockList(sockNode, E_SEND); - socketDeleter(sock); - } - else if (Sends[sock]->doesSendEnd() || ret == -1) - { - finishSend(sock); - deleteMapAndSockList(sockNode, E_SEND); - } + Connection *connection = itr2->second; + const sSelectRequest r = itr2->first; + const int fd = Connection::getFd(r); + const bool fdIsSet = Connection::getType(r) == READ ? FD_ISSET(fd, read_fds) : FD_ISSET(fd, write_fds); + + const sSelectRequest req = connection->handleEvent(r, fdIsSet); + if (req != -1) + newConnections[req] = connection; + itr2++; } + _connections = newConnections; return (0); } -int Server::accept(Socket *serverSock) +Connection *Server::accept(Socket *serverSock) { if (_socketCount >= MAX_SOCKETS) - return (0); + return (NULL); SvSocket *svSock = dynamic_cast(serverSock); ClSocket *newClSock = svSock->dequeueSocket(); if (newClSock == NULL) - return (0); - if (addMapAndSockList(newClSock, new Request(newClSock), E_RECV)) - { - socketDeleter(newClSock); - return (1); - } - _socketCount++; - return (0); -} - -int Server::recv(Socket *sock, HttpMessage *message) { - ssize_t recv_ret; - - static char buffer[BUFFER_LEN]; - sock->updateLastAccess(); - recv_ret = ::recv(sock->getFd(), buffer, BUFFER_LEN, 0); - if (recv_ret == -1) - { - perror("recv::: "); - return (-1); - } - try { - message->parsing(std::string(buffer, (std::size_t)recv_ret), _limitClientMsgSize); - return (recv_ret); - } - catch (const std::exception &e) { - return (-1); - } -} - -ssize_t Server::send(Socket *sock, HttpMessage *message) -{ - ssize_t ret; - const uint8_t *buffer; - - sock->updateLastAccess(); - buffer = message->getSendBuffer(); - if (buffer == NULL) - return (-1); - ret = ::send(sock->getFd(), buffer, message->getContentLengthRemain(), 0); - if (ret >= 0) // 0 も含んでるのはcgiのために超大事 - message->addSendPos(ret); - return (ret); -} - -Socket *Server::getHandleSock(Socket *sock, HttpMessage *recvdMessage, HttpMessage *toSendMessage) -{ - ClSocket *clSock = NULL; - if (CgiSocket *cgiSock = dynamic_cast(sock)) // from cgi - { - clSock = cgiSock->moveClSocket(); - socketDeleter(cgiSock); - } - else - clSock = dynamic_cast(sock); // from client - if (dynamic_cast(toSendMessage)) - { - CgiSocket *newCgiSock; - if ((newCgiSock = CgiSocketFactory::create(*recvdMessage, clSock))) // to cgi - _socketCount++; - return (newCgiSock); - } - else - return (clSock); // to client -} - -// bool じゃなくて dynamic_cast で判定したほうがいいかも -int Server::setNewSendMessage(Socket *sock, HttpMessage *message) -{ - #ifdef TEST - std::cout << "setNewSendMessage [" << message->getRaw() << "]" << std::endl; - #endif - - Router router; - // ルーティング - HttpMessage *newMessage = router.routeHandler(*message, sock); - if (newMessage == NULL) - return (1); - Socket *handleSock = getHandleSock(sock, message, newMessage); - if (handleSock == NULL) - { - delete (newMessage); - return (1); - } - if (addMapAndSockList(handleSock, newMessage, E_SEND)) - { - socketDeleter(handleSock); - return (1); - } - return (0); -} - -int Server::finishSend(Socket *sock) -{ - if (CgiSocket *cgiSock = dynamic_cast(sock)) - { - if ((shutdown(sock->getFd(), SHUT_WR) == -1 && errno != ENOTCONN) - || addMapAndSockList(sock, new(std::nothrow) CgiResponse(), E_RECV)) - { - perror("shutdown: "); - setCgiErrorResponse(cgiSock, false); - socketDeleter(cgiSock); - return (1); - } - } - else if (ClSocket *clSock = dynamic_cast(sock)) - { - if (clSock->getMaxRequest() == 0) - socketDeleter(clSock); - else if (addMapAndSockList(sock, new Request((ClSocket *)sock), E_RECV)) - socketDeleter(clSock); - } - return (0); -} - -/** - * @brief 指定したソケットを監視対象に追加する - * - * @param type - * @param sock - * @param client_sock - * @return int - */ -int Server::setSocket(E_TYPE type, Socket *sock) throw () -{ - try - { - if (type == E_RECV) - recv_sockets.push_back(sock); - else if (type == E_SEND) - send_sockets.push_back(sock); - else if (type == E_SERVER) - server_sockets.push_back(sock); - else - return (1); - return (0); - } - catch(const std::exception& e) - { - return (1); - } + return (NULL); + return (new Connection(newClSock)); } int Server::set_fd_set(fd_set &set, std::list sockets, int &maxFd) throw () @@ -387,66 +151,29 @@ int Server::set_fd_set(fd_set &set, std::list sockets, int &maxFd) thr return (0); } -// 例外: 強い保証 + message を削除する -int Server::addMapAndSockList(Socket *sock, HttpMessage *message, S_TYPE type) throw () -{ - if (message == NULL) - return (1); - std::map *map = NULL; - if (type == E_RECV) - map = &Recvs; - else if (type == E_SEND) - map = &Sends; - if (addMessageToMap(*map, sock, message)) - { - delete (message); - return (1); - } - if (setSocket(type, sock)) - { - map->erase(sock); - delete (message); - return (1); - } - return (0); -} - -// 失敗しない保障 -int Server::deleteMapAndSockList(std::list::iterator sockNode, S_TYPE type) throw() -{ - // delete Map - std::map *map = NULL; - if (type == E_RECV) - map = &Recvs; - else if (type == E_SEND) - map = &Sends; - delete ((*map)[*sockNode]); - map->erase(*sockNode); - - // delete SockList - if (type == E_RECV) - recv_sockets.erase(sockNode); - else if (type == E_SEND) - send_sockets.erase(sockNode); - return (0); -} - -// 例外: 強い保証 -int Server::addMessageToMap(std::map &map, Socket *sock, HttpMessage *message) throw() -{ - try { - map[sock] = message; - } - catch (const std::exception &e) - { - return (1); - } - return (0); -} - -// 失敗しない保障 -void Server::socketDeleter(Socket *sock) throw () -{ - delete (sock); - _socketCount--; -} +// int Server::setCgiErrorResponse(CgiSocket *cgiSock, bool timeout) +// { +// if (timeout && cgiSock->killCgi()) +// perror("kill: "); +// if (ClSocket *clSock = cgiSock->moveClSocket()) +// { +// clSock->updateLastAccess(); +// if (addMapAndSockList(clSock, IHandler::handleError("500", clSock->getLocalPort()), E_SEND)) +// { +// socketDeleter(clSock); +// return (1); +// } +// } +// return (0); +// } + +// int Server::handleConnectionErr(E_TYPE type, std::list::iterator sockNode, bool timeout) +// { +// Socket *sock = *sockNode; +// CgiSocket *cgiSock = dynamic_cast(sock); +// if (cgiSock) +// setCgiErrorResponse(cgiSock, timeout); +// deleteMapAndSockList(sockNode, type); +// socketDeleter(sock); +// return (0); +// } \ No newline at end of file diff --git a/srcs/Server/Server.hpp b/srcs/Server/Server.hpp index 4ea2989..7900941 100644 --- a/srcs/Server/Server.hpp +++ b/srcs/Server/Server.hpp @@ -19,6 +19,7 @@ #include "Socket.hpp" #include "HttpMessage.hpp" #include "Response.hpp" +#include "Connection.hpp" #define BUFFER_LEN 10000 #define MAX_SOCKETS 1024 @@ -45,31 +46,19 @@ class Server private: std::list server_sockets; - std::list recv_sockets; - std::list send_sockets; - std::map Recvs; - std::map Sends; timeval timeout; std::size_t _limitClientMsgSize; int _socketCount; + std::map _connections; Socket *getHandleSock(Socket *sock, HttpMessage *recvdMessage, HttpMessage *toSendMessage); int handleSockets(fd_set *read_fds, fd_set *write_fds, int activity); - int accept(Socket *serverSocket); - int recv(Socket *sock, HttpMessage *message); - ssize_t send(Socket *sock, HttpMessage *message); - int setNewSendMessage(Socket *sock, HttpMessage *message); - int finishSend(Socket *sock); + Connection *accept(Socket *serverSock); int handleConnectionErr(E_TYPE type, std::list::iterator sockNode, bool timeout); int setCgiErrorResponse(CgiSocket *cgiSock, bool timeout); // utils - static int addMessageToMap(std::map &map, Socket *sock, HttpMessage *message) throw() ; - int addMapAndSockList(Socket *sock, HttpMessage *message, S_TYPE type) throw (); - int deleteMapAndSockList(std::list::iterator sockNode, S_TYPE type) throw(); - void socketDeleter(Socket *sock) throw(); int createServerSocket(int port) throw(); - int setSocket(E_TYPE type, Socket *sock) throw(); static int set_fd_set(fd_set &set, std::list sockets, int &maxFd) throw(); }; #endif