Open Lighting Architecture  0.9.5
 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 <ola/win/CleanWinSock2.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  static const char CONTENT_TYPE_OCT[];
209 
210  // Expose the SelectServer
211  ola::io::SelectServer *SelectServer() { return &m_select_server; }
212 
213  private :
214  typedef struct {
215  std::string file_path;
216  std::string content_type;
217  } static_file_info;
218 
219  struct DescriptorState {
220  public:
221  explicit DescriptorState(ola::io::UnmanagedFileDescriptor *descriptor)
222  : descriptor(descriptor), read(0), write(0) {}
223 
225  uint8_t read : 1;
226  uint8_t write : 1;
227  uint8_t : 6;
228  };
229 
230  struct Descriptor_lt {
231  bool operator()(const DescriptorState *d1,
232  const DescriptorState *d2) const {
233  return d1->descriptor->ReadDescriptor() <
234  d2->descriptor->ReadDescriptor();
235  }
236  };
237 
238  typedef std::set<DescriptorState*, Descriptor_lt> SocketSet;
239 
240  struct MHD_Daemon *m_httpd;
241  ola::io::SelectServer m_select_server;
242  SocketSet m_sockets;
243 
244  std::map<std::string, BaseHTTPCallback*> m_handlers;
245  std::map<std::string, static_file_info> m_static_content;
246  BaseHTTPCallback *m_default_handler;
247  unsigned int m_port;
248  std::string m_data_dir;
249 
250  int ServeStaticContent(static_file_info *file_info,
251  HTTPResponse *response);
252 
253  void InsertSocket(bool is_readable, bool is_writeable, int fd);
254  void FreeSocket(DescriptorState *state);
255 
257 };
258 } // namespace http
259 } // namespace ola
260 #endif // INCLUDE_OLA_HTTP_HTTPSERVER_H_