868 lines
17 KiB
C++
868 lines
17 KiB
C++
#include <iostream>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <netinet/in.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <utf8/utf8.h>
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
#include "server.h"
|
|
#include "string_functions.h"
|
|
|
|
|
|
|
|
Server::Server()
|
|
{
|
|
main_socket = -1;
|
|
close_server = false;
|
|
in_buffer_max_len = 2048;
|
|
in_buffer = nullptr;
|
|
}
|
|
|
|
|
|
|
|
|
|
Server::~Server()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
|
|
void Server::CloseMainSocket()
|
|
{
|
|
if( main_socket != -1 )
|
|
{
|
|
close(main_socket);
|
|
main_socket = -1;
|
|
}
|
|
}
|
|
|
|
|
|
void Server::CloseClientSockets()
|
|
{
|
|
for(auto i=client_tab.begin() ; i != client_tab.end() ; ++i)
|
|
{
|
|
close(i->socket);
|
|
|
|
if( i->external_resource.external_resource_fd >= 0 )
|
|
close(i->external_resource.external_resource_fd);
|
|
}
|
|
|
|
client_tab.clear();
|
|
}
|
|
|
|
|
|
void Server::Close()
|
|
{
|
|
CloseMainSocket();
|
|
CloseClientSockets();
|
|
}
|
|
|
|
|
|
void Server::AllocInputBuffer()
|
|
{
|
|
delete [] in_buffer;
|
|
in_buffer = new char[in_buffer_max_len];
|
|
}
|
|
|
|
|
|
|
|
void Server::Prepare()
|
|
{
|
|
PrepareMainSocket();
|
|
AllocInputBuffer();
|
|
}
|
|
|
|
|
|
|
|
void Server::PrepareMainSocket()
|
|
{
|
|
CloseMainSocket();
|
|
|
|
main_socket = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
|
|
|
if( main_socket < 0 )
|
|
{
|
|
std::cout << "I cannot create a socket" << std::endl;
|
|
return;
|
|
}
|
|
|
|
int optval = 1;
|
|
|
|
if( setsockopt(main_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) < 0 )
|
|
{
|
|
std::cout << "I cannot setsockopt " << std::endl;
|
|
return;
|
|
}
|
|
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sin_len = sizeof(addr);
|
|
addr.sin_family = PF_INET;
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
addr.sin_port = htons(3012);
|
|
|
|
socklen_t len = sizeof(addr);
|
|
|
|
if( bind(main_socket, (struct sockaddr*)&addr, len) < 0 )
|
|
{
|
|
std::cout << "bind failed: " << std::endl;
|
|
return;
|
|
}
|
|
|
|
|
|
if( listen(main_socket, 100) < 0 )
|
|
{
|
|
std::cout << "listen failed" << std::endl;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Server::Wait()
|
|
{
|
|
while( !close_server )
|
|
{
|
|
timeval t;
|
|
int fd_max;
|
|
int how_many_external_resources;
|
|
|
|
PrepareSocketsForSelect(fd_max, t, how_many_external_resources);
|
|
|
|
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);
|
|
|
|
if( ready_fd > 0 )
|
|
{
|
|
if( FD_ISSET(main_socket, &read_set) )
|
|
{
|
|
AddNewClient();
|
|
}
|
|
else
|
|
{
|
|
ReadWriteToClients();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Server::PrepareSocketsForSelect(int & fd_max, timeval & t, int & how_many_external_resources)
|
|
{
|
|
FD_ZERO(&read_set);
|
|
FD_ZERO(&write_set);
|
|
|
|
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(auto i=client_tab.begin() ; i != client_tab.end() ; ++i)
|
|
{
|
|
if( !i->answering_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( i->socket > fd_max )
|
|
fd_max = i->socket;
|
|
|
|
if( i->external_resource.reading_external_resource )
|
|
{
|
|
how_many_external_resources += 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "there is no main socket" << std::endl;
|
|
}
|
|
|
|
if( how_many_external_resources > 0 )
|
|
t.tv_usec = 1;
|
|
}
|
|
|
|
|
|
|
|
void Server::AddNewClient()
|
|
{
|
|
struct sockaddr_in client_addr;
|
|
socklen_t len;
|
|
int client_socket;
|
|
//int optval;
|
|
|
|
memset(&client_addr, 0, sizeof(client_addr));
|
|
len = sizeof(client_addr);
|
|
|
|
client_socket = accept(main_socket, (struct sockaddr*)&client_addr, &len);
|
|
|
|
if( client_socket < 0 )
|
|
{
|
|
std::cout << "accept failed" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
int opt = fcntl(client_socket, F_GETFL);
|
|
|
|
if( opt >= 0 )
|
|
{
|
|
opt = opt | O_NONBLOCK;
|
|
|
|
if( fcntl(client_socket, F_SETFL, opt) >= 0 )
|
|
{
|
|
Client c;
|
|
|
|
c.socket = client_socket;
|
|
c.close_connection = false;
|
|
c.PrepareToNewRequest();
|
|
|
|
client_tab.push_back(c);
|
|
}
|
|
else
|
|
{
|
|
std::cout << "I cannot fcntl (O_NONBLOCK)" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Server::ReadWriteToClients()
|
|
{
|
|
for(auto i=client_tab.begin() ; i != client_tab.end() ; )
|
|
{
|
|
if( FD_ISSET(i->socket, &read_set))
|
|
{
|
|
ReadInputFromClient(*i);
|
|
}
|
|
|
|
if( FD_ISSET(i->socket, &write_set) )
|
|
{
|
|
WriteOutputToClient(*i);
|
|
}
|
|
|
|
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 " << i->socket << std::endl;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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 )
|
|
{
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
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 )
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
std::cout << "some error" << std::endl;
|
|
// what about this buffer?
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Server::ReadInputFromClient(Client & client)
|
|
{
|
|
int read_len = read(client.socket, in_buffer, in_buffer_max_len);
|
|
|
|
if( read_len < 0 )
|
|
{
|
|
// read failed, we do not parse this request
|
|
|
|
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
|
|
{
|
|
size_t input_buffer_index = client.input_buffer.size();
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Server::WriteOutputToClient(Client & client, std::string & output_buffer, size_t & 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;
|
|
int len = 0;
|
|
|
|
if( how_many_to_send > 0 )
|
|
{
|
|
len = send(client.socket, data, how_many_to_send, 0);
|
|
|
|
if( len < 0 )
|
|
{
|
|
std::cout << "writing failed" << std::endl;
|
|
}
|
|
}
|
|
|
|
if( len >= 0 )
|
|
{
|
|
output_buffer_sent += len;
|
|
|
|
if( output_buffer_sent >= output_buffer.size() )
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
{
|
|
// 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;
|
|
else
|
|
input_buffer_index = 0;
|
|
|
|
for( ; input_buffer_index + 3 < client.input_buffer.size() ; ++input_buffer_index)
|
|
{
|
|
if( headers_parser.IsHeadersEnding(client.input_buffer.c_str() + input_buffer_index) )
|
|
{
|
|
ParseHeaders(client);
|
|
client.input_buffer.erase(0, input_buffer_index + 4);
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Server::SelectMethodName(Client & client, const std::wstring & method_name)
|
|
{
|
|
client.http_method = http_method_unsupported;
|
|
|
|
if( CompareNoCase(method_name, L"get") )
|
|
{
|
|
client.http_method = http_method_get;
|
|
}
|
|
else
|
|
if( CompareNoCase(method_name, L"put") )
|
|
{
|
|
client.http_method = http_method_put;
|
|
}
|
|
else
|
|
if( CompareNoCase(method_name, L"post") )
|
|
{
|
|
client.http_method = http_method_post;
|
|
}
|
|
else
|
|
if( CompareNoCase(method_name, L"delete") )
|
|
{
|
|
client.http_method = http_method_delete;
|
|
}
|
|
else
|
|
if( CompareNoCase(method_name, L"options") )
|
|
{
|
|
client.http_method = http_method_options;
|
|
}
|
|
|
|
return client.http_method != http_method_unsupported;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//void Server::RemoveClientSocket(int client_socket)
|
|
//{
|
|
// for(size_t i=0 ; i<client_tab.size() ; ++i)
|
|
// {
|
|
// if( client_tab[i].socket == client_socket )
|
|
// {
|
|
// close(client_socket);
|
|
// client_tab.erase(client_tab.begin() + i);
|
|
//
|
|
// // warning: in ReadWriteToClients we have a loop through client_tab
|
|
// // (next item will be skipped by ++i)
|
|
// break;
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
int Server::FileLen(std::string & file_name, size_t & file_len)
|
|
{
|
|
struct stat s;
|
|
|
|
file_len = 0;
|
|
|
|
int res = stat(file_name.c_str(), &s);
|
|
|
|
if( res == 0 )
|
|
{
|
|
file_len = s.st_size;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Server::CreateAnswer(Client & client)
|
|
{
|
|
// tmp, a user method will be called
|
|
|
|
std::wstring a, c;
|
|
std::string c_ascii;
|
|
|
|
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/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) )
|
|
{
|
|
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);
|
|
|
|
// 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 )
|
|
{
|
|
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;
|
|
|
|
client.external_resource.reading_external_resource = true;
|
|
client.external_resource.type = ExternalResource::type_file;
|
|
}
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
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";
|
|
|
|
if( client.url == L"/quit" )
|
|
{
|
|
c += L"<br><br>bye bye";
|
|
close_server = true;
|
|
}
|
|
|
|
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;
|
|
}
|
|
*/
|
|
}
|
|
|
|
|