fixed: last packet from a file was not sent to the browser

git-svn-id: svn://ttmath.org/publicrep/libscorpiohttpserver/trunk@1064 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2017-05-09 10:09:28 +00:00
parent 80b53a7fd5
commit 3d7148e8c0
5 changed files with 200 additions and 116 deletions

View File

@ -10,7 +10,7 @@ Client::Client()
socket = 0; socket = 0;
close_connection = false; close_connection = false;
PrepareToNewRequest(); 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 read_static_buffer = new char[read_static_buffer_size]; // add to config
std::cout << "alokuje buforek: " << (void*)read_static_buffer << std::endl; 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); memcpy(read_static_buffer, c.read_static_buffer, read_static_buffer_size);
out_headers = c.out_headers;
status = c.status;
return *this; return *this;
} }
@ -120,6 +124,9 @@ void Client::PrepareToNewRequest()
memset(&iocb, 0, sizeof(iocb)); memset(&iocb, 0, sizeof(iocb));
out_headers.Clear();
status = 404;
// don't set flag close_connection to false here // don't set flag close_connection to false here
} }

View File

@ -85,6 +85,19 @@ public:
HTTPMethod http_method; HTTPMethod http_method;
HTTPVersion http_version; HTTPVersion http_version;
// a better name?
PT::Space out_headers;
int status;
bool answer_generated; bool answer_generated;
bool close_connection; bool close_connection;

View File

@ -12,11 +12,17 @@ void HeadersParser::ParseHeaders(Client & client)
if( !ParseFirstHeader(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; client.close_connection = true;
return; 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 // 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 // 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 // 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<char>(c); url_ascii += static_cast<char>(c);
} }
std::cout << "URL ASCII: " << url_ascii << "-----------------" << std::endl;
bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url); bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url);
SkipWhite(client); SkipWhite(client);

View File

@ -135,8 +135,13 @@ void Server::Wait()
int how_many_external_resources; int how_many_external_resources;
PrepareSocketsForSelect(fd_max, t, 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 ) if( how_many_external_resources > 0 )
ReadExternalResource(how_many_external_resources); ReadExternalResource(how_many_external_resources);
@ -363,6 +368,10 @@ void Server::ReadExternalResource(Client & client, std::string & output_buffer)
if( res < 0 ) 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; int err = errno;
std::cout << "aio_return returned error, errno: " << err << std::endl; 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); output_buffer.append(client.read_static_buffer, res);
client.external_resource.file_how_many_read += (size_t)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; client.reading_to_buffer = 2;
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 ) 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 ) if( client.sending_from_buffer != 1 )
{ {
client.reading_to_buffer = 1; client.reading_to_buffer = 1;
} }
if( client.sending_from_buffer == 0 ) if( client.sending_from_buffer == 0 )
{ {
client.sending_from_buffer = 2; client.sending_from_buffer = 2;
}
} }
} }
} }
client.external_resource.waiting_for_last_read = false;
} }
else else
{ {
@ -442,13 +452,14 @@ void Server::ReadInputFromClient(Client & client)
{ {
// read failed, we do not parse this request // 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; client.close_connection = true;
} }
else else
if( read_len == 0 ) if( read_len == 0 )
{ {
// the client has terminated connection // the client has terminated connection
std::cout << "read returned 0, client " << client.socket << " closed the connection" << std::endl;
client.close_connection = true; client.close_connection = true;
} }
else else
@ -457,6 +468,13 @@ void Server::ReadInputFromClient(Client & client)
client.input_buffer.append(in_buffer, read_len); 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 ) if( client.parsing_headers )
CheckHeaders(client, input_buffer_index); 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; const char * data = output_buffer.c_str() + output_buffer_sent;
size_t how_many_to_send = output_buffer.size() - output_buffer_sent; size_t how_many_to_send = output_buffer.size() - output_buffer_sent;
int len = 0;
if( how_many_to_send > 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 ) if( len < 0 )
{ {
std::cout << "writing failed" << std::endl; 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(); client.sending_from_buffer = 0;
output_buffer_sent = 0;
if( client.reading_to_buffer != 2 && !client.output_buffer_two.empty() )
if( client.sending_from_buffer == 1 )
{ {
client.sending_from_buffer = 0; client.sending_from_buffer = 2;
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 ) 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() ) if( client.reading_to_buffer != 1 && !client.output_buffer.empty() )
{ {
client.sending_from_buffer = 1; client.sending_from_buffer = 1;
} }
if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 ) if( client.external_resource.reading_external_resource && client.reading_to_buffer == 0 )
{ {
client.reading_to_buffer = 2; 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::wstring a, c;
std::string c_ascii; 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; 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); PT::WideToUTF8(client.send_file, file_name_ascii);
if( FileLen(file_name_ascii, client.external_resource.file_len) ) if( FileLen(file_name_ascii, client.external_resource.file_len) )
{ {
a = L"HTTP/"; client.status = 200;
//client.out_headers.Add(L"Content-Type", L"image/jpeg;");
if( client.http_version == http_version_1_0 ) client.out_headers.Add(L"Content-Length", client.external_resource.file_len);
a += L"1.0"; CreateOutputHeaders(client);
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 ) if( client.external_resource.external_resource_fd != -1 )
close(client.external_resource.external_resource_fd); close(client.external_resource.external_resource_fd);
@ -744,6 +806,7 @@ void Server::CreateAnswer(Client & client)
if( client.external_resource.external_resource_fd >= 0 ) 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.reading_to_buffer = 1;
client.sending_from_buffer = 0; client.sending_from_buffer = 0;
client.answering_to_client = true; client.answering_to_client = true;
@ -756,13 +819,29 @@ void Server::CreateAnswer(Client & client)
} }
else 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; return;
} }
/*
else 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"hello world from my webserver, your requested: " + client.url;
c += L"\r\n"; c += L"\r\n";
@ -774,41 +853,15 @@ void Server::CreateAnswer(Client & client)
PT::WideToUTF8(c,c_ascii); PT::WideToUTF8(c,c_ascii);
client.out_headers.Add(L"Content-Length", c_ascii.size());
a = L"HTTP/"; CreateOutputHeaders(client);
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.output_buffer += c_ascii;
client.reading_to_buffer = 0; client.reading_to_buffer = 0;
client.sending_from_buffer = 1; client.sending_from_buffer = 1;
client.answering_to_client = true; client.answering_to_client = true;
} }
*/
} }

View File

@ -71,6 +71,9 @@ private:
void PrepareMainSocket(); void PrepareMainSocket();
int FileLen(std::string & file_name, size_t & file_len); int FileLen(std::string & file_name, size_t & file_len);
void CreateOutputHeaders(Client & client);
}; };