winlin

implements the http stream module.

1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#include <srs_app_http_conn.hpp>  
25 -  
26 -#ifdef SRS_HTTP_SERVER  
27 -  
28 -#include <sstream>  
29 -using namespace std;  
30 -  
31 -#include <sys/types.h>  
32 -#include <sys/stat.h>  
33 -#include <fcntl.h>  
34 -  
35 -#include <srs_kernel_log.hpp>  
36 -#include <srs_kernel_error.hpp>  
37 -#include <srs_app_socket.hpp>  
38 -#include <srs_app_http.hpp>  
39 -#include <srs_core_autofree.hpp>  
40 -#include <srs_app_json.hpp>  
41 -#include <srs_app_config.hpp>  
42 -  
43 -SrsHttpRoot::SrsHttpRoot()  
44 -{  
45 - // TODO: FIXME: support reload vhosts.  
46 -}  
47 -  
48 -SrsHttpRoot::~SrsHttpRoot()  
49 -{  
50 -}  
51 -  
52 -int SrsHttpRoot::initialize()  
53 -{  
54 - int ret = ERROR_SUCCESS;  
55 -  
56 - // add root  
57 - handlers.push_back(new SrsHttpVhost("__http__", "/", _srs_config->get_http_stream_dir()));  
58 -  
59 - // add other virtual path  
60 - SrsConfDirective* root = _srs_config->get_root();  
61 - for (int i = 0; i < (int)root->directives.size(); i++) {  
62 - SrsConfDirective* conf = root->at(i);  
63 -  
64 - if (!conf->is_vhost()) {  
65 - continue;  
66 - }  
67 -  
68 - std::string vhost = conf->arg0();  
69 - if (!_srs_config->get_vhost_http_enabled(vhost)) {  
70 - continue;  
71 - }  
72 -  
73 - std::string mount = _srs_config->get_vhost_http_mount(vhost);  
74 - std::string dir = _srs_config->get_vhost_http_dir(vhost);  
75 -  
76 - handlers.push_back(new SrsHttpVhost(vhost, mount, dir));  
77 - }  
78 -  
79 - return ret;  
80 -}  
81 -  
82 -bool SrsHttpRoot::can_handle(const char* path, int length, const char** pchild)  
83 -{  
84 - // reset the child path to path,  
85 - // for child to reparse the path.  
86 - *pchild = path;  
87 -  
88 - // only compare the first char.  
89 - return srs_path_equals("/", path, 1);  
90 -}  
91 -  
92 -bool SrsHttpRoot::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)  
93 -{  
94 - if (!SrsHttpHandler::is_handler_valid(req, status_code, reason_phrase)) {  
95 - return false;  
96 - }  
97 -  
98 - if (req->match()->matched_url.length() != 1) {  
99 - status_code = HTTP_NotFound;  
100 - reason_phrase = HTTP_NotFound_str;  
101 - return false;  
102 - }  
103 -  
104 - return true;  
105 -}  
106 -  
107 -int SrsHttpRoot::do_process_request(SrsSocket* skt, SrsHttpMessage* req)  
108 -{  
109 - std::stringstream ss;  
110 -  
111 - ss << JOBJECT_START  
112 - << JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT  
113 - << JFIELD_ORG("urls", JOBJECT_START);  
114 -  
115 - vector<SrsHttpHandler*>::iterator it;  
116 - for (it = handlers.begin(); it != handlers.end(); ++it) {  
117 - SrsHttpVhost* handler = dynamic_cast<SrsHttpVhost*>(*it);  
118 - srs_assert(handler);  
119 -  
120 - ss << JFIELD_ORG(handler->mount(), JOBJECT_START)  
121 - << JFIELD_STR("mount", handler->mount()) << JFIELD_CONT  
122 - << JFIELD_STR("vhost", handler->vhost()) << JFIELD_CONT  
123 - << JFIELD_STR("dir", handler->dir())  
124 - << JOBJECT_END;  
125 -  
126 - if (it + 1 != handlers.end()) {  
127 - ss << JFIELD_CONT;  
128 - }  
129 - }  
130 -  
131 - ss << JOBJECT_END  
132 - << JOBJECT_END;  
133 -  
134 - return res_json(skt, req, ss.str());  
135 -}  
136 -  
137 -SrsHttpVhost::SrsHttpVhost(std::string vhost, std::string mount, std::string dir)  
138 -{  
139 - _vhost = vhost;  
140 - _mount = mount;  
141 - _dir = dir;  
142 -}  
143 -  
144 -SrsHttpVhost::~SrsHttpVhost()  
145 -{  
146 -}  
147 -  
148 -bool SrsHttpVhost::can_handle(const char* path, int length, const char** /*pchild*/)  
149 -{  
150 - int min_match = srs_min(length, (int)_mount.length());  
151 - return srs_path_equals(_mount.c_str(), path, min_match);  
152 -}  
153 -  
154 -bool SrsHttpVhost::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)  
155 -{  
156 - std::string fullpath = _dir + "/" + req->match()->unmatched_url;  
157 - if (req->match()->unmatched_url.empty()) {  
158 - fullpath += req->match()->matched_url;  
159 - }  
160 -  
161 - if (::access(fullpath.c_str(), F_OK | R_OK) < 0) {  
162 - srs_warn("check file %s does not exists", fullpath.c_str());  
163 -  
164 - status_code = HTTP_NotFound;  
165 - reason_phrase = HTTP_NotFound_str;  
166 - return false;  
167 - }  
168 -  
169 - return true;  
170 -}  
171 -  
172 -int SrsHttpVhost::do_process_request(SrsSocket* skt, SrsHttpMessage* req)  
173 -{  
174 - int ret = ERROR_SUCCESS;  
175 -  
176 - std::string fullpath = _dir + "/" + req->match()->unmatched_url;  
177 - if (req->match()->unmatched_url.empty()) {  
178 - fullpath += req->match()->matched_url;  
179 - }  
180 -  
181 - if (srs_string_ends_with(fullpath, "/")) {  
182 - fullpath += "index.html";  
183 - }  
184 -  
185 - int fd = ::open(fullpath.c_str(), O_RDONLY);  
186 - if (fd < 0) {  
187 - ret = ERROR_HTTP_OPEN_FILE;  
188 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
189 - return ret;  
190 - }  
191 -  
192 - int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);  
193 - ::lseek(fd, 0, SEEK_SET);  
194 -  
195 - char* buf = new char[length];  
196 - SrsAutoFree(char, buf, true);  
197 -  
198 - if (::read(fd, buf, length) < 0) {  
199 - ::close(fd);  
200 - ret = ERROR_HTTP_READ_FILE;  
201 - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);  
202 - return ret;  
203 - }  
204 - ::close(fd);  
205 -  
206 - std::string str;  
207 - str.append(buf, length);  
208 -  
209 - if (srs_string_ends_with(fullpath, ".ts")) {  
210 - return res_mpegts(skt, req, str);  
211 - } else if (srs_string_ends_with(fullpath, ".m3u8")) {  
212 - return res_m3u8(skt, req, str);  
213 - } else {  
214 - return res_text(skt, req, str);  
215 - }  
216 -  
217 - return ret;  
218 -}  
219 -  
220 -string SrsHttpVhost::vhost()  
221 -{  
222 - return _vhost;  
223 -}  
224 -  
225 -string SrsHttpVhost::mount()  
226 -{  
227 - return _mount;  
228 -}  
229 -  
230 -string SrsHttpVhost::dir()  
231 -{  
232 - return _dir;  
233 -}  
234 -  
235 -SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)  
236 - : SrsConnection(srs_server, client_stfd)  
237 -{  
238 - parser = new SrsHttpParser();  
239 - handler = _handler;  
240 - requires_crossdomain = false;  
241 -}  
242 -  
243 -SrsHttpConn::~SrsHttpConn()  
244 -{  
245 - srs_freep(parser);  
246 -}  
247 -  
248 -int SrsHttpConn::do_cycle()  
249 -{  
250 - int ret = ERROR_SUCCESS;  
251 -  
252 - if ((ret = get_peer_ip()) != ERROR_SUCCESS) {  
253 - srs_error("get peer ip failed. ret=%d", ret);  
254 - return ret;  
255 - }  
256 - srs_trace("http get peer ip success. ip=%s", ip);  
257 -  
258 - // initialize parser  
259 - if ((ret = parser->initialize(HTTP_REQUEST)) != ERROR_SUCCESS) {  
260 - srs_error("http initialize http parser failed. ret=%d", ret);  
261 - return ret;  
262 - }  
263 -  
264 - // underlayer socket  
265 - SrsSocket skt(stfd);  
266 -  
267 - // process http messages.  
268 - for (;;) {  
269 - SrsHttpMessage* req = NULL;  
270 -  
271 - // get a http message  
272 - if ((ret = parser->parse_message(&skt, &req)) != ERROR_SUCCESS) {  
273 - return ret;  
274 - }  
275 -  
276 - // if SUCCESS, always NOT-NULL and completed message.  
277 - srs_assert(req);  
278 - srs_assert(req->is_complete());  
279 -  
280 - // always free it in this scope.  
281 - SrsAutoFree(SrsHttpMessage, req, false);  
282 -  
283 - // ok, handle http request.  
284 - if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) {  
285 - return ret;  
286 - }  
287 - }  
288 -  
289 - return ret;  
290 -}  
291 -  
292 -int SrsHttpConn::process_request(SrsSocket* skt, SrsHttpMessage* req)  
293 -{  
294 - int ret = ERROR_SUCCESS;  
295 -  
296 - // parse uri to schema/server:port/path?query  
297 - if ((ret = req->parse_uri()) != ERROR_SUCCESS) {  
298 - return ret;  
299 - }  
300 -  
301 - srs_trace("http request parsed, method=%d, url=%s, content-length=%"PRId64"",  
302 - req->method(), req->url().c_str(), req->content_length());  
303 -  
304 - // TODO: maybe need to parse the url.  
305 - std::string url = req->path();  
306 -  
307 - SrsHttpHandlerMatch* p = NULL;  
308 - if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {  
309 - srs_warn("failed to find the best match handler for url. ret=%d", ret);  
310 - return ret;  
311 - }  
312 -  
313 - // if success, p and pstart should be valid.  
314 - srs_assert(p);  
315 - srs_assert(p->handler);  
316 - srs_assert(p->matched_url.length() <= url.length());  
317 - srs_info("best match handler, matched_url=%s", p->matched_url.c_str());  
318 -  
319 - req->set_match(p);  
320 - req->set_requires_crossdomain(requires_crossdomain);  
321 -  
322 - // use handler to process request.  
323 - if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {  
324 - srs_warn("handler failed to process http request. ret=%d", ret);  
325 - return ret;  
326 - }  
327 -  
328 - if (req->requires_crossdomain()) {  
329 - requires_crossdomain = true;  
330 - }  
331 -  
332 - return ret;  
333 -}  
334 -  
335 -#endif 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_app_http_conn.hpp>
  25 +
  26 +#ifdef SRS_HTTP_SERVER
  27 +
  28 +#include <sstream>
  29 +using namespace std;
  30 +
  31 +#include <sys/types.h>
  32 +#include <sys/stat.h>
  33 +#include <fcntl.h>
  34 +
  35 +#include <srs_kernel_log.hpp>
  36 +#include <srs_kernel_error.hpp>
  37 +#include <srs_app_socket.hpp>
  38 +#include <srs_app_http.hpp>
  39 +#include <srs_core_autofree.hpp>
  40 +#include <srs_app_json.hpp>
  41 +#include <srs_app_config.hpp>
  42 +
  43 +SrsHttpRoot::SrsHttpRoot()
  44 +{
  45 + // TODO: FIXME: support reload vhosts.
  46 +}
  47 +
  48 +SrsHttpRoot::~SrsHttpRoot()
  49 +{
  50 +}
  51 +
  52 +int SrsHttpRoot::initialize()
  53 +{
  54 + int ret = ERROR_SUCCESS;
  55 +
  56 + // add root
  57 + handlers.push_back(new SrsHttpVhost("__http__", "/", _srs_config->get_http_stream_dir()));
  58 +
  59 + // add other virtual path
  60 + SrsConfDirective* root = _srs_config->get_root();
  61 + for (int i = 0; i < (int)root->directives.size(); i++) {
  62 + SrsConfDirective* conf = root->at(i);
  63 +
  64 + if (!conf->is_vhost()) {
  65 + continue;
  66 + }
  67 +
  68 + std::string vhost = conf->arg0();
  69 + if (!_srs_config->get_vhost_http_enabled(vhost)) {
  70 + continue;
  71 + }
  72 +
  73 + std::string mount = _srs_config->get_vhost_http_mount(vhost);
  74 + std::string dir = _srs_config->get_vhost_http_dir(vhost);
  75 +
  76 + handlers.push_back(new SrsHttpVhost(vhost, mount, dir));
  77 + }
  78 +
  79 + return ret;
  80 +}
  81 +
  82 +bool SrsHttpRoot::can_handle(const char* path, int length, const char** pchild)
  83 +{
  84 + // reset the child path to path,
  85 + // for child to reparse the path.
  86 + *pchild = path;
  87 +
  88 + // never handle request for root.
  89 + return false;
  90 +}
  91 +
  92 +bool SrsHttpRoot::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)
  93 +{
  94 + status_code = HTTP_InternalServerError;
  95 + reason_phrase = HTTP_InternalServerError_str;
  96 + return false;
  97 +}
  98 +
  99 +int SrsHttpRoot::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
  100 +{
  101 + int ret = ERROR_SUCCESS;
  102 + return ret;
  103 +}
  104 +
  105 +SrsHttpVhost::SrsHttpVhost(std::string vhost, std::string mount, std::string dir)
  106 +{
  107 + _vhost = vhost;
  108 + _mount = mount;
  109 + _dir = dir;
  110 +}
  111 +
  112 +SrsHttpVhost::~SrsHttpVhost()
  113 +{
  114 +}
  115 +
  116 +bool SrsHttpVhost::can_handle(const char* path, int length, const char** /*pchild*/)
  117 +{
  118 + int min_match = srs_min(length, (int)_mount.length());
  119 + return srs_path_equals(_mount.c_str(), path, min_match);
  120 +}
  121 +
  122 +bool SrsHttpVhost::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)
  123 +{
  124 + std::string fullpath = _dir + "/" + req->match()->unmatched_url;
  125 + if (req->match()->unmatched_url.empty()) {
  126 + fullpath += req->match()->matched_url;
  127 + }
  128 +
  129 + if (::access(fullpath.c_str(), F_OK | R_OK) < 0) {
  130 + srs_warn("check file %s does not exists", fullpath.c_str());
  131 +
  132 + status_code = HTTP_NotFound;
  133 + reason_phrase = HTTP_NotFound_str;
  134 + return false;
  135 + }
  136 +
  137 + return true;
  138 +}
  139 +
  140 +int SrsHttpVhost::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
  141 +{
  142 + int ret = ERROR_SUCCESS;
  143 +
  144 + std::string fullpath = _dir + "/" + req->match()->unmatched_url;
  145 + if (req->match()->unmatched_url.empty()) {
  146 + fullpath += req->match()->matched_url;
  147 + }
  148 +
  149 + if (srs_string_ends_with(fullpath, "/")) {
  150 + fullpath += "index.html";
  151 + }
  152 +
  153 + int fd = ::open(fullpath.c_str(), O_RDONLY);
  154 + if (fd < 0) {
  155 + ret = ERROR_HTTP_OPEN_FILE;
  156 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  157 + return ret;
  158 + }
  159 +
  160 + int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);
  161 + ::lseek(fd, 0, SEEK_SET);
  162 +
  163 + char* buf = new char[length];
  164 + SrsAutoFree(char, buf, true);
  165 +
  166 + if (::read(fd, buf, length) < 0) {
  167 + ::close(fd);
  168 + ret = ERROR_HTTP_READ_FILE;
  169 + srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
  170 + return ret;
  171 + }
  172 + ::close(fd);
  173 +
  174 + std::string str;
  175 + str.append(buf, length);
  176 +
  177 + if (srs_string_ends_with(fullpath, ".ts")) {
  178 + return res_mpegts(skt, req, str);
  179 + } else if (srs_string_ends_with(fullpath, ".m3u8")) {
  180 + return res_m3u8(skt, req, str);
  181 + } else {
  182 + return res_text(skt, req, str);
  183 + }
  184 +
  185 + return ret;
  186 +}
  187 +
  188 +string SrsHttpVhost::vhost()
  189 +{
  190 + return _vhost;
  191 +}
  192 +
  193 +string SrsHttpVhost::mount()
  194 +{
  195 + return _mount;
  196 +}
  197 +
  198 +string SrsHttpVhost::dir()
  199 +{
  200 + return _dir;
  201 +}
  202 +
  203 +SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
  204 + : SrsConnection(srs_server, client_stfd)
  205 +{
  206 + parser = new SrsHttpParser();
  207 + handler = _handler;
  208 + requires_crossdomain = false;
  209 +}
  210 +
  211 +SrsHttpConn::~SrsHttpConn()
  212 +{
  213 + srs_freep(parser);
  214 +}
  215 +
  216 +int SrsHttpConn::do_cycle()
  217 +{
  218 + int ret = ERROR_SUCCESS;
  219 +
  220 + if ((ret = get_peer_ip()) != ERROR_SUCCESS) {
  221 + srs_error("get peer ip failed. ret=%d", ret);
  222 + return ret;
  223 + }
  224 + srs_trace("http get peer ip success. ip=%s", ip);
  225 +
  226 + // initialize parser
  227 + if ((ret = parser->initialize(HTTP_REQUEST)) != ERROR_SUCCESS) {
  228 + srs_error("http initialize http parser failed. ret=%d", ret);
  229 + return ret;
  230 + }
  231 +
  232 + // underlayer socket
  233 + SrsSocket skt(stfd);
  234 +
  235 + // process http messages.
  236 + for (;;) {
  237 + SrsHttpMessage* req = NULL;
  238 +
  239 + // get a http message
  240 + if ((ret = parser->parse_message(&skt, &req)) != ERROR_SUCCESS) {
  241 + return ret;
  242 + }
  243 +
  244 + // if SUCCESS, always NOT-NULL and completed message.
  245 + srs_assert(req);
  246 + srs_assert(req->is_complete());
  247 +
  248 + // always free it in this scope.
  249 + SrsAutoFree(SrsHttpMessage, req, false);
  250 +
  251 + // ok, handle http request.
  252 + if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) {
  253 + return ret;
  254 + }
  255 + }
  256 +
  257 + return ret;
  258 +}
  259 +
  260 +int SrsHttpConn::process_request(SrsSocket* skt, SrsHttpMessage* req)
  261 +{
  262 + int ret = ERROR_SUCCESS;
  263 +
  264 + // parse uri to schema/server:port/path?query
  265 + if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
  266 + return ret;
  267 + }
  268 +
  269 + srs_trace("http request parsed, method=%d, url=%s, content-length=%"PRId64"",
  270 + req->method(), req->url().c_str(), req->content_length());
  271 +
  272 + // TODO: maybe need to parse the url.
  273 + std::string url = req->path();
  274 +
  275 + SrsHttpHandlerMatch* p = NULL;
  276 + if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {
  277 + srs_warn("failed to find the best match handler for url. ret=%d", ret);
  278 + return ret;
  279 + }
  280 +
  281 + // if success, p and pstart should be valid.
  282 + srs_assert(p);
  283 + srs_assert(p->handler);
  284 + srs_assert(p->matched_url.length() <= url.length());
  285 + srs_info("best match handler, matched_url=%s", p->matched_url.c_str());
  286 +
  287 + req->set_match(p);
  288 + req->set_requires_crossdomain(requires_crossdomain);
  289 +
  290 + // use handler to process request.
  291 + if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {
  292 + srs_warn("handler failed to process http request. ret=%d", ret);
  293 + return ret;
  294 + }
  295 +
  296 + if (req->requires_crossdomain()) {
  297 + requires_crossdomain = true;
  298 + }
  299 +
  300 + return ret;
  301 +}
  302 +
  303 +#endif