winlin

refine http stream server

@@ -164,104 +164,120 @@ int SrsHttpVhost::do_process_request(SrsSocket* skt, SrsHttpMessage* req) @@ -164,104 +164,120 @@ int SrsHttpVhost::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
164 std::string fullpath = get_request_file(req); 164 std::string fullpath = get_request_file(req);
165 165
166 if (srs_string_ends_with(fullpath, ".ts")) { 166 if (srs_string_ends_with(fullpath, ".ts")) {
167 - // TODO: FIXME: use more advance cache.  
168 - // for ts video large file, use bytes to write it.  
169 - int fd = ::open(fullpath.c_str(), O_RDONLY);  
170 - if (fd < 0) {  
171 - ret = ERROR_HTTP_OPEN_FILE;  
172 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
173 - return ret;  
174 - } 167 + return response_ts_file(skt, req, fullpath);
  168 + } else {
  169 + return response_regular_file(skt, req, fullpath);
  170 + }
175 171
176 - int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);  
177 - ::lseek(fd, 0, SEEK_SET); 172 + return ret;
  173 +}
  174 +
  175 +int SrsHttpVhost::response_regular_file(SrsSocket* skt, SrsHttpMessage* req, string fullpath)
  176 +{
  177 + int ret = ERROR_SUCCESS;
  178 +
  179 + // TODO: FIXME: refine the file stream.
  180 + int fd = ::open(fullpath.c_str(), O_RDONLY);
  181 + if (fd < 0) {
  182 + ret = ERROR_HTTP_OPEN_FILE;
  183 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  184 + return ret;
  185 + }
  186 +
  187 + int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);
  188 + ::lseek(fd, 0, SEEK_SET);
178 189
179 - // write http header for ts.  
180 - std::stringstream ss; 190 + char* buf = new char[length];
  191 + SrsAutoFree(char, buf);
181 192
182 - res_status_line(ss)->res_content_type_mpegts(ss)  
183 - ->res_content_length(ss, (int)length);  
184 -  
185 - if (req->requires_crossdomain()) {  
186 - res_enable_crossdomain(ss);  
187 - }  
188 -  
189 - res_header_eof(ss);  
190 -  
191 - // flush http header to peer  
192 - if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {  
193 - return ret;  
194 - }  
195 -  
196 - // write body.  
197 - int64_t left = length;  
198 - char* buf = req->http_ts_send_buffer();  
199 -  
200 - while (left > 0) {  
201 - ssize_t nread = -1;  
202 - // TODO: FIXME: use st_read.  
203 - if ((nread = ::read(fd, buf, HTTP_TS_SEND_BUFFER_SIZE)) < 0) {  
204 - ::close(fd);  
205 - ret = ERROR_HTTP_READ_FILE;  
206 - srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);  
207 - return ret;  
208 - }  
209 -  
210 - left -= nread;  
211 - if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {  
212 - break;  
213 - }  
214 - } 193 + // TODO: FIXME: use st_read.
  194 + if (::read(fd, buf, length) < 0) {
215 ::close(fd); 195 ::close(fd);
216 - 196 + ret = ERROR_HTTP_READ_FILE;
  197 + srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
217 return ret; 198 return ret;
  199 + }
  200 + ::close(fd);
  201 +
  202 + std::string str;
  203 + str.append(buf, length);
  204 +
  205 + if (srs_string_ends_with(fullpath, ".ts")) {
  206 + return res_mpegts(skt, req, str);
  207 + } else if (srs_string_ends_with(fullpath, ".m3u8")) {
  208 + return res_m3u8(skt, req, str);
  209 + } else if (srs_string_ends_with(fullpath, ".xml")) {
  210 + return res_xml(skt, req, str);
  211 + } else if (srs_string_ends_with(fullpath, ".js")) {
  212 + return res_javascript(skt, req, str);
  213 + } else if (srs_string_ends_with(fullpath, ".json")) {
  214 + return res_json(skt, req, str);
  215 + } else if (srs_string_ends_with(fullpath, ".swf")) {
  216 + return res_swf(skt, req, str);
  217 + } else if (srs_string_ends_with(fullpath, ".css")) {
  218 + return res_css(skt, req, str);
  219 + } else if (srs_string_ends_with(fullpath, ".ico")) {
  220 + return res_ico(skt, req, str);
218 } else { 221 } else {
219 - // TODO: FIXME: refine the file stream.  
220 - int fd = ::open(fullpath.c_str(), O_RDONLY);  
221 - if (fd < 0) {  
222 - ret = ERROR_HTTP_OPEN_FILE;  
223 - srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);  
224 - return ret;  
225 - } 222 + return res_text(skt, req, str);
  223 + }
