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;
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
}

View File

@ -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;

View File

@ -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<char>(c);
}
std::cout << "URL ASCII: " << url_ascii << "-----------------" << std::endl;
bool utf8_correct = PT::UTF8ToWide(url_ascii, client.url);
SkipWhite(client);

View File

@ -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;
}
*/
}

View File

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