diff --git a/src/client.cpp b/src/client.cpp index 70a95ed..55f1dd2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -10,7 +10,7 @@ Client::Client() 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_size = 1500 * 30; // 1500 * 30 // 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; @@ -76,6 +76,10 @@ Client & Client::operator=(const Client & c) memcpy(read_static_buffer, c.read_static_buffer, read_static_buffer_size); + + out_headers = c.out_headers; + status = c.status; + return *this; } @@ -120,6 +124,9 @@ void Client::PrepareToNewRequest() memset(&iocb, 0, sizeof(iocb)); + out_headers.Clear(); + status = 404; + // don't set flag close_connection to false here } diff --git a/src/client.h b/src/client.h index 6dcbe0c..08f506c 100644 --- a/src/client.h +++ b/src/client.h @@ -85,6 +85,19 @@ public: HTTPMethod http_method; HTTPVersion http_version; + + // a better name? + PT::Space out_headers; + + + + + int status; + + + + + bool answer_generated; bool close_connection; diff --git a/src/headers_parser.cpp b/src/headers_parser.cpp index f05dbd8..49b22cc 100644 --- a/src/headers_parser.cpp +++ b/src/headers_parser.cpp @@ -12,11 +12,17 @@ void HeadersParser::ParseHeaders(Client & client) if( !ParseFirstHeader(client) ) { - std::cout << "incorrect first header, closing connection" << std::endl; + std::cout << "incorrect first header, closing connection ------------------------------------" << std::endl; client.close_connection = true; return; } + // remove me + if( client.url == L"/static/styles.css" ) + { + header_index = 0; + } + // we are testing header_index + 3 < client.input_buffer.size() because we know // that the \r\n\r\n sequence already exists in this string // so there is no a problem that we leave some characters at the end of the string @@ -163,6 +169,8 @@ bool HeadersParser::ParseFirstHeaderURL(Client & client) url_ascii += static_cast(c); } + std::cout << "URL ASCII: " << url_ascii << "-----------------" << std::endl; + bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url); SkipWhite(client); diff --git a/src/server.cpp b/src/server.cpp index a66aec1..ef5b4c7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -135,8 +135,13 @@ void Server::Wait() int how_many_external_resources; 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); + + timeval * pt = 0; + + if( how_many_external_resources > 0 ) + pt = &t; + + int ready_fd = select(fd_max + 1, &read_set, &write_set, 0, pt); if( how_many_external_resources > 0 ) ReadExternalResource(how_many_external_resources); @@ -363,6 +368,10 @@ void Server::ReadExternalResource(Client & client, std::string & output_buffer) if( res < 0 ) { + 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; int err = errno; std::cout << "aio_return returned error, errno: " << err << std::endl; } @@ -385,42 +394,43 @@ void Server::ReadExternalResource(Client & client, std::string & output_buffer) 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 + client.external_resource.waiting_for_last_read = false; + + if( output_buffer.size() > 1500 ) // send at least one full packed, add to config + { + if( client.reading_to_buffer == 1 ) { - if( client.reading_to_buffer == 1 ) + client.reading_to_buffer = 0; + + if( client.sending_from_buffer != 2 ) { - 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; - } + client.reading_to_buffer = 2; } - else - if( client.reading_to_buffer == 2 ) + + if( client.sending_from_buffer == 0 ) { - client.reading_to_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 != 1 ) + { + client.reading_to_buffer = 1; + } - if( client.sending_from_buffer == 0 ) - { - client.sending_from_buffer = 2; - } + if( client.sending_from_buffer == 0 ) + { + client.sending_from_buffer = 2; } } } - client.external_resource.waiting_for_last_read = false; } else { @@ -442,13 +452,14 @@ void Server::ReadInputFromClient(Client & client) { // read failed, we do not parse this request - std::cout << "read failed" << std::endl; + std::cout << "read failed for client " << client.socket << std::endl; client.close_connection = true; } else if( read_len == 0 ) { // the client has terminated connection + std::cout << "read returned 0, client " << client.socket << " closed the connection" << std::endl; client.close_connection = true; } else @@ -457,6 +468,13 @@ void Server::ReadInputFromClient(Client & client) client.input_buffer.append(in_buffer, read_len); + std::cout << "read from client " << client.socket << ":"; + + for(size_t i=0 ; i<(size_t)read_len ; ++i) + std::cout << in_buffer[i]; + + std::cout << std::endl; + if( client.parsing_headers ) CheckHeaders(client, input_buffer_index); } @@ -468,53 +486,54 @@ void Server::WriteOutputToClient(Client & client, std::string & output_buffer, s { const char * data = output_buffer.c_str() + output_buffer_sent; size_t how_many_to_send = output_buffer.size() - output_buffer_sent; + int len = 0; if( how_many_to_send > 0 ) { - int len = send(client.socket, data, how_many_to_send, 0); + len = send(client.socket, data, how_many_to_send, 0); if( len < 0 ) { std::cout << "writing failed" << std::endl; } - else + } + + if( len >= 0 ) + { + output_buffer_sent += len; + + if( output_buffer_sent >= output_buffer.size() ) { - output_buffer_sent += len; + output_buffer.clear(); + output_buffer_sent = 0; - if( output_buffer_sent >= output_buffer.size() ) + if( client.sending_from_buffer == 1 ) { - output_buffer.clear(); - output_buffer_sent = 0; + client.sending_from_buffer = 0; - - if( client.sending_from_buffer == 1 ) + if( client.reading_to_buffer != 2 && !client.output_buffer_two.empty() ) { - 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; - } + client.sending_from_buffer = 2; } - else - if( client.sending_from_buffer == 2 ) + + if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 ) { - client.sending_from_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.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; - } + if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 ) + { + client.reading_to_buffer = 2; } } } @@ -692,6 +711,58 @@ int Server::FileLen(std::string & file_name, size_t & file_len) } +void Server::CreateOutputHeaders(Client & client) +{ + std::wstring a; + wchar_t buf[32]; + swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", client.status); + + a = L"HTTP/"; + + if( client.http_version == http_version_1_0 ) + a += L"1.0"; + else + a += L"1.1"; + + a += L" "; + a += buf; + a += L" "; + + + if( client.status == 200 ) + a += L"OK"; + else + if( client.status == 404 ) + a += L"Not Found"; + + a += L"\r\n"; + PT::WideToUTF8(a, client.output_buffer); // we can use directly client.output_buffer without 'a' + + auto i = client.out_headers.table_single.begin(); + bool has_connection = false; + + for( ; i != client.out_headers.table_single.end() ; ++i) + { + a = i->first; + a += L": "; + a += i->second; + a += L"\r\n"; + PT::WideToUTF8(a, client.output_buffer, false); + + if( CompareNoCase(i->first, L"connection") ) + has_connection = true; + } + + if( !has_connection && CompareNoCase(client.in.Text(L"connection"), L"keep-alive") ) + { + client.output_buffer += "Connection: keep-alive\r\n"; + } + + + a = L"\r\n"; + PT::WideToUTF8(a, client.output_buffer, false); +} + @@ -702,39 +773,30 @@ void Server::CreateAnswer(Client & client) std::wstring a, c; std::string c_ascii; - if( client.url == L"/swinka.jpg" ) + if( client.url == L"/static/styles.css" ) + { + a.clear(); + } + + if( client.url == L"/quit" ) + { + close_server = true; + } + + //if( client.url == L"/swinka.jpg" ) { std::string file_name_ascii; - client.send_file = L"/home/tomek/pani.jpg"; + client.send_file = L"/home/tomek/roboczy/prog/libscorpiohttpserver/www-data"; + client.send_file += client.url; 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); + client.status = 200; + //client.out_headers.Add(L"Content-Type", L"image/jpeg;"); + client.out_headers.Add(L"Content-Length", client.external_resource.file_len); + CreateOutputHeaders(client); if( client.external_resource.external_resource_fd != -1 ) close(client.external_resource.external_resource_fd); @@ -744,6 +806,7 @@ void Server::CreateAnswer(Client & client) if( client.external_resource.external_resource_fd >= 0 ) { + std::cout << "przygotowuje do czytania pliku " << file_name_ascii << std::endl; client.reading_to_buffer = 1; client.sending_from_buffer = 0; client.answering_to_client = true; @@ -756,13 +819,29 @@ void Server::CreateAnswer(Client & client) } else { - // return an error page? + client.status = 404; + client.out_headers.Add(L"Content-Type", L"text/html; charset=UTF-8"); + + c = L"404 nie ma czegos takiego"; + PT::WideToUTF8(c, c_ascii); + + client.out_headers.Add(L"Content-Length", c_ascii.size()); + CreateOutputHeaders(client); + client.output_buffer += c_ascii; + + client.reading_to_buffer = 0; + client.sending_from_buffer = 1; + client.answering_to_client = true; } return; } + /* else { + client.status = 200; + client.out_headers.Add(L"Content-Type", L"text/html; charset=UTF-8"); + c = L"hello world from my webserver, your requested: " + client.url; c += L"\r\n"; @@ -774,41 +853,15 @@ void Server::CreateAnswer(Client & client) 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.out_headers.Add(L"Content-Length", c_ascii.size()); + CreateOutputHeaders(client); client.output_buffer += c_ascii; client.reading_to_buffer = 0; client.sending_from_buffer = 1; client.answering_to_client = true; - } - + */ } diff --git a/src/server.h b/src/server.h index deadee0..3c27c34 100644 --- a/src/server.h +++ b/src/server.h @@ -71,6 +71,9 @@ private: void PrepareMainSocket(); int FileLen(std::string & file_name, size_t & file_len); + + void CreateOutputHeaders(Client & client); + };