226 224
227 - int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);  
228 - ::lseek(fd, 0, SEEK_SET);  
229 -  
230 - char* buf = new char[length];  
231 - SrsAutoFree(char, buf); 225 + return ret;
  226 +}
  227 +
  228 +int SrsHttpVhost::response_ts_file(SrsSocket* skt, SrsHttpMessage* req, string fullpath)
  229 +{
  230 + int ret = ERROR_SUCCESS;
  231 +
  232 + // TODO: FIXME: use more advance cache.
  233 + // for ts video large file, use bytes to write it.
  234 + int fd = ::open(fullpath.c_str(), O_RDONLY);
  235 + if (fd < 0) {
  236 + ret = ERROR_HTTP_OPEN_FILE;
  237 + srs_warn("open file %s failed, ret=%d", fullpath.c_str(), ret);
  238 + return ret;
  239 + }
  240 +
  241 + int64_t length = (int64_t)::lseek(fd, 0, SEEK_END);
  242 + ::lseek(fd, 0, SEEK_SET);
  243 +
  244 + // write http header for ts.
  245 + std::stringstream ss;
  246 +
  247 + res_status_line(ss)->res_content_type_mpegts(ss)
  248 + ->res_content_length(ss, (int)length);
232 249
  250 + if (req->requires_crossdomain()) {
  251 + res_enable_crossdomain(ss);
  252 + }
  253 +
  254 + res_header_eof(ss);
  255 +
  256 + // flush http header to peer
  257 + if ((ret = res_flush(skt, ss)) != ERROR_SUCCESS) {
  258 + return ret;
  259 + }
  260 +
  261 + // write body.
  262 + int64_t left = length;
  263 + char* buf = req->http_ts_send_buffer();
  264 +
  265 + while (left > 0) {
  266 + ssize_t nread = -1;
233 // TODO: FIXME: use st_read. 267 // TODO: FIXME: use st_read.
234 - if (::read(fd, buf, length) < 0) { 268 + if ((nread = ::read(fd, buf, HTTP_TS_SEND_BUFFER_SIZE)) < 0) {
235 ::close(fd); 269 ::close(fd);
236 ret = ERROR_HTTP_READ_FILE; 270 ret = ERROR_HTTP_READ_FILE;
237 srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret); 271 srs_warn("read file %s failed, ret=%d", fullpath.c_str(), ret);
238 return ret; 272 return ret;
239 } 273 }
240 - ::close(fd);  
241 -  
242 - std::string str;  
243 - str.append(buf, length);  
244 274
245 - if (srs_string_ends_with(fullpath, ".ts")) {  
246 - return res_mpegts(skt, req, str);  
247 - } else if (srs_string_ends_with(fullpath, ".m3u8")) {  
248 - return res_m3u8(skt, req, str);  
249 - } else if (srs_string_ends_with(fullpath, ".xml")) {  
250 - return res_xml(skt, req, str);  
251 - } else if (srs_string_ends_with(fullpath, ".js")) {  
252 - return res_javascript(skt, req, str);  
253 - } else if (srs_string_ends_with(fullpath, ".json")) {  
254 - return res_json(skt, req, str);  
255 - } else if (srs_string_ends_with(fullpath, ".swf")) {  
256 - return res_swf(skt, req, str);  
257 - } else if (srs_string_ends_with(fullpath, ".css")) {  
258 - return res_css(skt, req, str);  
259 - } else if (srs_string_ends_with(fullpath, ".ico")) {  
260 - return res_ico(skt, req, str);  
261 - } else {  
262 - return res_text(skt, req, str); 275 + left -= nread;
  276 + if ((ret = skt->write(buf, nread, NULL)) != ERROR_SUCCESS) {
  277 + break;
263 } 278 }
264 } 279 }
  280 + ::close(fd);
265 281
266 return ret; 282 return ret;
267 } 283 }
@@ -70,6 +70,8 @@ protected: @@ -70,6 +70,8 @@ protected:
70 virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase); 70 virtual bool is_handler_valid(SrsHttpMessage* req, int& status_code, std::string& reason_phrase);
71 virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req); 71 virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
72 private: 72 private:
  73 + virtual int response_regular_file(SrsSocket* skt, SrsHttpMessage* req, std::string fullpath);
  74 + virtual int response_ts_file(SrsSocket* skt, SrsHttpMessage* req, std::string fullpath);
73 virtual std::string get_request_file(SrsHttpMessage* req); 75 virtual std::string get_request_file(SrsHttpMessage* req);
74 public: 76 public:
75 virtual std::string vhost(); 77 virtual std::string vhost();