|
@ -1,5 +1,5 @@ |
|
|
/**
|
|
|
/**
|
|
|
* Copyright (C) 2015-2016 Jessica James. |
|
|
* Copyright (C) 2015-2021 Jessica James. |
|
|
* |
|
|
* |
|
|
* Permission to use, copy, modify, and/or distribute this software for any |
|
|
* Permission to use, copy, modify, and/or distribute this software for any |
|
|
* purpose with or without fee is hereby granted, provided that the above |
|
|
* purpose with or without fee is hereby granted, provided that the above |
|
@ -21,7 +21,6 @@ |
|
|
#include "String.hpp" |
|
|
#include "String.hpp" |
|
|
#include "Reference_String.h" |
|
|
#include "Reference_String.h" |
|
|
#include "TCPSocket.h" |
|
|
#include "TCPSocket.h" |
|
|
#include "ArrayList.h" |
|
|
|
|
|
#include "HTTP.h" |
|
|
#include "HTTP.h" |
|
|
#include "HTTP_Server.h" |
|
|
#include "HTTP_Server.h" |
|
|
|
|
|
|
|
@ -50,131 +49,108 @@ enum HTTPVersion |
|
|
|
|
|
|
|
|
// HTTP::Server::Content
|
|
|
// HTTP::Server::Content
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) |
|
|
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) { |
|
|
{ |
|
|
|
|
|
Jupiter::HTTP::Server::Content::function = in_function; |
|
|
Jupiter::HTTP::Server::Content::function = in_function; |
|
|
Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive
|
|
|
Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
|
|
|
return Jupiter::HTTP::Server::Content::function(query_string); |
|
|
return Jupiter::HTTP::Server::Content::function(query_string); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// HTTP::Server::Directory
|
|
|
// HTTP::Server::Directory
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) |
|
|
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) { |
|
|
{ |
|
|
|
|
|
name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum(); |
|
|
name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Directory::~Directory() |
|
|
Jupiter::HTTP::Server::Directory::~Directory() { |
|
|
{ |
|
|
|
|
|
Jupiter::HTTP::Server::Directory::directories.emptyAndDelete(); |
|
|
|
|
|
Jupiter::HTTP::Server::Directory::content.emptyAndDelete(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// host/dir/content
|
|
|
// host/dir/content
|
|
|
// .hook("dir/subdir/", content)
|
|
|
// .hook("dir/subdir/", content)
|
|
|
|
|
|
|
|
|
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, Content *in_content) |
|
|
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, std::unique_ptr<Content> in_content) { |
|
|
{ |
|
|
|
|
|
Jupiter::ReferenceString in_name_ref = in_name; |
|
|
Jupiter::ReferenceString in_name_ref = in_name; |
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
|
|
|
|
|
|
if (in_name_ref.isEmpty()) // Hook content
|
|
|
if (in_name_ref.isEmpty()) { // Hook content
|
|
|
Jupiter::HTTP::Server::Directory::content.add(in_content); |
|
|
content.push_back(std::move(in_content)); |
|
|
else |
|
|
return; |
|
|
{ |
|
|
} |
|
|
size_t index = in_name_ref.find('/'); |
|
|
|
|
|
Jupiter::ReferenceString dir_name; |
|
|
|
|
|
if (index == Jupiter::INVALID_INDEX) |
|
|
|
|
|
dir_name = in_name_ref; |
|
|
|
|
|
else |
|
|
|
|
|
dir_name = in_name_ref.substring(size_t{ 0 }, index); |
|
|
|
|
|
|
|
|
|
|
|
in_name_ref.shiftRight(dir_name.size()); |
|
|
|
|
|
Jupiter::HTTP::Server::Directory *directory; |
|
|
|
|
|
unsigned int dir_name_checksum = dir_name.calcChecksum(); |
|
|
|
|
|
index = Jupiter::HTTP::Server::Directory::directories.size(); |
|
|
|
|
|
while (index != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
directory = Jupiter::HTTP::Server::Directory::directories.get(--index); |
|
|
|
|
|
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) |
|
|
|
|
|
{ |
|
|
|
|
|
directory->hook(in_name_ref, in_content); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// create directories
|
|
|
size_t index = in_name_ref.find('/'); |
|
|
directory = new Jupiter::HTTP::Server::Directory(dir_name); |
|
|
Jupiter::ReferenceString dir_name; |
|
|
Jupiter::HTTP::Server::Directory::directories.add(directory); |
|
|
if (index == Jupiter::INVALID_INDEX) { |
|
|
|
|
|
dir_name = in_name_ref; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
dir_name = in_name_ref.substring(size_t{ 0 }, index); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
directory_add_loop: |
|
|
in_name_ref.shiftRight(dir_name.size()); |
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
unsigned int dir_name_checksum = dir_name.calcChecksum(); |
|
|
if (in_name_ref.isNotEmpty()) |
|
|
index = directories.size(); |
|
|
{ |
|
|
for (auto& directory : directories) { |
|
|
// add directory
|
|
|
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) { |
|
|
index = in_name_ref.find('/'); |
|
|
directory->hook(in_name_ref, std::move(in_content)); |
|
|
if (index != Jupiter::INVALID_INDEX) |
|
|
return; |
|
|
{ |
|
|
|
|
|
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref.substring(size_t{ 0 }, index))); |
|
|
|
|
|
directory = directory->directories.get(directories.size() - 1); |
|
|
|
|
|
in_name_ref.shiftRight(index + 1); |
|
|
|
|
|
goto directory_add_loop; |
|
|
|
|
|
} |
|
|
|
|
|
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref)); |
|
|
|
|
|
directory = directory->directories.get(directories.size() - 1); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// add content
|
|
|
// create directories
|
|
|
directory->content.add(in_content); |
|
|
Directory* directory = directories.emplace_back(std::make_unique<Directory>(dir_name)).get(); |
|
|
|
|
|
|
|
|
|
|
|
directory_add_loop: // TODO: for the love of god, why why why
|
|
|
|
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
|
|
|
if (in_name_ref.isNotEmpty()) { |
|
|
|
|
|
// add directory
|
|
|
|
|
|
index = in_name_ref.find('/'); |
|
|
|
|
|
if (index != Jupiter::INVALID_INDEX) { |
|
|
|
|
|
directory->directories.push_back(std::make_unique<Directory>(in_name_ref.substring(size_t{ 0 }, index))); |
|
|
|
|
|
directory = directory->directories[directories.size() - 1].get(); |
|
|
|
|
|
in_name_ref.shiftRight(index + 1); |
|
|
|
|
|
goto directory_add_loop; |
|
|
|
|
|
} |
|
|
|
|
|
directory->directories.push_back(std::make_unique<Directory>(in_name_ref)); |
|
|
|
|
|
directory = directory->directories[directories.size() - 1].get(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// add content
|
|
|
|
|
|
directory->content.push_back(std::move(in_content)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) |
|
|
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) { |
|
|
{ |
|
|
|
|
|
size_t index; |
|
|
|
|
|
Jupiter::ReferenceString in_name_ref = path; |
|
|
Jupiter::ReferenceString in_name_ref = path; |
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
in_name_ref.shiftRight(in_name_ref.span('/')); |
|
|
unsigned int checksum; |
|
|
unsigned int checksum; |
|
|
|
|
|
|
|
|
if (in_name_ref.isEmpty()) // Remove content
|
|
|
if (in_name_ref.isEmpty()) { // Remove content
|
|
|
{ |
|
|
|
|
|
Jupiter::HTTP::Server::Content *content_node; |
|
|
|
|
|
checksum = content_name.calcChecksum(); |
|
|
checksum = content_name.calcChecksum(); |
|
|
index = Jupiter::HTTP::Server::Directory::content.size(); |
|
|
for (auto itr = content.begin(); itr != content.end(); ++itr) { |
|
|
while (index != 0) |
|
|
auto& content_node = *itr; |
|
|
{ |
|
|
if (content_node->name_checksum == checksum && content_node->name.equals(content_name)) { |
|
|
content_node = Jupiter::HTTP::Server::Directory::content.get(--index); |
|
|
content.erase(itr); |
|
|
if (content_node->name_checksum == checksum && content_node->name.equals(content_name)) |
|
|
|
|
|
{ |
|
|
|
|
|
delete Jupiter::HTTP::Server::Directory::content.remove(index); |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
else // Call remove() on next directory in path
|
|
|
|
|
|
{ |
|
|
// Call remove() on next directory in path
|
|
|
index = in_name_ref.find('/'); |
|
|
size_t index = in_name_ref.find('/'); |
|
|
Jupiter::ReferenceString dir_name; |
|
|
Jupiter::ReferenceString dir_name; |
|
|
if (index == Jupiter::INVALID_INDEX) |
|
|
if (index == Jupiter::INVALID_INDEX) |
|
|
dir_name = in_name_ref; |
|
|
dir_name = in_name_ref; |
|
|
else |
|
|
else |
|
|
dir_name = in_name_ref.substring(size_t{ 0 }, index); |
|
|
dir_name = in_name_ref.substring(size_t{ 0 }, index); |
|
|
|
|
|
|
|
|
in_name_ref.shiftRight(dir_name.size()); |
|
|
in_name_ref.shiftRight(dir_name.size()); |
|
|
Jupiter::HTTP::Server::Directory *directory; |
|
|
checksum = dir_name.calcChecksum(); |
|
|
checksum = dir_name.calcChecksum(); |
|
|
for (auto& directory : directories) { |
|
|
index = Jupiter::HTTP::Server::Directory::directories.size(); |
|
|
if (directory->name_checksum == checksum && directory->name.equals(dir_name)) { |
|
|
while (index != 0) |
|
|
return directory->remove(in_name_ref, content_name); |
|
|
{ |
|
|
|
|
|
directory = Jupiter::HTTP::Server::Directory::directories.get(--index); |
|
|
|
|
|
if (directory->name_checksum == checksum && directory->name.equals(dir_name)) |
|
|
|
|
|
return directory->remove(in_name_ref, content_name); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
return false; |
|
@ -182,7 +158,7 @@ bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &pat |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name) |
|
|
bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name) |
|
|
{ |
|
|
{ |
|
|
return this->find(in_name) != nullptr; |
|
|
return find(in_name) != nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name) |
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name) |
|
@ -191,96 +167,86 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jup |
|
|
in_name_ref.shiftRight(in_name_ref.span("/"_jrs)); |
|
|
in_name_ref.shiftRight(in_name_ref.span("/"_jrs)); |
|
|
|
|
|
|
|
|
size_t index = in_name_ref.find('/'); |
|
|
size_t index = in_name_ref.find('/'); |
|
|
if (index == Jupiter::INVALID_INDEX) // Search content
|
|
|
if (index == Jupiter::INVALID_INDEX) { // Search content
|
|
|
{ |
|
|
|
|
|
unsigned int content_name_checksum = in_name_ref.calcChecksum(); |
|
|
unsigned int content_name_checksum = in_name_ref.calcChecksum(); |
|
|
index = Jupiter::HTTP::Server::Directory::content.size(); |
|
|
index = content.size(); |
|
|
Jupiter::HTTP::Server::Content *content_itr; |
|
|
for (auto& content_item : content) { |
|
|
while (index != 0) |
|
|
if (content_item->name_checksum == content_name_checksum && content_item->name.equals(in_name_ref)) { |
|
|
{ |
|
|
return content_item.get(); |
|
|
content_itr = Jupiter::HTTP::Server::Directory::content.get(--index); |
|
|
} |
|
|
if (content_itr->name_checksum == content_name_checksum && content_itr->name.equals(in_name_ref)) |
|
|
|
|
|
return content_itr; |
|
|
|
|
|
} |
|
|
} |
|
|
return nullptr; // No such content
|
|
|
return nullptr; // No such content
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index); |
|
|
Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index); |
|
|
in_name_ref.shiftRight(dir_name.size() + 1); |
|
|
in_name_ref.shiftRight(dir_name.size() + 1); |
|
|
Jupiter::HTTP::Server::Directory *directory; |
|
|
|
|
|
unsigned int dir_name_checksum = dir_name.calcChecksum(); |
|
|
unsigned int dir_name_checksum = dir_name.calcChecksum(); |
|
|
index = Jupiter::HTTP::Server::Directory::directories.size(); |
|
|
|
|
|
|
|
|
|
|
|
while (index != 0) |
|
|
for (auto& directory : directories) { |
|
|
{ |
|
|
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) { |
|
|
directory = Jupiter::HTTP::Server::Directory::directories.get(--index); |
|
|
|
|
|
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) |
|
|
|
|
|
return directory->find(in_name_ref); |
|
|
return directory->find(in_name_ref); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return nullptr; // No such directory
|
|
|
return nullptr; // No such directory
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
Jupiter::HTTP::Server::Content *content_ptr = find(in_name); |
|
|
Jupiter::HTTP::Server::Content *content_ptr = Jupiter::HTTP::Server::Directory::find(in_name); |
|
|
|
|
|
if (content_ptr == nullptr) |
|
|
if (content_ptr == nullptr) |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
|
|
|
|
|
|
return content_ptr->execute(query_string); |
|
|
return content_ptr->execute(query_string); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// HTTP::Server::Host
|
|
|
// HTTP::Server::Host
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) |
|
|
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) { |
|
|
{ |
|
|
|
|
|
name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi(); |
|
|
name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// HTTPSession struct
|
|
|
// HTTPSession struct
|
|
|
|
|
|
|
|
|
struct HTTPSession |
|
|
struct HTTPSession { |
|
|
{ |
|
|
|
|
|
Jupiter::Socket sock; |
|
|
Jupiter::Socket sock; |
|
|
Jupiter::String request; |
|
|
Jupiter::String request; |
|
|
bool keep_alive = false; |
|
|
bool keep_alive = false; |
|
|
Jupiter::HTTP::Server::Host *host = nullptr; |
|
|
Jupiter::HTTP::Server::Host* host = nullptr; |
|
|
HTTPVersion version = HTTPVersion::HTTP_1_0; |
|
|
HTTPVersion version = HTTPVersion::HTTP_1_0; |
|
|
std::chrono::steady_clock::time_point last_active = std::chrono::steady_clock::now(); |
|
|
std::chrono::steady_clock::time_point last_active = std::chrono::steady_clock::now(); |
|
|
HTTPSession(Jupiter::Socket &&in_sock); |
|
|
HTTPSession(Jupiter::Socket&& in_sock); |
|
|
~HTTPSession(); |
|
|
~HTTPSession(); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
HTTPSession::HTTPSession(Jupiter::Socket &&in_sock) : sock(std::move(in_sock)) |
|
|
HTTPSession::HTTPSession(Jupiter::Socket&& in_sock) |
|
|
{ |
|
|
: sock(std::move(in_sock)) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
HTTPSession::~HTTPSession() |
|
|
HTTPSession::~HTTPSession() { |
|
|
{ |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Server::Data struct
|
|
|
// Server::Data struct
|
|
|
|
|
|
|
|
|
struct Jupiter::HTTP::Server::Data |
|
|
struct Jupiter::HTTP::Server::Data { |
|
|
{ |
|
|
|
|
|
/** Data */ |
|
|
/** Data */ |
|
|
Jupiter::ArrayList<Jupiter::HTTP::Server::Host> hosts; |
|
|
std::vector<std::unique_ptr<Jupiter::HTTP::Server::Host>> m_hosts; |
|
|
Jupiter::ArrayList<Socket> ports; |
|
|
std::vector<std::unique_ptr<Socket>> m_ports; |
|
|
Jupiter::ArrayList<HTTPSession> sessions; |
|
|
std::vector<std::unique_ptr<HTTPSession>> m_sessions; |
|
|
std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable
|
|
|
std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable
|
|
|
std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable
|
|
|
std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable
|
|
|
size_t max_request_size = 8192; // TODO: Config variable
|
|
|
size_t max_request_size = 8192; // TODO: Config variable
|
|
|
bool permit_keept_alive = true; // TODO: Config variable
|
|
|
bool permit_keept_alive = true; // TODO: Config variable
|
|
|
|
|
|
|
|
|
/** Foward functions */ |
|
|
/** Foward functions */ |
|
|
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content); |
|
|
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content); |
|
|
bool remove(const Jupiter::ReadableString &hostname); |
|
|
bool remove(const Jupiter::ReadableString &hostname); |
|
|
//bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path);
|
|
|
//bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path);
|
|
|
bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name); |
|
|
bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name); |
|
|
bool has(const Jupiter::ReadableString &hostname); |
|
|
bool has(const Jupiter::ReadableString &hostname); |
|
|
bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); |
|
|
bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); |
|
|
Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name); |
|
|
Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name); |
|
|
Content *find(const Jupiter::ReadableString &name); |
|
|
Content* find(const Jupiter::ReadableString &name); |
|
|
Content *find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); |
|
|
Content* find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name); |
|
|
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); |
|
|
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); |
|
|
Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); |
|
|
Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string); |
|
|
|
|
|
|
|
@ -297,54 +263,43 @@ struct Jupiter::HTTP::Server::Data |
|
|
|
|
|
|
|
|
// Data constructor
|
|
|
// Data constructor
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Data::Data() |
|
|
Jupiter::HTTP::Server::Data::Data() { |
|
|
{ |
|
|
|
|
|
// hosts[0] is always the "global" namespace.
|
|
|
// hosts[0] is always the "global" namespace.
|
|
|
Jupiter::HTTP::Server::Data::hosts.add(new Jupiter::HTTP::Server::Host(Jupiter::HTTP::Server::global_namespace)); |
|
|
m_hosts.push_back(std::make_unique<Host>(Jupiter::HTTP::Server::global_namespace)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Data destructor
|
|
|
// Data destructor
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Data::~Data() |
|
|
Jupiter::HTTP::Server::Data::~Data() { |
|
|
{ |
|
|
|
|
|
Jupiter::HTTP::Server::Data::hosts.emptyAndDelete(); |
|
|
|
|
|
Jupiter::HTTP::Server::Data::sessions.emptyAndDelete(); |
|
|
|
|
|
Jupiter::HTTP::Server::Data::ports.emptyAndDelete(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Data functions
|
|
|
// Data functions
|
|
|
|
|
|
|
|
|
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, Content *in_content) |
|
|
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, std::unique_ptr<Content> in_content) { |
|
|
{ |
|
|
|
|
|
Jupiter::ReferenceString path = in_path; |
|
|
Jupiter::ReferenceString path = in_path; |
|
|
Jupiter::ReferenceString dir_name; |
|
|
Jupiter::ReferenceString dir_name; |
|
|
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname); |
|
|
Jupiter::HTTP::Server::Host* host = find_host(hostname); |
|
|
|
|
|
|
|
|
if (host == nullptr) |
|
|
if (host == nullptr) { |
|
|
{ |
|
|
//host = new Jupiter::HTTP::Server::Host(hostname);
|
|
|
host = new Jupiter::HTTP::Server::Host(hostname); |
|
|
host = m_hosts.emplace_back(std::make_unique<Host>(hostname)).get(); |
|
|
Jupiter::HTTP::Server::Data::hosts.add(host); |
|
|
|
|
|
// OPTIMIZE: create directory tree and return.
|
|
|
// OPTIMIZE: create directory tree and return.
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
path.shiftRight(path.span('/')); |
|
|
path.shiftRight(path.span('/')); |
|
|
if (path.isEmpty()) |
|
|
if (path.isEmpty()) { |
|
|
host->content.add(in_content); |
|
|
host->content.push_back(std::move(in_content)); |
|
|
else |
|
|
} |
|
|
host->hook(path, in_content); |
|
|
else { |
|
|
|
|
|
host->hook(path, std::move(in_content)); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) |
|
|
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) { |
|
|
{ |
|
|
|
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); |
|
|
for (auto host_itr = m_hosts.begin(); host_itr != m_hosts.end(); ++host_itr) { |
|
|
Jupiter::HTTP::Server::Host *host; |
|
|
if (name_checksum == (*host_itr)->name_checksum && (*host_itr)->name.equalsi(hostname)) { |
|
|
while (index != 0) |
|
|
m_hosts.erase(host_itr); |
|
|
{ |
|
|
|
|
|
host = Jupiter::HTTP::Server::Data::hosts.get(--index); |
|
|
|
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) |
|
|
|
|
|
{ |
|
|
|
|
|
delete Jupiter::HTTP::Server::Data::hosts.remove(index); |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -352,46 +307,34 @@ bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// name: path/to/resource OR path/
|
|
|
// name: path/to/resource OR path/
|
|
|
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) |
|
|
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
Jupiter::HTTP::Server::Host *host = find_host(hostname); |
|
|
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname); |
|
|
if (host == nullptr) { |
|
|
if (host == nullptr) |
|
|
|
|
|
return false; |
|
|
return false; |
|
|
|
|
|
} |
|
|
return host->remove(path, name); |
|
|
return host->remove(path, name); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) |
|
|
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) { |
|
|
{ |
|
|
|
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); |
|
|
for (const auto& host : m_hosts) { |
|
|
Jupiter::HTTP::Server::Host *host; |
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) { |
|
|
while (index != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
host = Jupiter::HTTP::Server::Data::hosts.get(--index); |
|
|
|
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) |
|
|
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
|
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
unsigned int name_checksum = hostname.calcChecksumi(); |
|
|
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); |
|
|
for (const auto& host : m_hosts) { |
|
|
Jupiter::HTTP::Server::Host *host; |
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) { |
|
|
while (index != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
host = Jupiter::HTTP::Server::Data::hosts.get(--index); |
|
|
|
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) |
|
|
|
|
|
{ |
|
|
|
|
|
name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive
|
|
|
name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive
|
|
|
index = host->content.size(); |
|
|
for (const auto& content : host->content) { |
|
|
Jupiter::HTTP::Server::Content *content; |
|
|
if (name_checksum == content->name_checksum && content->name.equals(name)) { // switch to equalsi to make case-insensitive
|
|
|
while (index != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
content = host->content.get(--index); |
|
|
|
|
|
if (name_checksum == content->name_checksum && content->name.equals(name)) // switch to equalsi to make case-insensitive
|
|
|
|
|
|
return true; |
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
@ -399,60 +342,53 @@ bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, c |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) |
|
|
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
|
|
|
unsigned int name_checksum = name.calcChecksumi(); |
|
|
unsigned int name_checksum = name.calcChecksumi(); |
|
|
size_t index = Jupiter::HTTP::Server::Data::hosts.size(); |
|
|
for (const auto& host : m_hosts) { |
|
|
Jupiter::HTTP::Server::Host *host; |
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(name)) { |
|
|
while (index != 0) |
|
|
return host.get(); |
|
|
{ |
|
|
} |
|
|
host = Jupiter::HTTP::Server::Data::hosts.get(--index); |
|
|
|
|
|
if (name_checksum == host->name_checksum && host->name.equalsi(name)) |
|
|
|
|
|
return host; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return nullptr; |
|
|
return nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) |
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
return m_hosts[0]->find(name); |
|
|
return Jupiter::HTTP::Server::Data::hosts.get(0)->find(name); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) |
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
Jupiter::HTTP::Server::Host *host = find_host(hostname); |
|
|
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname); |
|
|
|
|
|
if (host == nullptr) |
|
|
if (host == nullptr) |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
|
|
|
|
|
|
return host->find(name); |
|
|
return host->find(name); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
Jupiter::HTTP::Server::Content *content = find(name); |
|
|
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(name); |
|
|
|
|
|
if (content == nullptr) |
|
|
if (content == nullptr) |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
|
|
|
|
|
|
return content->execute(query_string); |
|
|
return content->execute(query_string); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
Jupiter::HTTP::Server::Content *content = find(hostname, name); |
|
|
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(hostname, name); |
|
|
|
|
|
if (content == nullptr) |
|
|
if (content == nullptr) |
|
|
return nullptr; |
|
|
return nullptr; |
|
|
|
|
|
|
|
|
return content->execute(query_string); |
|
|
return content->execute(query_string); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
char *html_time() |
|
|
char* html_time() { |
|
|
{ |
|
|
|
|
|
time_t rawtime = time(0); |
|
|
time_t rawtime = time(0); |
|
|
char *rtime = new char[64]; |
|
|
char *rtime = new char[64]; |
|
|
strftime(rtime, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime)); |
|
|
strftime(rtime, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime)); |
|
|
return rtime; |
|
|
return rtime; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) { |
|
|
{ |
|
|
|
|
|
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL)); |
|
|
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL)); |
|
|
HTTPCommand command = HTTPCommand::NONE_SPECIFIED; |
|
|
HTTPCommand command = HTTPCommand::NONE_SPECIFIED; |
|
|
Content *content = nullptr; |
|
|
Content *content = nullptr; |
|
@ -589,7 +525,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
session.request.shiftRight(get_line_offset(index)); |
|
|
session.request.shiftRight(get_line_offset(index)); |
|
|
|
|
|
|
|
|
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received
|
|
|
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received
|
|
|
return Jupiter::HTTP::Server::Data::process_request(session); |
|
|
return process_request(session); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -600,12 +536,12 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
{ |
|
|
{ |
|
|
first_token.truncate(1); // trim trailing ':'
|
|
|
first_token.truncate(1); // trim trailing ':'
|
|
|
if (first_token.equalsi("HOST"_jrs)) |
|
|
if (first_token.equalsi("HOST"_jrs)) |
|
|
session.host = Jupiter::HTTP::Server::Data::find_host(line.getWord(1, " ")); |
|
|
session.host = find_host(line.getWord(1, " ")); |
|
|
else if (first_token.equalsi("CONNECTION"_jrs)) |
|
|
else if (first_token.equalsi("CONNECTION"_jrs)) |
|
|
{ |
|
|
{ |
|
|
Jupiter::ReferenceString connection_type = line.getWord(1, " "); |
|
|
Jupiter::ReferenceString connection_type = line.getWord(1, " "); |
|
|
if (connection_type.equalsi("keep-alive"_jrs)) |
|
|
if (connection_type.equalsi("keep-alive"_jrs)) |
|
|
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; |
|
|
session.keep_alive = permit_keept_alive; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else // command
|
|
|
else // command
|
|
@ -619,7 +555,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
if (span == Jupiter::INVALID_INDEX) |
|
|
if (span == Jupiter::INVALID_INDEX) |
|
|
{ |
|
|
{ |
|
|
if (session.host == nullptr) |
|
|
if (session.host == nullptr) |
|
|
content = Jupiter::HTTP::Server::Data::find(query_string); |
|
|
content = find(query_string); |
|
|
else |
|
|
else |
|
|
content = session.host->find(query_string); |
|
|
content = session.host->find(query_string); |
|
|
query_string.erase(); |
|
|
query_string.erase(); |
|
@ -627,7 +563,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
if (session.host == nullptr) |
|
|
if (session.host == nullptr) |
|
|
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); |
|
|
content = find(query_string.substring(size_t{ 0 }, span)); |
|
|
else |
|
|
else |
|
|
content = session.host->find(query_string.substring(size_t{ 0 }, span)); |
|
|
content = session.host->find(query_string.substring(size_t{ 0 }, span)); |
|
|
query_string.shiftRight(span + 1); |
|
|
query_string.shiftRight(span + 1); |
|
@ -640,7 +576,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
else if (protocol_str.equalsi("http/1.1"_jrs)) |
|
|
else if (protocol_str.equalsi("http/1.1"_jrs)) |
|
|
{ |
|
|
{ |
|
|
session.version = HTTPVersion::HTTP_1_1; |
|
|
session.version = HTTPVersion::HTTP_1_1; |
|
|
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; |
|
|
session.keep_alive = permit_keept_alive; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (first_token.equals("HEAD"_jrs)) |
|
|
else if (first_token.equals("HEAD"_jrs)) |
|
@ -652,7 +588,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
if (span == Jupiter::INVALID_INDEX) |
|
|
if (span == Jupiter::INVALID_INDEX) |
|
|
{ |
|
|
{ |
|
|
if (session.host == nullptr) |
|
|
if (session.host == nullptr) |
|
|
content = Jupiter::HTTP::Server::Data::find(query_string); |
|
|
content = find(query_string); |
|
|
else |
|
|
else |
|
|
content = session.host->find(query_string); |
|
|
content = session.host->find(query_string); |
|
|
query_string.erase(); |
|
|
query_string.erase(); |
|
@ -660,7 +596,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
if (session.host == nullptr) |
|
|
if (session.host == nullptr) |
|
|
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); |
|
|
content = find(query_string.substring(size_t{ 0 }, span)); |
|
|
else |
|
|
else |
|
|
content = session.host->find(query_string.substring(size_t{ 0 }, span)); |
|
|
content = session.host->find(query_string.substring(size_t{ 0 }, span)); |
|
|
query_string.shiftRight(span + 1); |
|
|
query_string.shiftRight(span + 1); |
|
@ -673,7 +609,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
else if (protocol_str.equalsi("http/1.1"_jrs)) |
|
|
else if (protocol_str.equalsi("http/1.1"_jrs)) |
|
|
{ |
|
|
{ |
|
|
session.version = HTTPVersion::HTTP_1_1; |
|
|
session.version = HTTPVersion::HTTP_1_1; |
|
|
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; |
|
|
session.keep_alive = permit_keept_alive; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
@ -687,188 +623,172 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) |
|
|
|
|
|
|
|
|
// Server constructors
|
|
|
// Server constructors
|
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Server() |
|
|
Jupiter::HTTP::Server::Server() { |
|
|
{ |
|
|
m_data = new Data(); |
|
|
Jupiter::HTTP::Server::data_ = new Jupiter::HTTP::Server::Data(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source) |
|
|
Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source) { |
|
|
{ |
|
|
m_data = source.m_data; |
|
|
Jupiter::HTTP::Server::data_ = source.data_; |
|
|
source.m_data = new Data(); |
|
|
source.data_ = new Jupiter::HTTP::Server::Data(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::~Server() |
|
|
Jupiter::HTTP::Server::~Server() { |
|
|
{ |
|
|
delete m_data; |
|
|
delete Jupiter::HTTP::Server::data_; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Server functions
|
|
|
// Server functions
|
|
|
|
|
|
|
|
|
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, Content *content) |
|
|
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, std::unique_ptr<Content> content) { |
|
|
{ |
|
|
return m_data->hook(host, name, std::move(content)); |
|
|
return Jupiter::HTTP::Server::data_->hook(host, name, content); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) |
|
|
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) { |
|
|
{ |
|
|
return m_data->remove(host); |
|
|
return Jupiter::HTTP::Server::data_->remove(host); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path)
|
|
|
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path) {
|
|
|
{ |
|
|
return m_data->remove(host, path); |
|
|
return Jupiter::HTTP::Server::data_->remove(host, path); |
|
|
|
|
|
}*/ |
|
|
}*/ |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) |
|
|
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
return m_data->remove(host, path, name); |
|
|
return Jupiter::HTTP::Server::data_->remove(host, path, name); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) |
|
|
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) { |
|
|
{ |
|
|
return m_data->has(host); |
|
|
return Jupiter::HTTP::Server::data_->has(host); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) |
|
|
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
return m_data->has(host, name); |
|
|
return Jupiter::HTTP::Server::data_->has(host, name); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) |
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
return m_data->find(name); |
|
|
return Jupiter::HTTP::Server::data_->find(name); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) |
|
|
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) { |
|
|
{ |
|
|
return m_data->find(host, name); |
|
|
return Jupiter::HTTP::Server::data_->find(host, name); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
return m_data->execute(name, query_string); |
|
|
return Jupiter::HTTP::Server::data_->execute(name, query_string); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) |
|
|
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) { |
|
|
{ |
|
|
return m_data->execute(host, name, query_string); |
|
|
return Jupiter::HTTP::Server::data_->execute(host, name, query_string); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) |
|
|
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) { |
|
|
{ |
|
|
auto socket = std::make_unique<Jupiter::TCPSocket>(); |
|
|
Jupiter::TCPSocket *socket = new Jupiter::TCPSocket(); |
|
|
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) { |
|
|
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) |
|
|
|
|
|
{ |
|
|
|
|
|
socket->setBlocking(false); |
|
|
socket->setBlocking(false); |
|
|
Jupiter::HTTP::Server::data_->ports.add(socket); |
|
|
m_data->m_ports.push_back(std::move(socket)); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
delete socket; |
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) |
|
|
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) { |
|
|
{ |
|
|
auto socket = std::make_unique<Jupiter::SecureTCPSocket>(); |
|
|
Jupiter::SecureTCPSocket *socket = new Jupiter::SecureTCPSocket(); |
|
|
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) { |
|
|
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) |
|
|
m_data->m_ports.push_back(std::move(socket)); |
|
|
{ |
|
|
|
|
|
Jupiter::HTTP::Server::data_->ports.add(socket); |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
delete socket; |
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int Jupiter::HTTP::Server::think() |
|
|
int Jupiter::HTTP::Server::think() { |
|
|
{ |
|
|
|
|
|
Jupiter::Socket *socket; |
|
|
|
|
|
HTTPSession *session; |
|
|
|
|
|
|
|
|
|
|
|
// Process existing clients
|
|
|
// Process existing clients
|
|
|
size_t index = Jupiter::HTTP::Server::data_->sessions.size(); |
|
|
auto sessions_end = m_data->m_sessions.end(); |
|
|
while (index != 0) |
|
|
for (auto itr = m_data->m_sessions.begin(); itr != sessions_end;) { |
|
|
{ |
|
|
auto& session = *itr; |
|
|
session = Jupiter::HTTP::Server::data_->sessions.get(--index); |
|
|
if (session->sock.isShutdown()) { |
|
|
if (session->sock.isShutdown()) |
|
|
if (session->sock.recv() == 0) { |
|
|
{ |
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
if (session->sock.recv() == 0) |
|
|
continue; |
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
} |
|
|
} |
|
|
} |
|
|
else if ((std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->keep_alive_session_timeout) |
|
|
else if ((std::chrono::steady_clock::now() > session->last_active + m_data->keep_alive_session_timeout) |
|
|
|| (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->session_timeout)) |
|
|
|| (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + m_data->session_timeout)) { |
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
//session->sock.shutdown();
|
|
|
continue; |
|
|
else if (session->sock.recv() > 0) |
|
|
} |
|
|
{ |
|
|
else if (session->sock.recv() > 0) { |
|
|
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); |
|
|
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); |
|
|
if (session->request.size() + sock_buffer.size() <= Jupiter::HTTP::Server::data_->max_request_size) // accept
|
|
|
if (session->request.size() + sock_buffer.size() <= m_data->max_request_size) { // accept
|
|
|
{ |
|
|
|
|
|
session->request += sock_buffer; |
|
|
session->request += sock_buffer; |
|
|
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request
|
|
|
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
|
|
|
{ |
|
|
|
|
|
session->last_active = std::chrono::steady_clock::now(); |
|
|
session->last_active = std::chrono::steady_clock::now(); |
|
|
Jupiter::HTTP::Server::data_->process_request(*session); |
|
|
m_data->process_request(*session); |
|
|
if (session->keep_alive == false) // remove completed session
|
|
|
if (session->keep_alive == false) { // remove completed session
|
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
//session->sock.shutdown();
|
|
|
//session->sock.shutdown();
|
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// else // keep_alive: session not deleted
|
|
|
} |
|
|
} |
|
|
else if (session->request.size() == Jupiter::HTTP::Server::data_->max_request_size) // reject (full buffer)
|
|
|
else if (session->request.size() == m_data->max_request_size) { // reject (full buffer)
|
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// else // request not over: session not deleted
|
|
|
|
|
|
} |
|
|
|
|
|
else { // reject
|
|
|
|
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
|
|
|
continue; |
|
|
} |
|
|
} |
|
|
else // reject
|
|
|
|
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
|
|
|
} |
|
|
} |
|
|
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK) |
|
|
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK) { |
|
|
delete Jupiter::HTTP::Server::data_->sessions.remove(index); |
|
|
itr = m_data->m_sessions.erase(itr + 1); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
// else // EWOULDBLOCK: session not deleted
|
|
|
|
|
|
|
|
|
|
|
|
++itr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Process incoming clients
|
|
|
// Process incoming clients
|
|
|
index = Jupiter::HTTP::Server::data_->ports.size(); |
|
|
std::unique_ptr<Jupiter::Socket> socket; |
|
|
while (index != 0) |
|
|
for (auto& port : m_data->m_ports) { |
|
|
{ |
|
|
socket.reset(socket->accept()); |
|
|
socket = Jupiter::HTTP::Server::data_->ports.get(--index); |
|
|
if (socket != nullptr) { |
|
|
socket = socket->accept(); |
|
|
|
|
|
if (socket != nullptr) |
|
|
|
|
|
{ |
|
|
|
|
|
socket->setBlocking(false); |
|
|
socket->setBlocking(false); |
|
|
session = new HTTPSession(std::move(*socket)); |
|
|
auto session = std::make_unique<HTTPSession>(std::move(*socket)); |
|
|
if (session->sock.recv() > 0) // data received
|
|
|
if (session->sock.recv() > 0) { // data received
|
|
|
{ |
|
|
|
|
|
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); |
|
|
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); |
|
|
if (sock_buffer.size() < Jupiter::HTTP::Server::data_->max_request_size) // accept
|
|
|
if (sock_buffer.size() < m_data->max_request_size) { // accept
|
|
|
{ |
|
|
|
|
|
session->request = session->sock.getBuffer(); |
|
|
session->request = session->sock.getBuffer(); |
|
|
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request
|
|
|
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
|
|
|
{ |
|
|
m_data->process_request(*session); |
|
|
Jupiter::HTTP::Server::data_->process_request(*session); |
|
|
if (session->keep_alive) { // session will live for 30 seconds.
|
|
|
if (session->keep_alive) // session will live for 30 seconds.
|
|
|
m_data->m_sessions.push_back(std::move(session)); |
|
|
Jupiter::HTTP::Server::data_->sessions.add(session); |
|
|
} |
|
|
else // session completed
|
|
|
// else // session completed
|
|
|
delete session; |
|
|
} |
|
|
|
|
|
else { // store for more processing
|
|
|
|
|
|
m_data->m_sessions.push_back(std::move(session)); |
|
|
} |
|
|
} |
|
|
else // store for more processing
|
|
|
|
|
|
Jupiter::HTTP::Server::data_->sessions.add(session); |
|
|
|
|
|
} |
|
|
} |
|
|
else if (sock_buffer.size() == Jupiter::HTTP::Server::data_->max_request_size) |
|
|
else if (sock_buffer.size() == m_data->max_request_size) { |
|
|
{ |
|
|
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) { // reject (too large)
|
|
|
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) // reject (too large)
|
|
|
continue; |
|
|
delete session; |
|
|
|
|
|
else // accept (max size, completed request)
|
|
|
|
|
|
{ |
|
|
|
|
|
session->request = session->sock.getBuffer(); |
|
|
|
|
|
Jupiter::HTTP::Server::data_->process_request(*session); |
|
|
|
|
|
if (session->keep_alive) // session will live for 30 seconds.
|
|
|
|
|
|
Jupiter::HTTP::Server::data_->sessions.add(session); |
|
|
|
|
|
else // session completed
|
|
|
|
|
|
delete session; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// accept (max size, completed request)
|
|
|
|
|
|
session->request = session->sock.getBuffer(); |
|
|
|
|
|
m_data->process_request(*session); |
|
|
|
|
|
if (session->keep_alive) { // session will live for 30 seconds.
|
|
|
|
|
|
m_data->m_sessions.push_back(std::move(session)); |
|
|
|
|
|
} |
|
|
|
|
|
// else // session completed
|
|
|
} |
|
|
} |
|
|
else // reject (too large)
|
|
|
// else // reject (too large)
|
|
|
delete session; |
|
|
} |
|
|
|
|
|
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) { // store for more processing
|
|
|
|
|
|
m_data->m_sessions.push_back(std::move(session)); |
|
|
} |
|
|
} |
|
|
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) // store for more processing
|
|
|
|
|
|
Jupiter::HTTP::Server::data_->sessions.add(session); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
return 0; |
|
|