Arduino DLNA Server
Loading...
Searching...
No Matches
HttpServerUsingTasks.h
Go to the documentation of this file.
1#pragma once
2#include "basic/Logger.h"
3#include "concurrency/Task.h"
5
6namespace tiny_dlna {
7
26template <typename ClientType, typename ServerType>
27class HttpServerUsingTasks : public HttpServer<ClientType, ServerType> {
28 private:
29 bool is_started_ = false;
30
31 public:
32 HttpServerUsingTasks(ServerType& server, int bufferSize = 1024,
33 int taskStackSize = 1024 * 8, int taskPriority = 1)
34 : HttpServer<ClientType, ServerType>(server, bufferSize),
35 taskStackSize_(taskStackSize),
36 taskPriority_(taskPriority) {}
37
39
40 bool begin() override {
41 DlnaLogger.log(DlnaLogLevel::Debug, "HttpServerUsingTasks::begin()");
42 if (is_started_) {
43 DlnaLogger.log(
45 "HttpServerUsingTasks::begin() called but already started");
46 return false;
47 }
48
50 if (!result) {
51 DlnaLogger.log(
53 "HttpServerUsingTasks::begin() failed to start base HttpServer");
54 return false;
55 }
56 // Start the main accept loop in a background task
57 accept_task_.begin([this]() {
58 while (this->isActive()) {
59 if (this->server_ptr) {
60 ClientType client = this->server_ptr->accept();
61 if (client.connected()) {
62 client.setNoDelay(true); // disables Nagle
63 tasks_.emplace_back(
64 new Task("HttpClientTask", taskStackSize_, taskPriority_));
65 Task* clientTask = tasks_.back().get();
66 clientTask->begin([this, client, clientTask]() mutable {
67 this->handleClientTask(client);
68 delay(5);
69 DlnaLogger.log(DlnaLogLevel::Debug, "Removing client");
70 });
71 }
72 } else {
73 DlnaLogger.log(DlnaLogLevel::Error,
74 "HttpServerUsingTasks::begin() server_ptr is null");
75 }
76 delay(10); // avoid busy loop (Arduino delay)
77 }
78 });
79 is_started_ = true;
80 DlnaLogger.log(DlnaLogLevel::Info, "HttpServerUsingTasks started: %s",
81 result ? "true" : "false");
82 return result;
83 }
84
85 void end() override {
86 DlnaLogger.log(DlnaLogLevel::Debug, "HttpServerUsingTasks::end()");
87 if (!is_started_) return;
88 accept_task_.end();
89 for (auto& t : tasks_) {
90 t->end();
91 }
92 tasks_.clear();
94 is_started_ = false;
95 }
96
97 bool doLoop() override { return true; }
98
99 protected:
100 void handleClientTask(ClientType& client) {
101 DlnaLogger.log(DlnaLogLevel::Debug,
102 "HttpServerUsingTasks: handling new client");
103 // Create a dedicated handler for this client
104 while (client.connected()) {
106 handler.readHttpHeader();
107 onRequest(handler.requestHeader().urlPath(), handler);
108 }
109
110 DlnaLogger.log(DlnaLogLevel::Debug,
111 "HttpServerUsingTasks: client disconnected");
112 }
113
114 void removeTask(Task* task) {
115 auto it = std::remove_if(
116 tasks_.begin(), tasks_.end(),
117 [task](const std::unique_ptr<Task>& t) { return t.get() == task; });
118 tasks_.erase(it, tasks_.end());
119 }
120
122 std::vector<std::unique_ptr<Task>> tasks_;
125
127 bool onRequest(const char* path, HttpClientHandler<ClientType>& handler) {
128 DlnaLogger.log(DlnaLogLevel::Info, "Serving at %s", path);
129
130 bool result = false;
131 // check in registered handlers
132 StrView pathStr = StrView(path);
133 pathStr.replace("//", "/"); // TODO investiage why we get //
134 for (auto handler_line_ptr : this->handler_collection) {
135 DlnaLogger.log(DlnaLogLevel::Debug, "onRequest: %s %s vs: %s %s %s", path,
136 methods[handler.requestHeader().method()],
137 this->nullstr(handler_line_ptr->path.c_str()),
138 methods[handler_line_ptr->method],
139 this->nullstr(handler_line_ptr->mime));
140
141 if (pathStr.matches(handler_line_ptr->path.c_str()) &&
142 handler.requestHeader().method() == handler_line_ptr->method &&
143 this->matchesMime(this->nullstr(handler_line_ptr->mime),
144 this->nullstr(handler.requestHeader().accept()))) {
145 // call registed handler function
146 DlnaLogger.log(DlnaLogLevel::Debug, "onRequest %s", "->found",
147 this->nullstr(handler_line_ptr->path.c_str()));
148 handler_line_ptr->fn(handler, this, path, handler_line_ptr);
149 result = true;
150 break;
151 }
152 }
153
154 if (!result) {
155 DlnaLogger.log(DlnaLogLevel::Error, "Request %s not available", path);
156 }
157
158 return result;
159 }
160};
161
162} // namespace tiny_dlna
Handles HTTP client connections and responses for the DLNA HTTP server.
Definition: HttpClientHandler.h:30
HttpRequestHeader & requestHeader()
Definition: HttpClientHandler.h:192
void readHttpHeader()
Reads the http header info from the client.
Definition: HttpClientHandler.h:42
const char * accept()
Definition: HttpHeader.h:221
TinyMethodID method()
Definition: HttpHeader.h:219
const char * urlPath()
Definition: HttpHeader.h:215
Experimental HTTP server implementation that handles each client in a separate task.
Definition: HttpServerUsingTasks.h:27
Task accept_task_
Definition: HttpServerUsingTasks.h:121
void removeTask(Task *task)
Definition: HttpServerUsingTasks.h:114
int taskStackSize_
Definition: HttpServerUsingTasks.h:123
void handleClientTask(ClientType &client)
Definition: HttpServerUsingTasks.h:100
int taskPriority_
Definition: HttpServerUsingTasks.h:124
~HttpServerUsingTasks()
Definition: HttpServerUsingTasks.h:38
HttpServerUsingTasks(ServerType &server, int bufferSize=1024, int taskStackSize=1024 *8, int taskPriority=1)
Definition: HttpServerUsingTasks.h:32
std::vector< std::unique_ptr< Task > > tasks_
Definition: HttpServerUsingTasks.h:122
bool doLoop() override
Process server loop.
Definition: HttpServerUsingTasks.h:97
void end() override
Definition: HttpServerUsingTasks.h:85
bool begin() override
Definition: HttpServerUsingTasks.h:40
bool onRequest(const char *path, HttpClientHandler< ClientType > &handler)
processing logic
Definition: HttpServerUsingTasks.h:127
Header-only HTTP server wrapper that registers callback handlers.
Definition: HttpServer.h:37
bool isActive() override
Definition: HttpServer.h:299
ServerType * server_ptr
Definition: HttpServer.h:339
void end() override
stops the server_ptr
Definition: HttpServer.h:69
bool begin() override
Starts the server.
Definition: HttpServer.h:61
A simple wrapper to provide string functions on char*. If the underlying char* is a const we do not a...
Definition: StrView.h:18
virtual bool matches(const char *pattern)
Definition: StrView.h:207
virtual bool replace(const char *toReplace, const int replaced)
Replaces the first instance of toReplace with replaced.
Definition: StrView.h:395
FreeRTOS task.
Definition: TaskRTOS.h:23
bool begin(std::function< void()> process)
Definition: TaskRTOS.h:45
Definition: Allocator.h:13
const char * methods[]
Definition: HttpHeader.h:50