From 80b53a7fd5a75d8a045aa57cff9aff4a3e9fff34 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 7 May 2017 22:56:44 +0000 Subject: [PATCH] start adding support for sending files git-svn-id: svn://ttmath.org/publicrep/libscorpiohttpserver/trunk@1063 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/client.cpp | 96 +++++-- src/client.h | 85 +++++- src/headers_parser.cpp | 6 +- src/main.cpp | 2 +- src/server.cpp | 620 ++++++++++++++++++++++++++++++----------- src/server.h | 53 ++-- 6 files changed, 636 insertions(+), 226 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index e6187ac..70a95ed 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,34 +1,33 @@ #include "client.h" +#include +#include Client::Client() { - in_buffer_max_len = WEBSERVER_INPUT_BUFFER_MAX_LEN; - socket = 0; - in_buffer = nullptr; - in_buffer_len = 0; - parsing_headers = true; - parsing_first_header = true; - http_method = http_method_unsupported; - http_version = http_version_unsupported; - answer_generated = false; - output_buffer_sent = 0; - close_connection = false; + socket = 0; + close_connection = false; + PrepareToNewRequest(); + read_static_buffer_size = 1500 * 3; // this will be testing (size of one packet * how many packets) + read_static_buffer = new char[read_static_buffer_size]; // add to config + std::cout << "alokuje buforek: " << (void*)read_static_buffer << std::endl; + + // check whether there is no too much copying when we add Client to a list } Client::Client(const Client & c) { - in_buffer = nullptr; operator=(c); } 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; - 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_first_header = c.parsing_first_header; http_method_str = c.http_method_str; @@ -54,6 +46,35 @@ Client & Client::operator=(const Client & c) output_buffer = c.output_buffer; output_buffer_sent = c.output_buffer_sent; 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; } @@ -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() { - if( !in_buffer ) - AllocInputBuffer(); - parsing_headers = true; parsing_first_header = true; - in_buffer_len = 0; http_method = http_method_unsupported; http_version = http_version_unsupported; answer_generated = false; 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(); output_buffer.clear(); + output_buffer_two.clear(); url.clear(); + send_file.clear(); + + external_resource.Clear(); + + memset(&iocb, 0, sizeof(iocb)); // don't set flag close_connection to false here } + diff --git a/src/client.h b/src/client.h index 81a8d2d..6dcbe0c 100644 --- a/src/client.h +++ b/src/client.h @@ -2,6 +2,7 @@ #define headerfile_libscorpiohttpserver_src_client_h +#include #include @@ -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 { public: + + int socket; PT::Space in; @@ -52,9 +96,39 @@ public: 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(const Client & c); @@ -62,15 +136,14 @@ public: Client & operator=(const Client & c); - void AllocInputBuffer(); void PrepareToNewRequest(); private: - char * in_buffer; // rename to a better name - size_t in_buffer_max_len; // at least two characters - size_t in_buffer_len; + //char * in_buffer; // rename to a better name + //size_t in_buffer_max_len; // at least two characters + //size_t in_buffer_len; std::wstring http_method_str; diff --git a/src/headers_parser.cpp b/src/headers_parser.cpp index a51631f..f05dbd8 100644 --- a/src/headers_parser.cpp +++ b/src/headers_parser.cpp @@ -35,9 +35,9 @@ void HeadersParser::ParseHeaders(Client & client) if( tmp_header.size() > 0 ) { - std::wcout << L"header parsed: "; - std::wcout << L"\"" << tmp_header << L"\"=\""; - std::wcout << tmp_value << L"\"" << std::endl; + //std::wcout << L"header parsed: "; + //std::wcout << L"\"" << tmp_header << L"\"=\""; + //std::wcout << tmp_value << L"\"" << std::endl; client.in.Add(tmp_header, tmp_value); } else diff --git a/src/main.cpp b/src/main.cpp index f138738..ca1b7b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,8 +40,8 @@ int main() signal(SIGPIPE, signal_handler_sigpipe); + server.Prepare(); - server.PrepareMainSocket(); server.Wait(); diff --git a/src/server.cpp b/src/server.cpp index 4c4c9e1..a66aec1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "server.h" #include "string_functions.h" @@ -16,8 +18,13 @@ Server::Server() { main_socket = -1; close_server = false; + in_buffer_max_len = 2048; + in_buffer = nullptr; } + + + Server::~Server() { Close(); @@ -36,8 +43,13 @@ void Server::CloseMainSocket() void Server::CloseClientSockets() { - for(size_t i=0 ; isocket); + + if( i->external_resource.external_resource_fd >= 0 ) + close(i->external_resource.external_resource_fd); + } 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() { @@ -106,14 +130,16 @@ void Server::Wait() { while( !close_server ) { - int fd_max = AddSocketsToSet(); - int ready_fd = select(fd_max + 1, &read_set, &write_set, 0, 0); + timeval t; + int fd_max; + int how_many_external_resources; - if( ready_fd < 0 ) - { - std::cout << "select failed" << std::endl; - return; - } + PrepareSocketsForSelect(fd_max, t, how_many_external_resources); + // sprawdzic czy jak t jest zerem to select czeka nieskonczenie dlugo czy od razu przerywa + int ready_fd = select(fd_max + 1, &read_set, &write_set, 0, &t); + + if( how_many_external_resources > 0 ) + ReadExternalResource(how_many_external_resources); 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(&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 ) { FD_SET(main_socket, &read_set); fd_max = main_socket; - for(size_t i=0 ; ianswering_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() ) - FD_SET(client_tab[i].socket, &write_set); + if( i->socket > fd_max ) + fd_max = i->socket; - if( client_tab[i].socket > fd_max ) - fd_max = client_tab[i].socket; + if( i->external_resource.reading_external_resource ) + { + how_many_external_resources += 1; + } } } else @@ -159,7 +202,8 @@ int Server::AddSocketsToSet() 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.close_connection = false; + c.PrepareToNewRequest(); client_tab.push_back(c); - client_tab.back().PrepareToNewRequest(); } else { @@ -209,30 +253,179 @@ int client_socket; void Server::ReadWriteToClients() { - size_t i = 0; - - while( i < client_tab.size() ) + for(auto i=client_tab.begin() ; i != client_tab.end() ; ) { - 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); - client_tab.erase(client_tab.begin() + i); + close(i->socket); + + 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 { - 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) { - std::cout << "trying read something from client number: " << client.socket << std::endl; - - // 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); + int read_len = read(client.socket, in_buffer, in_buffer_max_len); if( read_len < 0 ) { @@ -270,51 +448,26 @@ void Server::ReadInputFromClient(Client & client) else 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 client.close_connection = true; } else { - client.in_buffer_len += read_len; - size_t input_buffer_index = client.input_buffer.size(); - client.input_buffer.append(client.in_buffer, client.in_buffer_len); - client.in_buffer_len = 0; + client.input_buffer.append(in_buffer, read_len); if( client.parsing_headers ) 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 = client.output_buffer.c_str() + client.output_buffer_sent; - size_t how_many_to_send = client.output_buffer.size() - client.output_buffer_sent; + const char * data = output_buffer.c_str() + output_buffer_sent; + size_t how_many_to_send = output_buffer.size() - output_buffer_sent; if( how_many_to_send > 0 ) { @@ -326,11 +479,43 @@ void Server::WriteOutputToClient(Client & client) } 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) { - // 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 ) 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) ) { - 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; + ParseHeaders(client); 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; } } } +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) //{ // for(size_t i=0 ; i
bye bye"; - close_server = true; + file_len = s.st_size; + 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"

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; } diff --git a/src/server.h b/src/server.h index 4a16691..deadee0 100644 --- a/src/server.h +++ b/src/server.h @@ -1,7 +1,7 @@ #ifndef headerfile_libscorpiohttpserver_src_server_h #define headerfile_libscorpiohttpserver_src_server_h - +#include #include #include "client.h" #include "headers_parser.h" @@ -14,6 +14,10 @@ public: Server(); + + Server(const Server & s) = delete; + Server & operator=(const Server & s) = delete; + virtual ~Server(); @@ -21,38 +25,52 @@ public: void CloseClientSockets(); void Close(); - void PrepareMainSocket(); + void Prepare(); void Wait(); private: - std::vector 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_tab; int main_socket; fd_set read_set, write_set; bool close_server; 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 - - int AddSocketsToSet(); + void PrepareSocketsForSelect(int & fd_max, timeval & t, int & how_many_external_resources); void AddNewClient(); + void AllocInputBuffer(); void ReadWriteToClients(); void ReadInputFromClient(Client & client); void WriteOutputToClient(Client & client); + void ReadExternalResource(int how_many_external_resources); + void CheckHeaders(Client & client, size_t input_buffer_index); + void ParseHeaders(Client & client); 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); virtual void CreateAnswer(Client & client); + void PrepareMainSocket(); + int FileLen(std::string & file_name, size_t & file_len); + }; @@ -61,31 +79,6 @@ private: - - - - - - - - - - - - - - - - - - - - - - - - - #endif