Arduino DLNA Server
HttpStreamedMultiOutput.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "HttpChunkWriter.h"
4 #include "HttpStreamedOutput.h"
5 #include "WiFi.h"
6 #include "basic/List.h"
7 #include "basic/Str.h"
8 
9 namespace tiny_dlna {
10 
28  public:
29  HttpStreamedMultiOutput(const char *mime, const char *startHtml = nullptr,
30  const char *endHtml = nullptr,
31  int maxHistoryLength = 0) {
32  DlnaLogger.log(DlnaInfo, "HttpStreamedMultiOutput");
33  this->start = startHtml;
34  this->end = endHtml;
35  this->mime_type = mime;
36  this->max_history_length = maxHistoryLength;
37  if (maxHistoryLength > 0) {
38  this->history = new Str(maxHistoryLength);
39  }
40  }
41 
42  // provides the mime type
43  virtual const char *mime() { return mime_type; }
44 
45  // checks if the client is valid
46  virtual bool isValid(WiFiClient &client) {
47  bool valid = client.connected();
48  return valid;
49  }
50 
51  // content that is written when the request is opened
52  virtual void open(WiFiClient &client) {
53  DlnaLogger.log(DlnaInfo, "HttpStreamedMultiOutput::open");
54  if (client.connected()) {
55  // create a copy
56  // we handle only valid clents
57  if (start != nullptr) {
58  int len = strlen(start);
59  writer.writeChunk(client, start, len);
60  }
61  if (history != nullptr && history->length() > 0) {
62  writer.writeChunk(client, history->c_str(), history->length());
63  }
64 
65  // add client to list of open clients
66  DlnaLogger.log(DlnaWarning, "new client");
67  clients.push_back(client);
68  }
69  }
70 
71  // checks if we have any open clients
72  virtual bool isOpen() {
73  cleanup();
74  for (auto i = clients.begin(); i != clients.end(); ++i) {
75  WiFiClient client = (*i);
76  if (isValid(client)) {
77  return true;
78  }
79  }
80  return false;
81  }
82 
83  // end processing by wr
84  virtual void close() {
85  for (auto i = clients.begin(); i != clients.end(); ++i) {
86  WiFiClient client = *i;
87  if (isValid(client)) {
88  if (end != nullptr) {
89  // send end to all clients
90  print(end);
91  }
92  writer.writeEnd(client);
93  }
94  }
95  cleanup();
96  }
97 
99  virtual int availableForWrite() { return isOpen() ? 1024 : 0; }
100 
101  // write the content to the HttpStreamedMultiOutput
102  virtual size_t write(uint8_t *content, int len) {
103  cleanup();
104  for (auto i = clients.begin(); i != clients.end(); ++i) {
105  WiFiClient client = *i;
106  if (isValid(client)) {
107  DlnaLogger.log(DlnaDebug, "HttpStreamedMultiOutput::write");
108  writer.writeChunk(client, (const char *)content, len);
109  }
110  }
111  return len;
112  }
113 
114  // writes a line
115  virtual size_t print(const char *str) {
116  cleanup();
117  int len = strlen(str);
118  for (auto i = clients.begin(); i != clients.end(); ++i) {
119  WiFiClient client = *i;
120  if (isValid(client)) {
121  DlnaLogger.log(DlnaDebug, "HttpStreamedMultiOutput::print");
122  writer.writeChunk(client, (const char *)str, len);
123  }
124  }
125  addHistory(str, false, len);
126  return len;
127  }
128 
129  // writes a line which terminates with a html line break
130  virtual size_t println(const char *str) {
131  cleanup();
132  int len = strlen(str);
133  for (auto i = clients.begin(); i != clients.end(); ++i) {
134  WiFiClient client = *i;
135  if (isValid(client)) {
136  DlnaLogger.log(DlnaDebug, "HttpStreamedMultiOutput::println");
137  writer.writeChunk(client, str, len, "<br>", 4);
138  }
139  }
140  addHistory(str, true, len);
141  return len;
142  }
143 
144  // actually we do nothing here - but some subclasses might
145  virtual void doLoop() {}
146 
147  protected:
150  Str *history = nullptr;
152  const char *start = nullptr;
153  const char *end = nullptr;
154  const char *mime_type = nullptr;
155  int id_value = 0;
156 
157  // clenaup closed clients
158  void cleanup() {
159  for (int pos = clients.size() - 1; pos >= 0; pos--) {
160  WiFiClient client = clients[pos];
161  if (!isValid(client)) {
162  DlnaLogger.log(DlnaWarning, "HttpStreamedMultiOutput::closed");
163  clients.erase(clients.begin() + pos);
164  }
165  }
166  }
167 
169  void onClose(WiFiClient &client) {
170  if (end != nullptr) {
171  DlnaLogger.log(DlnaInfo, "HttpStreamedMultiOutput::onClose");
172  int len = strlen(end);
173  writer.writeChunk(client, end, len);
174  }
175 
176  clients.push_back(client);
177  }
178 
180  void addHistory(const char *line, bool delimiter, int len) {
181  if (history != nullptr) {
182  int available = max_history_length - history->length();
183  // make space
184  while (len > available && history->length() > 0) {
185  int pos = history->indexOf("<br>");
186  if (pos >= 0) {
187  *history << (pos + 4);
188  } else {
189  history->clear();
190  }
191  available = max_history_length - history->length();
192  }
193  // add to history if it is not too big
194  if (len <= available) {
195  *history += line;
196  if (delimiter) {
197  *history += "<br>";
198  }
199  }
200  }
201  }
202 };
203 
204 } // namespace tiny_dlna
Writes the data chunked to the actual client.
Definition: HttpChunkWriter.h:12
int writeChunk(Client &client, const char *str, int len, const char *str1=nullptr, int len1=0)
Definition: HttpChunkWriter.h:14
void writeEnd(Client &client)
Definition: HttpChunkWriter.h:31
Generic HttpStreamedMultiOutput Class which handles multicast streaming. We can optionally define som...
Definition: HttpStreamedMultiOutput.h:27
void addHistory(const char *line, bool delimiter, int len)
adds the line to the history - removest oldest lines
Definition: HttpStreamedMultiOutput.h:180
const char * start
Definition: HttpStreamedMultiOutput.h:152
virtual void doLoop()
Definition: HttpStreamedMultiOutput.h:145
virtual const char * mime()
Definition: HttpStreamedMultiOutput.h:43
virtual bool isOpen()
Definition: HttpStreamedMultiOutput.h:72
const char * mime_type
Definition: HttpStreamedMultiOutput.h:154
List< WiFiClient > clients
Definition: HttpStreamedMultiOutput.h:149
virtual bool isValid(WiFiClient &client)
Definition: HttpStreamedMultiOutput.h:46
const char * end
Definition: HttpStreamedMultiOutput.h:153
virtual int availableForWrite()
Do not accept any writes if we are not connected.
Definition: HttpStreamedMultiOutput.h:99
int max_history_length
Definition: HttpStreamedMultiOutput.h:151
Str * history
Definition: HttpStreamedMultiOutput.h:150
virtual void open(WiFiClient &client)
Definition: HttpStreamedMultiOutput.h:52
virtual size_t write(uint8_t *content, int len)
Definition: HttpStreamedMultiOutput.h:102
void cleanup()
Definition: HttpStreamedMultiOutput.h:158
virtual void close()
Definition: HttpStreamedMultiOutput.h:84
virtual size_t println(const char *str)
Definition: HttpStreamedMultiOutput.h:130
int id_value
Definition: HttpStreamedMultiOutput.h:155
HttpChunkWriter writer
Definition: HttpStreamedMultiOutput.h:148
HttpStreamedMultiOutput(const char *mime, const char *startHtml=nullptr, const char *endHtml=nullptr, int maxHistoryLength=0)
Definition: HttpStreamedMultiOutput.h:29
void onClose(WiFiClient &client)
content that is written when the request is opened
Definition: HttpStreamedMultiOutput.h:169
virtual size_t print(const char *str)
Definition: HttpStreamedMultiOutput.h:115
Abstract class for handling streamed output.
Definition: HttpStreamedOutput.h:12
Iterator end()
Definition: List.h:257
size_t size()
Definition: List.h:272
bool push_back(T data)
Definition: List.h:128
bool erase(Iterator it)
Definition: List.h:233
Iterator begin()
Definition: List.h:252
void log(DlnaLogLevel current_level, const char *fmt...)
Print log message.
Definition: Logger.h:40
virtual int indexOf(const char c, int start=0)
Definition: StrView.h:267
virtual int length()
Definition: StrView.h:370
String implementation which keeps the data on the heap. We grow the allocated memory only if the copy...
Definition: Str.h:22
void clear() override
clears the string by setting the terminating 0 at the beginning
Definition: Str.h:164
const char * c_str()
provides the string value as const char*
Definition: Str.h:188
Definition: Allocator.h:6
@ DlnaDebug
Definition: Logger.h:16
@ DlnaInfo
Definition: Logger.h:16
@ DlnaWarning
Definition: Logger.h:16
LoggerClass DlnaLogger
Definition: Logger.cpp:5