Skip to content
Snippets Groups Projects
Commit 2a33ec9d authored by Mengqi Chen's avatar Mengqi Chen
Browse files

wip

parent 3813d331
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,7 @@
#include <iostream>
#include <cstring>
#include <sys/poll.h>
#include <fcntl.h>
#include "server_util.h"
#include "threadpool.h"
......@@ -35,6 +36,7 @@ int main(int argc, char **argv) {
int client_fds[num_threads];
int num_fds = 1;
int poll_timeout = -1; // -1 is same as infinite timeout
bool resize_events_arr = false;
// Check for valid number of arguments
if (argc != 3)
......@@ -87,41 +89,88 @@ int main(int argc, char **argv) {
/* POLLIN and determine whether it's the listening */
/* or the active connection. */
/*********************************************************/
if(events[i].revents == 0)
if (events[i].revents == 0)
continue;
/*********************************************************/
/* If revents is not POLLIN, it's an unexpected result, */
/* log and end the server. */
/*********************************************************/
if(events[i].revents != POLLIN)
{
if (events[i].revents != POLLIN) {
printf(" Error! revents = %d\n", events[i].revents);
break;
}
if (events[i].fd == listen_socket.GetSocketFd()) {
// we have a new client connection
int new_client_fd;
// Accept client connection
// if we encounter error with this event the go to next event
if (!listen_socket.Accept(&new_client_fd)) {
continue;
}
char client_buffer[BUFFER_SIZE];
int bytes_read = WrappedRead(new_client_fd, (unsigned char*) client_buffer, BUFFER_SIZE);
if (bytes_read > PATH_MAX) {
// file path too large
close(new_client_fd);
continue;
}
// read file path from client and do path validation
string req_file_path(client_buffer, bytes_read);
string base_dir(".");
if (!IsPathSafe(base_dir, req_file_path)) {
close(new_client_fd);
continue;
}
// all good, dispatch thread and setup pollfd
cout << " New incoming connection - " << new_client_fd << "\n";
// setup pipe for worker thread
int pipe_fds[2];
if (pipe2(pipe_fds, O_NONBLOCK) == -1) {
perror(" pipe failed");
close(new_client_fd);
// TODO: clean up;
continue;
}
// add pollfd
events[num_fds].fd = new_client_fd;
events[num_fds].events = POLLIN;
num_fds++;
// dispatch thread
HttpServerTask *worker_task = new HttpServerTask(HttpServer_ThrFn);
tp.Dispatch(worker_task);
} else {
// this is probably a worker thread done with the work
}
}
struct sockaddr_storage caddr;
socklen_t caddr_len = sizeof(caddr);
int client_fd = accept4(listen_fd,
reinterpret_cast<struct sockaddr *>(&caddr),
&caddr_len, O_NONBLOCK);
// check if we successfully accepted a client connection
if (client_fd < 0) {
cerr << "Failure on accept: " << strerror(errno) << endl;
close(listen_fd);
return EXIT_FAILURE;
}
if (resize_events_arr)
{
resize_events_arr = false;
for (int i = 0; i < num_fds; i++)
{
if (events[i].fd == -1)
{
for(int j = i; j < num_fds; j++)
{
events[j].fd = events[j+1].fd;
}
i--;
num_fds--;
}
}
}
// TODO: initialize shared data structure
// TODO: modify logic to add threapool
// TODO: use server_socket class
......@@ -135,32 +184,6 @@ int main(int argc, char **argv) {
*/
unsigned char buf[BUFFER_SIZE];
while (1) {
// TODO: Spawn workers when you see a client connect
// Read file path, clean it up, pass it to worker thread
//
HttpServerTask *hst = new HttpServerTask(HttpServer_ThrFn);
// TODO: change to new fields
hst->base_dir = static_file_dir_path_;
hst->indices = &indices_;
if (!server_socket.Accept(&hst->client_fd,
&hst->c_addr,
&hst->c_port,
&hst->c_dns,
&hst->s_addr,
&hst->s_dns)) {
// The accept failed for some reason, so quit out of the server.
// (Will happen when kill command is used to shut down the server.)
break;
}
//
// The accept succeeded; dispatch it.
tp.Dispatch(hst);
}
// read from client fd and write to stdout
while (1) {
int rlen = WrappedRead(client_fd, buf, BUFFER_SIZE);
......@@ -177,9 +200,6 @@ int main(int argc, char **argv) {
break;
}
}
close(client_fd);
}
return EXIT_SUCCESS;
......
......@@ -120,12 +120,7 @@ bool ServerSocket::BindAndListen() {
return true;
}
bool ServerSocket::Accept(int *accepted_fd,
std::string *client_addr,
uint16_t *client_port,
std::string *client_dnsname,
std::string *server_addr,
std::string *server_dnsname) {
bool ServerSocket::Accept(int *accepted_fd) {
// Accept a new connection on the listening socket listen_sock_fd_.
// (Block until a new connection arrives.) Return the newly accepted
// socket, as well as information about both ends of the new connection,
......@@ -140,82 +135,15 @@ bool ServerSocket::Accept(int *accepted_fd,
reinterpret_cast<struct sockaddr *>(&caddr),
&caddr_len, O_NONBLOCK);
if (client_fd < 0) {
close(listen_sock_fd_);
if (errno != EWOULDBLOCK && errno != EINTR) {
close(listen_sock_fd_);
perror(" accept failed");
exit(EXIT_FAILURE);
}
return false;
}
*accepted_fd = client_fd;
// check if listening socket is IPV4 or IPV6
if (sock_family_ == AF_INET) {
struct sockaddr_in *in4 = reinterpret_cast<struct sockaddr_in *>(&caddr);
char address[INET_ADDRSTRLEN];
// convert the addresss to string
inet_ntop(AF_INET, &(in4->sin_addr), address, INET_ADDRSTRLEN);
// update the client port and addr
*client_port = in4->sin_port;
*client_addr = address;
// get the clientdns and update the return parameter
char clientdns[1024];
if (getnameinfo(reinterpret_cast<struct sockaddr *>(&caddr),
caddr_len, clientdns, 1024, nullptr, 0, 0) == -1)
return false;
*client_dnsname = clientdns;
// get server address, and dnsname.
struct sockaddr_in saddr4;
socklen_t saddr4_len = sizeof(saddr4);
if (getsockname(client_fd,
reinterpret_cast<struct sockaddr *>(&saddr4),
&saddr4_len) == -1)
return false;
// convert server address to string and update return parameter
char saddress[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(saddr4.sin_addr), saddress, INET_ADDRSTRLEN);
*server_addr = saddress;
// get server dns, and update return parameter
char server_dns[1024];
if (getnameinfo(reinterpret_cast<struct sockaddr *>(&saddr4),
saddr4_len, server_dns, 1024, nullptr, 0, 0) == -1)
return false;
*server_dnsname = server_dns;
} else { // sock_family_ == AF_INET6
struct sockaddr_in6 *in6 = reinterpret_cast<struct sockaddr_in6 *>(&caddr);
// update client port return parameter
char address[INET_ADDRSTRLEN];
*client_port = in6->sin6_port;
// convert client address to string, and update return parameter
inet_ntop(AF_INET6, &(in6->sin6_addr), address, INET6_ADDRSTRLEN);
*client_addr = address;
// get client dns name, and update return parameter
char clientdns[1024];
if (getnameinfo(reinterpret_cast<struct sockaddr *>(&caddr),
caddr_len, clientdns, 1024, nullptr, 0, 0) == -1)
return false;
*client_dnsname = clientdns;
// get server address and update return parameter
struct sockaddr_in6 saddr6;
socklen_t saddr6_len = sizeof(saddr6);
if (getsockname(client_fd,
reinterpret_cast<struct sockaddr *>(&saddr6),
&saddr6_len) == -1)
return false;
char saddress[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(saddr6.sin6_addr), saddress, INET6_ADDRSTRLEN);
*server_addr = saddress;
// get server dns and update return parameter
char server_dns[1024];
if (getnameinfo(reinterpret_cast<struct sockaddr *>(&saddr6),
saddr6_len, server_dns, 1024, nullptr, 0, 0) == -1)
return false;
*server_dnsname = server_dns;
}
return true;
}
......
......@@ -65,10 +65,7 @@ class ServerSocket {
//
// - server_dnsname: a C++ string object containing the DNS name
// of the server.
bool Accept(int *accepted_fd,
std::string *client_addr, uint16_t *client_port,
std::string *client_dnsname, std::string *server_addr,
std::string *server_dnsname);
bool Accept(int *accepted_fd);
int GetSocketFd();
......
......@@ -11,7 +11,6 @@
#include <iostream>
#include <cstring>
const int PATH_MAX = 254;
int Listen(char *portnum) {
// Populate the "hints" addrinfo structure for getaddrinfo().
......@@ -95,8 +94,9 @@ int Listen(char *portnum) {
int WrappedRead(int fd, unsigned char *buf, int readlen) {
int read_res;
while (1) {
read_res = read(fd, buf, readlen);
int bytes_read = 0;
while (bytes_read < readlen) {
read_res = read(fd, buf + bytes_read, readlen - bytes_read);
// check for reading errors
if (read_res == -1) {
// check if error is recoverable, if so, try again
......@@ -104,11 +104,12 @@ int WrappedRead(int fd, unsigned char *buf, int readlen) {
continue;
}
// we read readlen bytes, so stop reading
break;
bytes_read += read_res;
}
return read_res;
return bytes_read;
}
int WrappedWrite(int fd, unsigned char *buf, int writelen) {
int total = 0;
int wlen;
......
......@@ -5,6 +5,8 @@
using namespace std;
static const int PATH_MAX = 254;
// accepts a char*/string representation of a portnum
// it returns a listen file descriptor to use
int Listen(char *portnum);
......
......@@ -79,7 +79,7 @@ class HttpServerTask : public ThreadPool::Task {
struct Work {
string filepath;
char buffer[FILE_BUFFER_SIZE]; // Buffer for main thread to read file contents from worker thread
int pipe_fd; // Write end for the pipe
int pipe_fd; // Write end for the pipe. Used to notify main thread that the worker is done writing the file contents.
};
#endif // THREADPOOL_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment