Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement running multiple servers #58

Merged
merged 1 commit into from
Oct 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ INCLUDE_FLAGS = -I srcs
TARGET = webserv

SRCS_FILES = main.cpp utils.cpp \
Master.cpp Worker.cpp Request.cpp Response.cpp Cgi.cpp Uri.cpp \
Nginxs.cpp Master.cpp Worker.cpp Request.cpp Response.cpp Cgi.cpp Uri.cpp \
autoindex/AutoindexData.cpp autoindex/Autoindex.cpp \
config/Config.cpp config/Block.cpp
SRCS = $(addprefix ./srcs/, $(SRCS_FILES))
Expand Down
File renamed without changes.
67 changes: 67 additions & 0 deletions conf/webserv.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
server {
listen 0.0.0.0:4242;

server_name xxx.xxx.com localhost;
root html;
client_max_body_size 4242;

error_page 400 error_pages/400.html;
error_page 403 error_pages/403.html;
error_page 404 error_pages/404.html;
error_page 405 error_pages/405.html;
error_page 500 error_pages/500.html;
error_page 505 error_pages/505.html;

location / {
location /*.py {
cgi ./cgi-bin/python-cgi.py;
}
index abc.html;
}

location /data {
autoindex on;
allowed_methods GET;
}

location /errors {
}

location /admin {
index index.html;
}
}

server {
listen 0.0.0.0:2424;

server_name xxx.xxx.com localhost;
root html;
client_max_body_size 4242;

error_page 400 error_pages/400.html;
error_page 403 error_pages/403.html;
error_page 404 error_pages/404.html;
error_page 405 error_pages/405.html;
error_page 500 error_pages/500.html;
error_page 505 error_pages/505.html;

location / {
location /*.py {
cgi ./cgi-bin/python-cgi.py;
}
index abc.html;
}

location /data {
autoindex on;
allowed_methods GET;
}

location /errors {
}

location /admin {
index index.html;
}
}
122 changes: 50 additions & 72 deletions srcs/Master.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,45 @@ const char *Master::MasterException::what() const throw() {
return message_.c_str();
}

Master::Master(char **env) {
struct sockaddr_in serverAddress;
Master::Master() {}

init(serverAddress);
bind(serverAddress);
Master::Master(const Block &serverBlock)
: serverBlock_(serverBlock) {
init();
bind();
listen();
setEnv(env);
}

Master::~Master() {
std::vector<Worker *>::iterator itBegin = workers_.begin();
std::vector<Worker *>::iterator itEnd = workers_.end();
std::vector<Worker *>::iterator it;

while (itBegin != itEnd) {
delete *itBegin;
++itBegin;
}
}

void Master::setEnv(char **originalEnv) {
while (originalEnv && *originalEnv) {
env_.push_back(std::string(*originalEnv));
originalEnv++;
}
for (it = workers_.begin(); it != workers_.end(); it++)
delete *it;
}

void Master::addEnv(std::string new_env) {
env_.push_back(new_env);
}

void Master::init(struct sockaddr_in &serverAddress) {
void Master::init() {
int yes = 1;

listenSocket_ = socket(PF_INET, SOCK_STREAM, 0);
std::cout << "listenSocket: " << listenSocket_ << std::endl;
std::cout << "Port: " << serverBlock_.getPort() << std::endl;
if (listenSocket_ == FT_ERROR)
throw MasterException("fail: socket()\n");
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_len = sizeof(struct sockaddr_in);
serverAddress.sin_family = PF_INET;
serverAddress.sin_port = htons(4242);
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
throw MasterException("init: socket() failed");
memset(&serverAddress_, 0, sizeof(serverAddress_));
serverAddress_.sin_len = sizeof(struct sockaddr_in);
serverAddress_.sin_family = PF_INET;
serverAddress_.sin_port = htons(serverBlock_.getPort());
serverAddress_.sin_addr.s_addr = htonl(inet_addr(serverBlock_.getHost().c_str()));
setsockopt(listenSocket_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
}

void Master::bind(struct sockaddr_in &serverAddress) {
void Master::bind() {
int ret;

ret = ::bind(listenSocket_, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
ret = ::bind(listenSocket_, (const struct sockaddr *)&serverAddress_, sizeof(serverAddress_));
if (ret == FT_ERROR) {
close(listenSocket_);
throw MasterException("fail: bind()\n");
throw MasterException("bind: bind() failed");
}
}

Expand All @@ -71,54 +58,45 @@ void Master::listen() {
ret = ::listen(listenSocket_, 2);
if (ret == -1) {
close(listenSocket_);
throw MasterException("fail: listen()\n");
throw MasterException("listen: listen() failed");
}
}

void Master::run() {
int i;
int ret;
int ret;
std::vector<Worker *>::iterator itBegin = workers_.begin();
std::vector<Worker *>::iterator itEnd = workers_.end();

while (itBegin != itEnd) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분에서 leak 문제 없을까요? for문으로 사용할 수 없을지 검색해보다가, 포인터 배열 다루다가 메모리 누수 많이 난다고 봐서요..!

Copy link
Collaborator Author

@hhkim0729 hhkim0729 Oct 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 찾았습니다... for문으로 바꾸는 게 깔끔할 것 같아요~! 저거 작성할 때는 저희가 이터레이터 쓰는 방법을 잘 모를 때 저렇게 작성했던 것 같습니다. 이전에 Master에 있던 코드 그대로입니다..

누수는 추후에 리팩토링 하면서 다시 확인해봐야 할 것 같습니다.

ret = (*itBegin)->work();
if (ret == FT_FALSE) {
delete *itBegin;
itBegin = workers_.erase(itBegin);
continue ;
}
++itBegin;
}
}

pollfds_[0].fd = listenSocket_;
pollfds_[0].events = POLLIN | POLLOUT;
pollfds_[0].revents = 0;
void Master::appendWorker(struct pollfd *pollFd) {
Worker *worker = new Worker(listenSocket_);

for (i = 1; i < POLLFDSLEN; i++)
pollfds_[i].fd = -1;
worker->setPollfd(pollFd);
workers_.push_back(worker);
}

while (1) {
ret = poll(pollfds_, POLLFDSLEN, -1);
if (ret == -1) {
close(listenSocket_);
throw MasterException("fail: poll()\n");
}
if (pollfds_[0].revents & POLLIN) {
Worker *worker = new Worker(listenSocket_);
worker->setPollfd(findEmptyPollfd());
workers_.push_back(worker);
}
const struct sockaddr_in Master::getServerAddress() const {
return serverAddress_;
}

std::vector<Worker *>::iterator itBegin = workers_.begin();
std::vector<Worker *>::iterator itEnd = workers_.end();

while (itBegin != itEnd) {
ret = (*itBegin)->work();
if (ret == FT_FALSE) {
delete *itBegin;
itBegin = workers_.erase(itBegin);
continue ;
}
++itBegin;
}
}
close(listenSocket_);
int Master::getListenSocket() const {
return listenSocket_;
}

struct pollfd *Master::findEmptyPollfd()
{
for (int i = 1; i < POLLFDSLEN; i++) {
if (pollfds_[i].fd == -1)
return &pollfds_[i];
}
return nullptr;
std::size_t Master::getPollIndex() const {
return pollIndex_;
}

void Master::setPollIndex(std::size_t pollIndex) {
pollIndex_ = pollIndex;
}
25 changes: 15 additions & 10 deletions srcs/Master.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,38 @@
#include <vector>
#include <iostream>
#include <exception>
#include "config/Block.hpp"
#include "Worker.hpp"
#include "macro.hpp"

#define POLLFDSLEN 100

class Master {
private:
std::vector<std::string> env_;
struct sockaddr_in serverAddress_;
int listenSocket_;
std::vector<Worker *> workers_;
struct pollfd pollfds_[POLLFDSLEN];
// Config config_;
Block serverBlock_;
std::size_t pollIndex_;

void init(struct sockaddr_in &serverAddress);
void bind(struct sockaddr_in &serverAddress);
void init();
void bind();
void listen();
struct pollfd *findEmptyPollfd();

Master();

public:
Master(char **env);
Master(const Block &serverBlock);
~Master();

void run();
void appendWorker(struct pollfd *pollFd);

void setEnv(char **originalEnv);
void addEnv(std::string new_env);
const struct sockaddr_in getServerAddress() const;
int getListenSocket() const;
std::size_t getPollIndex() const;

void setPollIndex(std::size_t pollIndex);

class MasterException : public std::exception {
private:
std::string message_;
Expand Down
76 changes: 76 additions & 0 deletions srcs/Nginxs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "Nginxs.hpp"

Nginxs::Nginxs() {}

Nginxs::Nginxs(const char *confFilePath) {
config_.parseConfigFile(confFilePath);
}

Nginxs::~Nginxs() {
std::vector<Master *>::iterator masterIt;

for (masterIt = masters_.begin(); masterIt != masters_.end(); masterIt++)
delete *masterIt;
}

void Nginxs::run() {
std::size_t i = 0;
int ret;

std::vector<Block> serverBlocks = config_.getServerBlocks();
std::vector<Block>::iterator it;
std::vector<Master *>::iterator masterIt;

for (it = serverBlocks.begin(); it != serverBlocks.end(); it++)
{
Master *m = new Master(*it);
m->setPollIndex(i);
std::cout << "setPollIndex: " << i << std::endl;
masters_.push_back(m);

pollfds_[i].fd = m->getListenSocket();
pollfds_[i].events = POLLIN | POLLOUT;
pollfds_[i].revents = 0;
i++;
}

// Initialize pollfds for workers
for (int fds = i; fds < POLLFDSLEN; fds++)
pollfds_[fds].fd = -1;

while (1) {
ret = poll(pollfds_, POLLFDSLEN, -1);
if (ret == -1) {
for (int fds = 0; fds < POLLFDSLEN; fds++) {
if (pollfds_[fds].fd != -1)
close(pollfds_[fds].fd);
}
throw std::runtime_error("run: poll() failed");
}
for(masterIt = masters_.begin(); masterIt != masters_.end(); masterIt++) {
if (pollfds_[(*masterIt)->getPollIndex()].revents & POLLIN) {
struct pollfd *emptyPollFd = findEmptyPollfd();
// // if (emptyPollFd == nullptr)
// // throw 503
// std::cout << "master: " << masterIt->getPollIndex() << std::endl;
(*masterIt)->appendWorker(emptyPollFd);
}
(*masterIt)->run();
}
}
for (int fds = 0; fds < POLLFDSLEN; fds++) {
if (pollfds_[fds].fd != -1)
close(pollfds_[fds].fd);
}
}

struct pollfd *Nginxs::findEmptyPollfd()
{
for (int i = 0; i < POLLFDSLEN; i++) {
if (pollfds_[i].fd == -1) {
std::cout << "pollfd index: " << i << std::endl;
return &pollfds_[i];
}
}
return nullptr;
}
Loading