Open Lighting Architecture  0.9.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HTTPServer.h
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * HTTPServer.h
17  * The Base HTTP Server class.
18  * Copyright (C) 2005 Simon Newton
19  */
20 
21 
22 #ifndef INCLUDE_OLA_HTTP_HTTPSERVER_H_
23 #define INCLUDE_OLA_HTTP_HTTPSERVER_H_
24 
25 #include <ola/Callback.h>
26 #include <ola/base/Macro.h>
27 #include <ola/io/Descriptor.h>
28 #include <ola/io/SelectServer.h>
29 #include <ola/thread/Thread.h>
30 #include <ola/web/Json.h>
31 // 0.4.6 of microhttp doesn't include stdarg so we do it here.
32 #include <stdarg.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35 #ifdef _WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <Winsock2.h>
38 #else
39 #include <sys/select.h>
40 #include <sys/socket.h>
41 #endif
42 #include <microhttpd.h>
43 #include <map>
44 #include <set>
45 #include <string>
46 #include <vector>
47 
48 namespace ola {
49 namespace http {
50 
51 /*
52  * Represents the HTTP request
53  */
54 class HTTPRequest {
55  public:
56  HTTPRequest(const std::string &url,
57  const std::string &method,
58  const std::string &version,
59  struct MHD_Connection *connection);
60  ~HTTPRequest();
61  bool Init();
62 
63  // accessors
64  const std::string Url() const { return m_url; }
65  const std::string Method() const { return m_method; }
66  const std::string Version() const { return m_version; }
67 
68  void AddHeader(const std::string &key, const std::string &value);
69  void AddPostParameter(const std::string &key, const std::string &value);
70  void ProcessPostData(const char *data, size_t *data_size);
71  const std::string GetHeader(const std::string &key) const;
72  bool CheckParameterExists(const std::string &key) const;
73  const std::string GetParameter(const std::string &key) const;
74  const std::string GetPostParameter(const std::string &key) const;
75 
76  bool InFlight() const { return m_in_flight; }
77  void SetInFlight() { m_in_flight = true; }
78 
79  private:
80  std::string m_url;
81  std::string m_method;
82  std::string m_version;
83  struct MHD_Connection *m_connection;
84  std::map<std::string, std::string> m_headers;
85  std::map<std::string, std::string> m_post_params;
86  struct MHD_PostProcessor *m_processor;
87  bool m_in_flight;
88 
89  static const unsigned int K_POST_BUFFER_SIZE = 1024;
90 
92 };
93 
94 
95 /*
96  * Represents the HTTP Response
97  */
98 class HTTPResponse {
99  public:
100  explicit HTTPResponse(struct MHD_Connection *connection):
101  m_connection(connection),
102  m_status_code(MHD_HTTP_OK) {}
103 
104  void Append(const std::string &data) { m_data.append(data); }
105  void SetContentType(const std::string &type);
106  void SetHeader(const std::string &key, const std::string &value);
107  void SetStatus(unsigned int status) { m_status_code = status; }
108  void SetNoCache();
109  int SendJson(const ola::web::JsonValue &json);
110  int Send();
111  struct MHD_Connection *Connection() const { return m_connection; }
112  private:
113  std::string m_data;
114  struct MHD_Connection *m_connection;
115  typedef std::multimap<std::string, std::string> HeadersMultiMap;
116  HeadersMultiMap m_headers;
117  unsigned int m_status_code;
118 
120 };
121 
122 
145  public:
148 
150  public:
151  // The port to listen on
152  uint16_t port;
153  // The root for content served with ServeStaticContent();
154  std::string data_dir;
155 
157  : port(0),
158  data_dir("") {
159  }
160  };
161 
162  explicit HTTPServer(const HTTPServerOptions &options);
163  virtual ~HTTPServer();
164  bool Init();
165  void *Run();
166  void Stop();
167  void UpdateSockets();
168 
173  void HandleHTTPIO() {}
174 
175  int DispatchRequest(const HTTPRequest *request, HTTPResponse *response);
176 
177  // Register a callback handler.
178  bool RegisterHandler(const std::string &path, BaseHTTPCallback *handler);
179 
180  // Register a file handler.
181  bool RegisterFile(const std::string &path,
182  const std::string &content_type);
183  bool RegisterFile(const std::string &path,
184  const std::string &file,
185  const std::string &content_type);
186  // Set the default handler.
187  void RegisterDefaultHandler(BaseHTTPCallback *handler);
188 
189  void Handlers(std::vector<std::string> *handlers) const;
190  const std::string DataDir() const { return m_data_dir; }
191 
192  // Return an error
193  int ServeError(HTTPResponse *response, const std::string &details="");
194  int ServeNotFound(HTTPResponse *response);
195  static int ServeRedirect(HTTPResponse *response, const std::string &location);
196 
197  // Return the contents of a file.
198  int ServeStaticContent(const std::string &path,
199  const std::string &content_type,
200  HTTPResponse *response);
201 
202  static const char CONTENT_TYPE_PLAIN[];
203  static const char CONTENT_TYPE_HTML[];
204  static const char CONTENT_TYPE_GIF[];
205  static const char CONTENT_TYPE_PNG[];
206  static const char CONTENT_TYPE_CSS[];
207  static const char CONTENT_TYPE_JS[];
208 
209  // Expose the SelectServer
210  ola::io::SelectServer *SelectServer() { return &m_select_server; }
211 
212  private :
213  typedef struct {
214  std::string file_path;
215  std::string content_type;
216  } static_file_info;
217 
218  struct DescriptorState {
219  public:
220  explicit DescriptorState(ola::io::UnmanagedFileDescriptor *descriptor)
221  : descriptor(descriptor), read(0), write(0) {}
222 
224  uint8_t read : 1;
225  uint8_t write : 1;
226  uint8_t : 6;
227  };
228 
229  struct Descriptor_lt {
230  bool operator()(const DescriptorState *d1,
231  const DescriptorState *d2) const {
232  return d1->descriptor->ReadDescriptor() <
233  d2->descriptor->ReadDescriptor();
234  }
235  };
236 
237  typedef std::set<DescriptorState*, Descriptor_lt> SocketSet;
238 
239  struct MHD_Daemon *m_httpd;
240  ola::io::SelectServer m_select_server;
241  SocketSet m_sockets;
242 
243  std::map<std::string, BaseHTTPCallback*> m_handlers;
244  std::map<std::string, static_file_info> m_static_content;
245  BaseHTTPCallback *m_default_handler;
246  unsigned int m_port;
247  std::string m_data_dir;
248 
249  int ServeStaticContent(static_file_info *file_info,
250  HTTPResponse *response);
251 
252  void InsertSocket(bool is_readable, bool is_writeable, int fd);
253  void FreeSocket(DescriptorState *state);
254 
256 };
257 } // namespace http
258 } // namespace ola
259 #endif // INCLUDE_OLA_HTTP_HTTPSERVER_H_