winlin

implements the http stream module. change to 0.9.49

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 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 +
  97 + return false;
  98 +}
  99 +
  100 +int SrsHttpRoot::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
  101 +{
  102 + int ret = ERROR_SUCCESS;
  103 + return ret;
  104 +}
  105 +
  106 +SrsHttpVhost::SrsHttpVhost(std::string vhost, std::string mount, std::string dir)
  107 +{
  108 + _vhost = vhost;
  109 + _mount = mount;
  110 + _dir = dir;
  111 +}
  112 +
  113 +SrsHttpVhost::~SrsHttpVhost()
  114 +{
  115 +}
  116 +
  117 +bool SrsHttpVhost::can_handle(const char* path, int length, const char** /*pchild*/)
  118 +{
  119 + int min_match = srs_min(length, (int)_mount.length());
  120 + return srs_path_equals(_mount.c_str(), path, min_match);
  121 +}
  122 +
  123 +bool SrsHttpVhost::is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase)
  124 +{
  125 + std::string fullpath = _dir + "/" + req->match()->unmatched_url;
  126 + if (req->match()->unmatched_url.empty()) {
  127 + fullpath += req->match()->matched_url;
  128 + }
  129 +
  130 + if (::access(fullpath.c_str(), F_OK | R_OK) < 0) {
  131 + srs_warn("check file %s does not exists", fullpath.c_str());
  132 +
  133 + status_code = HTTP_NotFound;
  134 + reason_phrase = HTTP_NotFound_str;
  135 + return false;
  136 + }
  137 +
  138 + return true;
  139 +}
  140 +
  141 +int SrsHttpVhost::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
  142 +{
  143 + int ret = ERROR_SUCCESS;
  144 +
  145 + std::string fullpath = _dir + "/" + req->match()->unmatched_url;
  146 + if (req->match()->unmatched_url.empty()) {
  147 + fullpath += req->match()->matched_url;
  148 + }
  149 +
  150 + if (srs_string_ends_with(fullpath, "/")) {
  151 + fullpath += "index.html";
  152 + }
  153 +
  154 + int fd = ::open(fullpath.c_str(), O_RDONLY);
  155 + if (fd < 0) {
  156 + ret = ERROR_HTTP_OPEN_FILE;
  157 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  158 + return ret;
  159 + }
  160 +
  161 + int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);
  162 + ::lseek(fd, 0, SEEK_SET);
  163 +
  164 + char* buf = new char[length];
  165 + SrsAutoFree(char, buf, true);
  166 +
  167 + if (::read(fd, buf, length) < 0) {
  168 + ::close(fd);
  169 + ret = ERROR_HTTP_READ_FILE;
  170 + srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
  171 + return ret;
  172 + }
  173 + ::close(fd);
  174 +
  175 + std::string str;
  176 + str.append(buf, length);
  177 +
  178 + if (srs_string_ends_with(fullpath, ".ts")) {
  179 + return res_mpegts(skt, req, str);
  180 + } else if (srs_string_ends_with(fullpath, ".m3u8")) {
  181 + return res_m3u8(skt, req, str);
  182 + } else {
  183 + return res_text(skt, req, str);
  184 + }
  185 +
  186 + return ret;
  187 +}
  188 +
  189 +string SrsHttpVhost::vhost()
  190 +{
  191 + return _vhost;
  192 +}
  193 +
  194 +string SrsHttpVhost::mount()
  195 +{
  196 + return _mount;
  197 +}
  198 +
  199 +string SrsHttpVhost::dir()
  200 +{
  201 + return _dir;
  202 +}
  203 +
  204 +SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
  205 + : SrsConnection(srs_server, client_stfd)
  206 +{
  207 + parser = new SrsHttpParser();
  208 + handler = _handler;
  209 + requires_crossdomain = false;
  210 +}
  211 +
  212 +SrsHttpConn::~SrsHttpConn()
  213 +{
  214 + srs_freep(parser);
  215 +}
  216 +
  217 +int SrsHttpConn::do_cycle()
  218 +{
  219 + int ret = ERROR_SUCCESS;
  220 +
  221 + if ((ret = get_peer_ip()) != ERROR_SUCCESS) {
  222 + srs_error("get peer ip failed. ret=%d", ret);
  223 + return ret;
  224 + }
  225 + srs_trace("http get peer ip success. ip=%s", ip);
  226 +
  227 + // initialize parser
  228 + if ((ret = parser->initialize(HTTP_REQUEST)) != ERROR_SUCCESS) {
  229 + srs_error("http initialize http parser failed. ret=%d", ret);
  230 + return ret;
  231 + }
  232 +
  233 + // underlayer socket
  234 + SrsSocket skt(stfd);
  235 +
  236 + // process http messages.
  237 + for (;;) {
  238 + SrsHttpMessage* req = NULL;
  239 +
  240 + // get a http message
  241 + if ((ret = parser->parse_message(&skt, &req)) != ERROR_SUCCESS) {
  242 + return ret;
  243 + }
  244 +
  245 + // if SUCCESS, always NOT-NULL and completed message.
  246 + srs_assert(req);
  247 + srs_assert(req->is_complete());
  248 +
  249 + // always free it in this scope.
  250 + SrsAutoFree(SrsHttpMessage, req, false);
  251 +
  252 + // ok, handle http request.
  253 + if ((ret = process_request(&skt, req)) != ERROR_SUCCESS) {
  254 + return ret;
  255 + }
  256 + }
  257 +
  258 + return ret;
  259 +}
  260 +
  261 +int SrsHttpConn::process_request(SrsSocket* skt, SrsHttpMessage* req)
  262 +{
  263 + int ret = ERROR_SUCCESS;
  264 +
  265 + // parse uri to schema/server:port/path?query
  266 + if ((ret = req->parse_uri()) != ERROR_SUCCESS) {
  267 + return ret;
  268 + }
  269 +
  270 + srs_trace("http request parsed, method=%d, url=%s, content-length=%"PRId64"",
  271 + req->method(), req->url().c_str(), req->content_length());
  272 +
  273 + // TODO: maybe need to parse the url.
  274 + std::string url = req->path();
  275 +
  276 + SrsHttpHandlerMatch* p = NULL;
  277 + if ((ret = handler->best_match(url.data(), url.length(), &p)) != ERROR_SUCCESS) {
  278 + srs_warn("failed to find the best match handler for url. ret=%d", ret);
  279 + return ret;
  280 + }
  281 +
  282 + // if success, p and pstart should be valid.
  283 + srs_assert(p);
  284 + srs_assert(p->handler);
  285 + srs_assert(p->matched_url.length() <= url.length());
  286 + srs_info("best match handler, matched_url=%s", p->matched_url.c_str());
  287 +
  288 + req->set_match(p);
  289 + req->set_requires_crossdomain(requires_crossdomain);
  290 +
  291 + // use handler to process request.
  292 + if ((ret = p->handler->process_request(skt, req)) != ERROR_SUCCESS) {
  293 + srs_warn("handler failed to process http request. ret=%d", ret);
  294 + return ret;
  295 + }
  296 +
  297 + if (req->requires_crossdomain()) {
  298 + requires_crossdomain = true;
  299 + }
  300 +
  301 + return ret;
  302 +}
  303 +
  304 +#endif