|
|
|
@ -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
|
|
|
|
|
{ |
|
|
|
|
if( client.reading_to_buffer == 1 ) |
|
|
|
|
{ |
|
|
|
|
client.reading_to_buffer = 0; |
|
|
|
|
client.external_resource.waiting_for_last_read = false; |
|
|
|
|
|
|
|
|
|
if( client.sending_from_buffer != 2 ) |
|
|
|
|
{ |
|
|
|
|
client.reading_to_buffer = 2; |
|
|
|
|
} |
|
|
|
|
if( output_buffer.size() > 1500 ) // send at least one full packed, add to config
|
|
|
|
|
{ |
|
|
|
|
if( client.reading_to_buffer == 1 ) |
|
|
|
|
{ |
|
|
|
|
client.reading_to_buffer = 0; |
|
|
|
|
|
|
|
|
|
if( client.sending_from_buffer == 0 ) |
|
|
|
|
{ |
|
|
|
|
client.sending_from_buffer = 1; |
|
|
|
|
} |
|
|
|
|
if( client.sending_from_buffer != 2 ) |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|