start adding support for sending files
git-svn-id: svn://ttmath.org/publicrep/libscorpiohttpserver/trunk@1063 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
71eb0ef4bf
commit
80b53a7fd5
|
@ -1,34 +1,33 @@
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Client::Client()
|
Client::Client()
|
||||||
{
|
{
|
||||||
in_buffer_max_len = WEBSERVER_INPUT_BUFFER_MAX_LEN;
|
socket = 0;
|
||||||
socket = 0;
|
close_connection = false;
|
||||||
in_buffer = nullptr;
|
PrepareToNewRequest();
|
||||||
in_buffer_len = 0;
|
read_static_buffer_size = 1500 * 3; // this will be testing (size of one packet * how many packets)
|
||||||
parsing_headers = true;
|
read_static_buffer = new char[read_static_buffer_size]; // add to config
|
||||||
parsing_first_header = true;
|
std::cout << "alokuje buforek: " << (void*)read_static_buffer << std::endl;
|
||||||
http_method = http_method_unsupported;
|
|
||||||
http_version = http_version_unsupported;
|
// check whether there is no too much copying when we add Client to a list
|
||||||
answer_generated = false;
|
|
||||||
output_buffer_sent = 0;
|
|
||||||
close_connection = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Client::Client(const Client & c)
|
Client::Client(const Client & c)
|
||||||
{
|
{
|
||||||
in_buffer = nullptr;
|
|
||||||
operator=(c);
|
operator=(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
delete [] in_buffer;
|
std::cout << "usuwam buforek: " << (void*)read_static_buffer << std::endl;
|
||||||
|
delete [] read_static_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,13 +35,6 @@ Client & Client::operator=(const Client & c)
|
||||||
{
|
{
|
||||||
socket = c.socket;
|
socket = c.socket;
|
||||||
|
|
||||||
if( c.in_buffer )
|
|
||||||
AllocInputBuffer();
|
|
||||||
else
|
|
||||||
in_buffer = nullptr;
|
|
||||||
|
|
||||||
in_buffer_len = c.in_buffer_len;
|
|
||||||
in_buffer_max_len = c.in_buffer_max_len;
|
|
||||||
parsing_headers = c.parsing_headers;
|
parsing_headers = c.parsing_headers;
|
||||||
parsing_first_header = c.parsing_first_header;
|
parsing_first_header = c.parsing_first_header;
|
||||||
http_method_str = c.http_method_str;
|
http_method_str = c.http_method_str;
|
||||||
|
@ -54,6 +46,35 @@ Client & Client::operator=(const Client & c)
|
||||||
output_buffer = c.output_buffer;
|
output_buffer = c.output_buffer;
|
||||||
output_buffer_sent = c.output_buffer_sent;
|
output_buffer_sent = c.output_buffer_sent;
|
||||||
close_connection = c.close_connection;
|
close_connection = c.close_connection;
|
||||||
|
output_buffer_two = c.output_buffer_two;
|
||||||
|
//is_sending_file = c.is_sending_file;
|
||||||
|
// external_resource_fd = c.external_resource_fd;
|
||||||
|
// waiting_for_last_read = c.waiting_for_last_read;
|
||||||
|
// send_file = c.send_file;
|
||||||
|
// file_how_many_read = c.file_how_many_read;
|
||||||
|
//file_has_been_read = c.file_has_been_read;
|
||||||
|
// file_len = c.file_len;
|
||||||
|
//file_how_many_send = c.file_how_many_send;
|
||||||
|
|
||||||
|
output_buffer_two_sent = c.output_buffer_two_sent;
|
||||||
|
|
||||||
|
external_resource = c.external_resource;
|
||||||
|
|
||||||
|
reading_to_buffer = c.reading_to_buffer;
|
||||||
|
sending_from_buffer = c.sending_from_buffer;
|
||||||
|
|
||||||
|
reading_to_buffer_two = c.reading_to_buffer_two;
|
||||||
|
sending_from_buffer_two = c.sending_from_buffer_two;
|
||||||
|
|
||||||
|
answering_to_client = c.answering_to_client;
|
||||||
|
|
||||||
|
// reading_external_resource = c.reading_external_resource;
|
||||||
|
|
||||||
|
read_static_buffer_size = c.read_static_buffer_size;
|
||||||
|
read_static_buffer = new char[read_static_buffer_size];
|
||||||
|
std::cout << "alokuje buforek: " << (void*)read_static_buffer << std::endl;
|
||||||
|
|
||||||
|
memcpy(read_static_buffer, c.read_static_buffer, read_static_buffer_size);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -61,29 +82,44 @@ Client & Client::operator=(const Client & c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Client::AllocInputBuffer()
|
|
||||||
{
|
|
||||||
delete [] in_buffer;
|
|
||||||
in_buffer = new char[in_buffer_max_len];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Client::PrepareToNewRequest()
|
void Client::PrepareToNewRequest()
|
||||||
{
|
{
|
||||||
if( !in_buffer )
|
|
||||||
AllocInputBuffer();
|
|
||||||
|
|
||||||
parsing_headers = true;
|
parsing_headers = true;
|
||||||
parsing_first_header = true;
|
parsing_first_header = true;
|
||||||
in_buffer_len = 0;
|
|
||||||
http_method = http_method_unsupported;
|
http_method = http_method_unsupported;
|
||||||
http_version = http_version_unsupported;
|
http_version = http_version_unsupported;
|
||||||
answer_generated = false;
|
answer_generated = false;
|
||||||
output_buffer_sent = 0;
|
output_buffer_sent = 0;
|
||||||
|
//is_sending_file = false;
|
||||||
|
//external_resource_fd = -1;
|
||||||
|
//waiting_for_last_read = false;
|
||||||
|
//file_how_many_read = 0;
|
||||||
|
//file_has_been_read = false;
|
||||||
|
|
||||||
|
output_buffer_two_sent = 0;
|
||||||
|
//file_len = 0;
|
||||||
|
//file_how_many_send = 0;
|
||||||
|
|
||||||
|
reading_to_buffer_two = false;
|
||||||
|
sending_from_buffer_two = false;
|
||||||
|
|
||||||
|
reading_to_buffer = 0;
|
||||||
|
sending_from_buffer = 0;
|
||||||
|
|
||||||
|
answering_to_client = false;
|
||||||
|
//reading_external_resource = false;
|
||||||
|
|
||||||
http_method_str.clear();
|
http_method_str.clear();
|
||||||
output_buffer.clear();
|
output_buffer.clear();
|
||||||
|
output_buffer_two.clear();
|
||||||
url.clear();
|
url.clear();
|
||||||
|
send_file.clear();
|
||||||
|
|
||||||
|
external_resource.Clear();
|
||||||
|
|
||||||
|
memset(&iocb, 0, sizeof(iocb));
|
||||||
|
|
||||||
// don't set flag close_connection to false here
|
// don't set flag close_connection to false here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
85
src/client.h
85
src/client.h
|
@ -2,6 +2,7 @@
|
||||||
#define headerfile_libscorpiohttpserver_src_client_h
|
#define headerfile_libscorpiohttpserver_src_client_h
|
||||||
|
|
||||||
|
|
||||||
|
#include <aio.h>
|
||||||
#include <space/space.h>
|
#include <space/space.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,12 +29,55 @@ enum HTTPVersion
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ExternalResource
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
type_file,
|
||||||
|
type_none,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ExternalResource()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
type = type_none;
|
||||||
|
reading_external_resource = false;
|
||||||
|
external_resource_fd = -1;
|
||||||
|
file_len = 0;
|
||||||
|
waiting_for_last_read = false;
|
||||||
|
file_how_many_read = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reading an external resource such as a file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool reading_external_resource;
|
||||||
|
|
||||||
|
int external_resource_fd;
|
||||||
|
|
||||||
|
size_t file_len;
|
||||||
|
bool waiting_for_last_read;
|
||||||
|
size_t file_how_many_read;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int socket;
|
int socket;
|
||||||
PT::Space in;
|
PT::Space in;
|
||||||
|
|
||||||
|
@ -52,9 +96,39 @@ public:
|
||||||
bool parsing_first_header;
|
bool parsing_first_header;
|
||||||
|
|
||||||
|
|
||||||
std::string output_buffer;
|
|
||||||
size_t output_buffer_sent; // how many characters were sent
|
|
||||||
|
|
||||||
|
std::wstring send_file;
|
||||||
|
|
||||||
|
//size_t how_many_to_send;
|
||||||
|
|
||||||
|
|
||||||
|
ExternalResource external_resource;
|
||||||
|
|
||||||
|
std::string output_buffer;
|
||||||
|
std::string output_buffer_two;
|
||||||
|
|
||||||
|
size_t output_buffer_sent; // how many characters were sent
|
||||||
|
size_t output_buffer_two_sent; // how many characters were sent
|
||||||
|
|
||||||
|
int reading_to_buffer;
|
||||||
|
int sending_from_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
bool reading_to_buffer_two;
|
||||||
|
bool sending_from_buffer_two;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if true then all headers has been read and now the server
|
||||||
|
* is creating the response
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool answering_to_client;
|
||||||
|
|
||||||
|
char * read_static_buffer;
|
||||||
|
size_t read_static_buffer_size;
|
||||||
|
|
||||||
|
|
||||||
|
aiocb iocb;
|
||||||
|
|
||||||
Client();
|
Client();
|
||||||
Client(const Client & c);
|
Client(const Client & c);
|
||||||
|
@ -62,15 +136,14 @@ public:
|
||||||
|
|
||||||
Client & operator=(const Client & c);
|
Client & operator=(const Client & c);
|
||||||
|
|
||||||
void AllocInputBuffer();
|
|
||||||
void PrepareToNewRequest();
|
void PrepareToNewRequest();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
char * in_buffer; // rename to a better name
|
//char * in_buffer; // rename to a better name
|
||||||
size_t in_buffer_max_len; // at least two characters
|
//size_t in_buffer_max_len; // at least two characters
|
||||||
size_t in_buffer_len;
|
//size_t in_buffer_len;
|
||||||
std::wstring http_method_str;
|
std::wstring http_method_str;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,9 @@ void HeadersParser::ParseHeaders(Client & client)
|
||||||
|
|
||||||
if( tmp_header.size() > 0 )
|
if( tmp_header.size() > 0 )
|
||||||
{
|
{
|
||||||
std::wcout << L"header parsed: ";
|
//std::wcout << L"header parsed: ";
|
||||||
std::wcout << L"\"" << tmp_header << L"\"=\"";
|
//std::wcout << L"\"" << tmp_header << L"\"=\"";
|
||||||
std::wcout << tmp_value << L"\"" << std::endl;
|
//std::wcout << tmp_value << L"\"" << std::endl;
|
||||||
client.in.Add(tmp_header, tmp_value);
|
client.in.Add(tmp_header, tmp_value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,8 +40,8 @@ int main()
|
||||||
|
|
||||||
signal(SIGPIPE, signal_handler_sigpipe);
|
signal(SIGPIPE, signal_handler_sigpipe);
|
||||||
|
|
||||||
|
server.Prepare();
|
||||||
|
|
||||||
server.PrepareMainSocket();
|
|
||||||
server.Wait();
|
server.Wait();
|
||||||
|
|
||||||
|
|
||||||
|
|
620
src/server.cpp
620
src/server.cpp
|
@ -7,6 +7,8 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <utf8/utf8.h>
|
#include <utf8/utf8.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "string_functions.h"
|
#include "string_functions.h"
|
||||||
|
|
||||||
|
@ -16,8 +18,13 @@ Server::Server()
|
||||||
{
|
{
|
||||||
main_socket = -1;
|
main_socket = -1;
|
||||||
close_server = false;
|
close_server = false;
|
||||||
|
in_buffer_max_len = 2048;
|
||||||
|
in_buffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
|
@ -36,8 +43,13 @@ void Server::CloseMainSocket()
|
||||||
|
|
||||||
void Server::CloseClientSockets()
|
void Server::CloseClientSockets()
|
||||||
{
|
{
|
||||||
for(size_t i=0 ; i<client_tab.size() ; ++i)
|
for(auto i=client_tab.begin() ; i != client_tab.end() ; ++i)
|
||||||
close(client_tab[i].socket);
|
{
|
||||||
|
close(i->socket);
|
||||||
|
|
||||||
|
if( i->external_resource.external_resource_fd >= 0 )
|
||||||
|
close(i->external_resource.external_resource_fd);
|
||||||
|
}
|
||||||
|
|
||||||
client_tab.clear();
|
client_tab.clear();
|
||||||
}
|
}
|
||||||
|
@ -50,9 +62,21 @@ void Server::Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Server::AllocInputBuffer()
|
||||||
|
{
|
||||||
|
delete [] in_buffer;
|
||||||
|
in_buffer = new char[in_buffer_max_len];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Server::Prepare()
|
||||||
|
{
|
||||||
|
PrepareMainSocket();
|
||||||
|
AllocInputBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Server::PrepareMainSocket()
|
void Server::PrepareMainSocket()
|
||||||
{
|
{
|
||||||
|
@ -106,14 +130,16 @@ void Server::Wait()
|
||||||
{
|
{
|
||||||
while( !close_server )
|
while( !close_server )
|
||||||
{
|
{
|
||||||
int fd_max = AddSocketsToSet();
|
timeval t;
|
||||||
int ready_fd = select(fd_max + 1, &read_set, &write_set, 0, 0);
|
int fd_max;
|
||||||
|
int how_many_external_resources;
|
||||||
|
|
||||||
if( ready_fd < 0 )
|
PrepareSocketsForSelect(fd_max, t, how_many_external_resources);
|
||||||
{
|
// sprawdzic czy jak t jest zerem to select czeka nieskonczenie dlugo czy od razu przerywa
|
||||||
std::cout << "select failed" << std::endl;
|
int ready_fd = select(fd_max + 1, &read_set, &write_set, 0, &t);
|
||||||
return;
|
|
||||||
}
|
if( how_many_external_resources > 0 )
|
||||||
|
ReadExternalResource(how_many_external_resources);
|
||||||
|
|
||||||
if( ready_fd > 0 )
|
if( ready_fd > 0 )
|
||||||
{
|
{
|
||||||
|
@ -131,27 +157,44 @@ void Server::Wait()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int Server::AddSocketsToSet()
|
void Server::PrepareSocketsForSelect(int & fd_max, timeval & t, int & how_many_external_resources)
|
||||||
{
|
{
|
||||||
FD_ZERO(&read_set);
|
FD_ZERO(&read_set);
|
||||||
FD_ZERO(&write_set);
|
FD_ZERO(&write_set);
|
||||||
|
|
||||||
int fd_max = 0;
|
fd_max = 0;
|
||||||
|
t.tv_sec = 0;
|
||||||
|
t.tv_usec = 0;
|
||||||
|
how_many_external_resources = 0;
|
||||||
|
|
||||||
if( main_socket >= 0 )
|
if( main_socket >= 0 )
|
||||||
{
|
{
|
||||||
FD_SET(main_socket, &read_set);
|
FD_SET(main_socket, &read_set);
|
||||||
fd_max = main_socket;
|
fd_max = main_socket;
|
||||||
|
|
||||||
for(size_t i=0 ; i<client_tab.size() ; ++i)
|
for(auto i=client_tab.begin() ; i != client_tab.end() ; ++i)
|
||||||
{
|
{
|
||||||
FD_SET(client_tab[i].socket, &read_set);
|
if( !i->answering_to_client )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* do not read the next request until the answer is sent
|
||||||
|
* (client can use pipelining)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
FD_SET(i->socket, &read_set);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FD_SET(i->socket, &write_set);
|
||||||
|
}
|
||||||
|
|
||||||
if( client_tab[i].answer_generated && !client_tab[i].output_buffer.empty() )
|
if( i->socket > fd_max )
|
||||||
FD_SET(client_tab[i].socket, &write_set);
|
fd_max = i->socket;
|
||||||
|
|
||||||
if( client_tab[i].socket > fd_max )
|
if( i->external_resource.reading_external_resource )
|
||||||
fd_max = client_tab[i].socket;
|
{
|
||||||
|
how_many_external_resources += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -159,7 +202,8 @@ int Server::AddSocketsToSet()
|
||||||
std::cout << "there is no main socket" << std::endl;
|
std::cout << "there is no main socket" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd_max;
|
if( how_many_external_resources > 0 )
|
||||||
|
t.tv_usec = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,9 +238,9 @@ int client_socket;
|
||||||
|
|
||||||
c.socket = client_socket;
|
c.socket = client_socket;
|
||||||
c.close_connection = false;
|
c.close_connection = false;
|
||||||
|
c.PrepareToNewRequest();
|
||||||
|
|
||||||
client_tab.push_back(c);
|
client_tab.push_back(c);
|
||||||
client_tab.back().PrepareToNewRequest();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -209,30 +253,179 @@ int client_socket;
|
||||||
|
|
||||||
void Server::ReadWriteToClients()
|
void Server::ReadWriteToClients()
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
for(auto i=client_tab.begin() ; i != client_tab.end() ; )
|
||||||
|
|
||||||
while( i < client_tab.size() )
|
|
||||||
{
|
{
|
||||||
if( FD_ISSET(client_tab[i].socket, &read_set))
|
if( FD_ISSET(i->socket, &read_set))
|
||||||
{
|
{
|
||||||
ReadInputFromClient(client_tab[i]);
|
ReadInputFromClient(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( client_tab[i].answer_generated && FD_ISSET(client_tab[i].socket, &write_set) )
|
if( FD_ISSET(i->socket, &write_set) )
|
||||||
{
|
{
|
||||||
WriteOutputToClient(client_tab[i]);
|
WriteOutputToClient(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( client_tab[i].output_buffer.empty() && client_tab[i].close_connection )
|
if( !i->answering_to_client && i->close_connection && (!i->external_resource.reading_external_resource || !i->external_resource.waiting_for_last_read) )
|
||||||
{
|
{
|
||||||
std::cout << "closing connection for client nr " << client_tab[i].socket << std::endl;
|
std::cout << "closing connection for client nr " << i->socket << std::endl;
|
||||||
|
|
||||||
close(client_tab[i].socket);
|
close(i->socket);
|
||||||
client_tab.erase(client_tab.begin() + i);
|
|
||||||
|
if( i->external_resource.external_resource_fd >= 0 )
|
||||||
|
close(i->external_resource.external_resource_fd);
|
||||||
|
|
||||||
|
auto next_i = i;
|
||||||
|
++next_i;
|
||||||
|
client_tab.erase(i);
|
||||||
|
i = next_i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i += 1;
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Server::ReadExternalResource(int how_many_external_resources)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for(auto i=client_tab.begin() ; i != client_tab.end() && count < how_many_external_resources ; ++i)
|
||||||
|
{
|
||||||
|
if( i->external_resource.reading_external_resource )
|
||||||
|
{
|
||||||
|
if( i->reading_to_buffer == 1 )
|
||||||
|
{
|
||||||
|
ReadExternalResource(*i, i->output_buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( i->reading_to_buffer == 2 )
|
||||||
|
{
|
||||||
|
ReadExternalResource(*i, i->output_buffer_two);
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Server::ReadExternalResource(Client & client, std::string & output_buffer)
|
||||||
|
{
|
||||||
|
if( !client.external_resource.waiting_for_last_read )
|
||||||
|
{
|
||||||
|
client.iocb.aio_fildes = client.external_resource.external_resource_fd;
|
||||||
|
client.iocb.aio_offset = client.external_resource.file_how_many_read;
|
||||||
|
client.iocb.aio_buf = (volatile void*)client.read_static_buffer;
|
||||||
|
|
||||||
|
client.iocb.aio_nbytes = client.read_static_buffer_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* at the beginning we have some headers in the first output buffer
|
||||||
|
*
|
||||||
|
* zmniejszamy ilosc bajtow do odczytania tak aby cala dlugosc bufora byla podzielna przez ilosc pakietow do wyslania
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if( output_buffer.size() < client.iocb.aio_nbytes )
|
||||||
|
client.iocb.aio_nbytes -= output_buffer.size();
|
||||||
|
|
||||||
|
int res = aio_read(&client.iocb);
|
||||||
|
|
||||||
|
if( res < 0 )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
std::cout << "aio_read has problems: errno: " << err << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client.external_resource.waiting_for_last_read = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int res = aio_error(&client.iocb);
|
||||||
|
|
||||||
|
std::cout << "aio_error returned: " << res << std::endl;
|
||||||
|
|
||||||
|
if( res == EINPROGRESS )
|
||||||
|
{
|
||||||
|
std::cout << "res is equal EINPROGRESS" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( res == 0 )
|
||||||
|
{
|
||||||
|
std::cout << "reading completed" << std::endl;
|
||||||
|
|
||||||
|
res = aio_return(&client.iocb);
|
||||||
|
|
||||||
|
if( res < 0 )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
std::cout << "aio_return returned error, errno: " << err << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( res == 0 )
|
||||||
|
{
|
||||||
|
std::cout << "koniec czytania pliku" << std::endl;
|
||||||
|
|
||||||
|
if( client.sending_from_buffer == 0 )
|
||||||
|
client.sending_from_buffer = client.reading_to_buffer;
|
||||||
|
|
||||||
|
client.reading_to_buffer = 0;
|
||||||
|
client.external_resource.reading_external_resource = false;
|
||||||
|
close(client.external_resource.external_resource_fd);
|
||||||
|
client.external_resource.external_resource_fd = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "przeczytano bajtow: " << res << std::endl;
|
||||||
|
|
||||||
|
output_buffer.append(client.read_static_buffer, res);
|
||||||
|
client.external_resource.file_how_many_read += (size_t)res;
|
||||||
|
|
||||||
|
if( output_buffer.size() > 1500 ) // add to config
|
||||||
|
{
|
||||||
|
if( client.reading_to_buffer == 1 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 0;
|
||||||
|
|
||||||
|
if( client.sending_from_buffer != 2 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( client.sending_from_buffer == 0 )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( client.reading_to_buffer == 2 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 0;
|
||||||
|
|
||||||
|
if( client.sending_from_buffer != 1 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( client.sending_from_buffer == 0 )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.external_resource.waiting_for_last_read = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "some error" << std::endl;
|
||||||
|
// what about this buffer?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,24 +434,9 @@ void Server::ReadWriteToClients()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Server::ReadInputFromClient(Client & client)
|
void Server::ReadInputFromClient(Client & client)
|
||||||
{
|
{
|
||||||
std::cout << "trying read something from client number: " << client.socket << std::endl;
|
int read_len = read(client.socket, in_buffer, in_buffer_max_len);
|
||||||
|
|
||||||
// we need at least one char more (for terminating zero for logging/debugging)
|
|
||||||
|
|
||||||
if( client.in_buffer_max_len - client.in_buffer_len < 2 )
|
|
||||||
{
|
|
||||||
client.input_buffer.append(client.in_buffer, client.in_buffer_len);
|
|
||||||
client.in_buffer_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char * old_pointer = client.in_buffer + client.in_buffer_len;
|
|
||||||
|
|
||||||
// after adding to client.input_buffer we set in_buffer_len to 0
|
|
||||||
// so here is sufficient client.in_buffer (without adding client.in_buffer_len)
|
|
||||||
int read_len = read(client.socket, client.in_buffer + client.in_buffer_len, client.in_buffer_max_len - client.in_buffer_len - 1);
|
|
||||||
|
|
||||||
if( read_len < 0 )
|
if( read_len < 0 )
|
||||||
{
|
{
|
||||||
|
@ -270,51 +448,26 @@ void Server::ReadInputFromClient(Client & client)
|
||||||
else
|
else
|
||||||
if( read_len == 0 )
|
if( read_len == 0 )
|
||||||
{
|
{
|
||||||
// end
|
|
||||||
|
|
||||||
if( client.in_buffer_len > 0 )
|
|
||||||
{
|
|
||||||
client.input_buffer.append(client.in_buffer, client.in_buffer_len);
|
|
||||||
client.in_buffer_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "------------------------------ client: " << client.socket << " calosc komunikatu " << std::endl;
|
|
||||||
std::cout << client.input_buffer;
|
|
||||||
std::cout << "----------------------------------------" << std::endl;
|
|
||||||
|
|
||||||
// the client has terminated connection
|
// the client has terminated connection
|
||||||
client.close_connection = true;
|
client.close_connection = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
client.in_buffer_len += read_len;
|
|
||||||
|
|
||||||
size_t input_buffer_index = client.input_buffer.size();
|
size_t input_buffer_index = client.input_buffer.size();
|
||||||
|
|
||||||
client.input_buffer.append(client.in_buffer, client.in_buffer_len);
|
client.input_buffer.append(in_buffer, read_len);
|
||||||
client.in_buffer_len = 0;
|
|
||||||
|
|
||||||
if( client.parsing_headers )
|
if( client.parsing_headers )
|
||||||
CheckHeaders(client, input_buffer_index);
|
CheckHeaders(client, input_buffer_index);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
client.in_buffer[client.in_buffer_len] = 0; // only for logging (we have at least one character more for terminating zero)
|
|
||||||
|
|
||||||
std::cout << "------------------------------ client: " << client.socket << std::endl;
|
|
||||||
std::cout << old_pointer;
|
|
||||||
std::cout << "----------------------------------------" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Server::WriteOutputToClient(Client & client)
|
void Server::WriteOutputToClient(Client & client, std::string & output_buffer, size_t & output_buffer_sent)
|
||||||
{
|
{
|
||||||
std::cout << "writing to client nr " << client.socket << std::endl;
|
const char * data = output_buffer.c_str() + output_buffer_sent;
|
||||||
|
size_t how_many_to_send = output_buffer.size() - output_buffer_sent;
|
||||||
const char * data = client.output_buffer.c_str() + client.output_buffer_sent;
|
|
||||||
size_t how_many_to_send = client.output_buffer.size() - client.output_buffer_sent;
|
|
||||||
|
|
||||||
if( how_many_to_send > 0 )
|
if( how_many_to_send > 0 )
|
||||||
{
|
{
|
||||||
|
@ -326,11 +479,43 @@ void Server::WriteOutputToClient(Client & client)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
client.output_buffer_sent += len;
|
output_buffer_sent += len;
|
||||||
|
|
||||||
if( client.output_buffer_sent == client.output_buffer.size() )
|
if( output_buffer_sent >= output_buffer.size() )
|
||||||
{
|
{
|
||||||
client.PrepareToNewRequest();
|
output_buffer.clear();
|
||||||
|
output_buffer_sent = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if( client.sending_from_buffer == 1 )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 0;
|
||||||
|
|
||||||
|
if( client.reading_to_buffer != 2 && !client.output_buffer_two.empty() )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( client.sending_from_buffer == 2 )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 0;
|
||||||
|
|
||||||
|
if( client.reading_to_buffer != 1 && !client.output_buffer.empty() )
|
||||||
|
{
|
||||||
|
client.sending_from_buffer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,10 +523,31 @@ void Server::WriteOutputToClient(Client & client)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Server::WriteOutputToClient(Client & client)
|
||||||
|
{
|
||||||
|
if( client.sending_from_buffer == 1 )
|
||||||
|
{
|
||||||
|
WriteOutputToClient(client, client.output_buffer, client.output_buffer_sent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( client.sending_from_buffer == 2 )
|
||||||
|
{
|
||||||
|
WriteOutputToClient(client, client.output_buffer_two, client.output_buffer_two_sent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( !client.external_resource.reading_external_resource && client.output_buffer.empty() && client.output_buffer_two.empty() )
|
||||||
|
{
|
||||||
|
client.PrepareToNewRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Server::CheckHeaders(Client & client, size_t input_buffer_index)
|
void Server::CheckHeaders(Client & client, size_t input_buffer_index)
|
||||||
{
|
{
|
||||||
// at least 3 bytes before
|
// we check at least 3 bytes before because we are looking for \r\n\r\n
|
||||||
|
// and the input_buffer_index can point at the last \n now
|
||||||
|
|
||||||
if( input_buffer_index > 3 )
|
if( input_buffer_index > 3 )
|
||||||
input_buffer_index -= 3;
|
input_buffer_index -= 3;
|
||||||
|
@ -352,50 +558,59 @@ void Server::CheckHeaders(Client & client, size_t input_buffer_index)
|
||||||
{
|
{
|
||||||
if( headers_parser.IsHeadersEnding(client.input_buffer.c_str() + input_buffer_index) )
|
if( headers_parser.IsHeadersEnding(client.input_buffer.c_str() + input_buffer_index) )
|
||||||
{
|
{
|
||||||
headers_parser.ParseHeaders(client);
|
ParseHeaders(client);
|
||||||
|
|
||||||
if( !SelectMethodName(client, client.http_method_str) )
|
|
||||||
{
|
|
||||||
std::cout << "unsupported http method" << std::endl;
|
|
||||||
client.close_connection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.parsing_headers = false;
|
|
||||||
client.input_buffer.erase(0, input_buffer_index + 4);
|
client.input_buffer.erase(0, input_buffer_index + 4);
|
||||||
|
|
||||||
|
|
||||||
// temporarily we are using only get method with http 1.0 (closing connection after answering)
|
|
||||||
if( client.http_method == http_method_get )
|
|
||||||
{
|
|
||||||
CreateAnswer(client);
|
|
||||||
client.answer_generated = true;
|
|
||||||
|
|
||||||
if( client.http_version == http_version_1_0 )
|
|
||||||
{
|
|
||||||
if( !CompareNoCase(client.in.Text(L"connection"), L"keep-alive") )
|
|
||||||
{
|
|
||||||
std::cout << "answer generated, closing connection for http 1.0" << std::endl;
|
|
||||||
client.close_connection = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "keep-alive is set, not closing connection for http 1.0" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( client.http_method != http_method_get )
|
|
||||||
{
|
|
||||||
// at the moment only get method
|
|
||||||
client.close_connection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Server::ParseHeaders(Client & client)
|
||||||
|
{
|
||||||
|
headers_parser.ParseHeaders(client);
|
||||||
|
|
||||||
|
if( !SelectMethodName(client, client.http_method_str) )
|
||||||
|
{
|
||||||
|
std::cout << "unsupported http method" << std::endl;
|
||||||
|
client.close_connection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.parsing_headers = false;
|
||||||
|
|
||||||
|
// temporarily we are using only get method with http 1.0 (closing connection after answering)
|
||||||
|
if( client.http_method == http_method_get )
|
||||||
|
{
|
||||||
|
CreateAnswer(client);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* we cannot close the connection here (a file can be send)
|
||||||
|
*
|
||||||
|
if( client.http_version == http_version_1_0 )
|
||||||
|
{
|
||||||
|
if( !CompareNoCase(client.in.Text(L"connection"), L"keep-alive") )
|
||||||
|
{
|
||||||
|
//std::cout << "answer generated, closing connection for http 1.0" << std::endl;
|
||||||
|
client.close_connection = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::cout << "keep-alive is set, not closing connection for http 1.0" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if( client.http_method != http_method_get )
|
||||||
|
{
|
||||||
|
// at the moment only get method
|
||||||
|
client.close_connection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,6 +652,8 @@ bool Server::SelectMethodName(Client & client, const std::wstring & method_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//void Server::RemoveClientSocket(int client_socket)
|
//void Server::RemoveClientSocket(int client_socket)
|
||||||
//{
|
//{
|
||||||
// for(size_t i=0 ; i<client_tab.size() ; ++i)
|
// for(size_t i=0 ; i<client_tab.size() ; ++i)
|
||||||
|
@ -456,51 +673,142 @@ bool Server::SelectMethodName(Client & client, const std::wstring & method_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Server::CreateAnswer(Client & client)
|
|
||||||
|
int Server::FileLen(std::string & file_name, size_t & file_len)
|
||||||
{
|
{
|
||||||
std::wstring a, c;
|
struct stat s;
|
||||||
|
|
||||||
c = L"hello world from my webserver, your requested: " + client.url;
|
file_len = 0;
|
||||||
c += L"\r\n";
|
|
||||||
|
|
||||||
if( client.url == L"/quit" )
|
int res = stat(file_name.c_str(), &s);
|
||||||
|
|
||||||
|
if( res == 0 )
|
||||||
{
|
{
|
||||||
c += L"<br><br>bye bye";
|
file_len = s.st_size;
|
||||||
close_server = true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Server::CreateAnswer(Client & client)
|
||||||
|
{
|
||||||
|
// tmp, a user method will be called
|
||||||
|
|
||||||
|
std::wstring a, c;
|
||||||
|
std::string c_ascii;
|
||||||
|
|
||||||
|
if( client.url == L"/swinka.jpg" )
|
||||||
|
{
|
||||||
|
std::string file_name_ascii;
|
||||||
|
|
||||||
|
client.send_file = L"/home/tomek/pani.jpg";
|
||||||
|
PT::WideToUTF8(client.send_file, file_name_ascii);
|
||||||
|
|
||||||
|
if( FileLen(file_name_ascii, client.external_resource.file_len) )
|
||||||
|
{
|
||||||
|
a = L"HTTP/";
|
||||||
|
|
||||||
|
if( client.http_version == http_version_1_0 )
|
||||||
|
a += L"1.0";
|
||||||
|
else
|
||||||
|
a += L"1.1";
|
||||||
|
|
||||||
|
a += L" 200 OK\r\n";
|
||||||
|
a += L"Content-Type: image/jpeg;\r\n";
|
||||||
|
|
||||||
|
if( CompareNoCase(client.in.Text(L"connection"), L"keep-alive") )
|
||||||
|
{
|
||||||
|
a += L"Connection: keep-alive\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t buf[32];
|
||||||
|
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", client.external_resource.file_len);
|
||||||
|
|
||||||
|
a += L"Content-Length: ";
|
||||||
|
a += buf;
|
||||||
|
a += L"\r\n";
|
||||||
|
a += L"\r\n";
|
||||||
|
|
||||||
|
PT::WideToUTF8(a, client.output_buffer);
|
||||||
|
|
||||||
|
if( client.external_resource.external_resource_fd != -1 )
|
||||||
|
close(client.external_resource.external_resource_fd);
|
||||||
|
|
||||||
|
// improve me (utf8)
|
||||||
|
client.external_resource.external_resource_fd = open(file_name_ascii.c_str(), O_RDONLY | O_NONBLOCK);
|
||||||
|
|
||||||
|
if( client.external_resource.external_resource_fd >= 0 )
|
||||||
|
{
|
||||||
|
client.reading_to_buffer = 1;
|
||||||
|
client.sending_from_buffer = 0;
|
||||||
|
client.answering_to_client = true;
|
||||||
|
|
||||||
|
client.external_resource.reading_external_resource = true;
|
||||||
|
client.external_resource.type = ExternalResource::type_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// return an error page?
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = L"hello world from my webserver, your requested: " + client.url;
|
||||||
|
c += L"\r\n";
|
||||||
|
|
||||||
|
if( client.url == L"/quit" )
|
||||||
|
{
|
||||||
|
c += L"<br><br>bye bye";
|
||||||
|
close_server = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PT::WideToUTF8(c,c_ascii);
|
||||||
|
|
||||||
|
|
||||||
|
a = L"HTTP/";
|
||||||
|
|
||||||
|
if( client.http_version == http_version_1_0 )
|
||||||
|
a += L"1.0";
|
||||||
|
else
|
||||||
|
a += L"1.1";
|
||||||
|
|
||||||
|
a += L" 200 OK\r\n";
|
||||||
|
a += L"Content-Type: text/html; charset=UTF-8\r\n";
|
||||||
|
|
||||||
|
|
||||||
|
if( CompareNoCase(client.in.Text(L"connection"), L"keep-alive") )
|
||||||
|
{
|
||||||
|
a += L"Connection: keep-alive\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t buf[32];
|
||||||
|
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", c_ascii.size());
|
||||||
|
|
||||||
|
a += L"Content-Length: ";
|
||||||
|
a += buf;
|
||||||
|
a += L"\r\n";
|
||||||
|
a += L"\r\n";
|
||||||
|
|
||||||
|
|
||||||
|
PT::WideToUTF8(a, client.output_buffer);
|
||||||
|
client.output_buffer += c_ascii;
|
||||||
|
|
||||||
|
client.reading_to_buffer = 0;
|
||||||
|
client.sending_from_buffer = 1;
|
||||||
|
client.answering_to_client = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string c_ascii;
|
|
||||||
PT::WideToUTF8(c,c_ascii);
|
|
||||||
|
|
||||||
|
|
||||||
a = L"HTTP/";
|
|
||||||
|
|
||||||
if( client.http_version == http_version_1_0 )
|
|
||||||
a += L"1.0";
|
|
||||||
else
|
|
||||||
a += L"1.1";
|
|
||||||
|
|
||||||
a += L" 200 OK\r\n";
|
|
||||||
a += L"Content-Type: text/html; charset=UTF-8\r\n";
|
|
||||||
|
|
||||||
|
|
||||||
if( CompareNoCase(client.in.Text(L"connection"), L"keep-alive") )
|
|
||||||
{
|
|
||||||
a += L"Connection: keep-alive\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wchar_t buf[32];
|
|
||||||
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", c_ascii.size());
|
|
||||||
|
|
||||||
a += L"Content-Length: ";
|
|
||||||
a += buf;
|
|
||||||
a += L"\r\n";
|
|
||||||
a += L"\r\n";
|
|
||||||
|
|
||||||
|
|
||||||
PT::WideToUTF8(a, client.output_buffer);
|
|
||||||
client.output_buffer += c_ascii;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
53
src/server.h
53
src/server.h
|
@ -1,7 +1,7 @@
|
||||||
#ifndef headerfile_libscorpiohttpserver_src_server_h
|
#ifndef headerfile_libscorpiohttpserver_src_server_h
|
||||||
#define headerfile_libscorpiohttpserver_src_server_h
|
#define headerfile_libscorpiohttpserver_src_server_h
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "headers_parser.h"
|
#include "headers_parser.h"
|
||||||
|
@ -14,6 +14,10 @@ public:
|
||||||
|
|
||||||
|
|
||||||
Server();
|
Server();
|
||||||
|
|
||||||
|
Server(const Server & s) = delete;
|
||||||
|
Server & operator=(const Server & s) = delete;
|
||||||
|
|
||||||
virtual ~Server();
|
virtual ~Server();
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,38 +25,52 @@ public:
|
||||||
void CloseClientSockets();
|
void CloseClientSockets();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
void PrepareMainSocket();
|
void Prepare();
|
||||||
void Wait();
|
void Wait();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<Client> client_tab;
|
// we cannot use vector here because Client has aiocb struct
|
||||||
|
// and when adding clients to tab pointers can be invalidated for aio reading
|
||||||
|
std::list<Client> client_tab;
|
||||||
int main_socket;
|
int main_socket;
|
||||||
fd_set read_set, write_set;
|
fd_set read_set, write_set;
|
||||||
bool close_server;
|
bool close_server;
|
||||||
HeadersParser headers_parser;
|
HeadersParser headers_parser;
|
||||||
|
char * in_buffer; // rename to a better name
|
||||||
|
size_t in_buffer_max_len;
|
||||||
|
//size_t how_many_sending_file; // how many sockets currently is used for sending files
|
||||||
|
|
||||||
|
void PrepareSocketsForSelect(int & fd_max, timeval & t, int & how_many_external_resources);
|
||||||
int AddSocketsToSet();
|
|
||||||
void AddNewClient();
|
void AddNewClient();
|
||||||
|
void AllocInputBuffer();
|
||||||
|
|
||||||
void ReadWriteToClients();
|
void ReadWriteToClients();
|
||||||
void ReadInputFromClient(Client & client);
|
void ReadInputFromClient(Client & client);
|
||||||
void WriteOutputToClient(Client & client);
|
void WriteOutputToClient(Client & client);
|
||||||
|
void ReadExternalResource(int how_many_external_resources);
|
||||||
|
|
||||||
|
|
||||||
void CheckHeaders(Client & client, size_t input_buffer_index);
|
void CheckHeaders(Client & client, size_t input_buffer_index);
|
||||||
|
void ParseHeaders(Client & client);
|
||||||
|
|
||||||
|
|
||||||
virtual bool SelectMethodName(Client & client, const std::wstring & method_name);
|
virtual bool SelectMethodName(Client & client, const std::wstring & method_name);
|
||||||
|
|
||||||
|
void ReadExternalResource(Client & client, std::string & output_buffer);
|
||||||
|
void WriteOutputToClient(Client & client, std::string & output_buffer, size_t & output_buffer_sent);
|
||||||
|
|
||||||
|
|
||||||
//void RemoveClientSocket(int client_socket);
|
//void RemoveClientSocket(int client_socket);
|
||||||
|
|
||||||
virtual void CreateAnswer(Client & client);
|
virtual void CreateAnswer(Client & client);
|
||||||
|
|
||||||
|
|
||||||
|
void PrepareMainSocket();
|
||||||
|
int FileLen(std::string & file_name, size_t & file_len);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,31 +79,6 @@ private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue