Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
胡斌
/
srs
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
winlin
2015-02-21 21:17:59 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c67a4fdf9737009beecdc2ccba196bda2b4c254e
c67a4fdf
1 parent
14450864
for #179, enable http api crossdomain for dvr api.
显示空白字符变更
内嵌
并排对比
正在显示
11 个修改的文件
包含
267 行增加
和
3 行删除
trunk/conf/full.conf
trunk/src/app/srs_app_config.cpp
trunk/src/app/srs_app_config.hpp
trunk/src/app/srs_app_dvr.cpp
trunk/src/app/srs_app_dvr.hpp
trunk/src/app/srs_app_http.cpp
trunk/src/app/srs_app_http.hpp
trunk/src/app/srs_app_http_api.cpp
trunk/src/app/srs_app_http_api.hpp
trunk/src/app/srs_app_server.cpp
trunk/src/kernel/srs_kernel_error.hpp
trunk/conf/full.conf
查看文件 @
c67a4fd
...
...
@@ -109,6 +109,9 @@ http_api {
# the http api port
# default: 1985
listen
1985
;
# whether enable crossdomain request.
# default: on
crossdomain
on
;
}
# embeded http server in srs.
# the http streaming config, for HLS/HDS/DASH/HTTPProgressive
...
...
@@ -286,6 +289,31 @@ vhost dvr.srs.com {
# segment reap flv when flv duration exceed the specified dvr_duration.
# append always append to flv file, never reap it.
# api reap flv when api required.
# about the api plan, the HTTP api to dvr,
# http url to control dvr, for example, http://dev:1985/api/v1/dvrs
# method=GET
# to query dvrs of server.
# request params, for example ?vhost=__defaultVhost__, where:
# vhost, query all dvr of this vhost.
# response in json, where:
# {code:0, dvrs: [{plan:"api", path:"./objs/nginx/html",
# autostart:true, wait_keyframe:true, jitter:"full"
# }]}
# method=POST
# to start dvr of specified vhost.
# request should encode in json, specifies the dvr to create, where:
# {plan:"api", path:"./objs/nginx/html",
# autostart:true, wait_keyframe:true, jitter:"full",
# vhost:"__defaultVhost", callback:"http://dvr/callback"
# }
# response in json, where:
# {code:0}
# method=DELETE, to stop dvr
# to stop dvr of specified vhost.
# request params, for example ?vhost=__defaultVhost__, where:
# vhost, stop all dvr of this vhost.
# response in json, where:
# {code:0}
# default: session
dvr_plan
session
;
# the dvr output path.
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
c67a4fd
...
...
@@ -1334,7 +1334,7 @@ int SrsConfig::check_config()
SrsConfDirective
*
conf
=
get_http_api
();
for
(
int
i
=
0
;
conf
&&
i
<
(
int
)
conf
->
directives
.
size
();
i
++
)
{
string
n
=
conf
->
at
(
i
)
->
name
;
if
(
n
!=
"enabled"
&&
n
!=
"listen"
)
{
if
(
n
!=
"enabled"
&&
n
!=
"listen"
&&
n
!=
"crossdomain"
)
{
ret
=
ERROR_SYSTEM_CONFIG_INVALID
;
srs_error
(
"unsupported http_api directive %s, ret=%d"
,
n
.
c_str
(),
ret
);
return
ret
;
...
...
@@ -3453,6 +3453,22 @@ int SrsConfig::get_http_api_listen()
return
::
atoi
(
conf
->
arg0
().
c_str
());
}
bool
SrsConfig
::
get_http_api_crossdomain
()
{
SrsConfDirective
*
conf
=
get_http_api
();
if
(
!
conf
)
{
return
SRS_CONF_DEFAULT_HTTP_API_CROSSDOMAIN
;
}
conf
=
conf
->
get
(
"crossdomain"
);
if
(
!
conf
||
conf
->
arg0
().
empty
())
{
return
SRS_CONF_DEFAULT_HTTP_API_CROSSDOMAIN
;
}
return
conf
->
arg0
()
!=
"off"
;
}
bool
SrsConfig
::
get_http_stream_enabled
()
{
SrsConfDirective
*
conf
=
get_http_stream
();
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
c67a4fd
...
...
@@ -79,6 +79,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONF_DEFAULT_HTTP_STREAM_PORT 8080
#define SRS_CONF_DEFAULT_HTTP_API_PORT 1985
#define SRS_CONF_DEFAULT_HTTP_API_CROSSDOMAIN true
#define SRS_CONF_DEFAULT_HTTP_HEAETBEAT_ENABLED false
#define SRS_CONF_DEFAULT_HTTP_HEAETBEAT_INTERVAL 9.9
...
...
@@ -957,6 +958,10 @@ public:
* get the http api listen port.
*/
virtual
int
get_http_api_listen
();
/**
* whether enable crossdomain for http api.
*/
virtual
bool
get_http_api_crossdomain
();
// http stream section
private:
/**
...
...
trunk/src/app/srs_app_dvr.cpp
查看文件 @
c67a4fd
...
...
@@ -40,6 +40,7 @@ using namespace std;
#include <srs_kernel_file.hpp>
#include <srs_rtmp_amf0.hpp>
#include <srs_kernel_stream.hpp>
#include <srs_app_json.hpp>
// update the flv duration and filesize every this interval in ms.
#define __SRS_DVR_UPDATE_DURATION_INTERVAL 60000
...
...
@@ -665,6 +666,8 @@ SrsDvrPlan* SrsDvrPlan::create_plan(string vhost)
return
new
SrsDvrSessionPlan
();
}
else
if
(
plan
==
SRS_CONF_DEFAULT_DVR_PLAN_APPEND
)
{
return
new
SrsDvrAppendPlan
();
}
else
if
(
plan
==
SRS_CONF_DEFAULT_DVR_PLAN_API
)
{
return
new
SrsDvrApiPlan
();
}
else
{
srs_error
(
"invalid dvr plan=%s, vhost=%s"
,
plan
.
c_str
(),
vhost
.
c_str
());
srs_assert
(
false
);
...
...
@@ -721,6 +724,56 @@ void SrsDvrSessionPlan::on_unpublish()
dvr_enabled
=
false
;
}
SrsDvrApiPlan
::
SrsDvrApiPlan
()
{
}
SrsDvrApiPlan
::~
SrsDvrApiPlan
()
{
}
int
SrsDvrApiPlan
::
on_publish
()
{
int
ret
=
ERROR_SUCCESS
;
// support multiple publish.
if
(
dvr_enabled
)
{
return
ret
;
}
if
(
!
_srs_config
->
get_dvr_enabled
(
req
->
vhost
))
{
return
ret
;
}
if
((
ret
=
segment
->
close
())
!=
ERROR_SUCCESS
)
{
return
ret
;
}
if
((
ret
=
segment
->
open
())
!=
ERROR_SUCCESS
)
{
return
ret
;
}
dvr_enabled
=
true
;
return
ret
;
}
void
SrsDvrApiPlan
::
on_unpublish
()
{
// support multiple publish.
if
(
!
dvr_enabled
)
{
return
;
}
// ignore error.
int
ret
=
segment
->
close
();
if
(
ret
!=
ERROR_SUCCESS
)
{
srs_warn
(
"ignore flv close error. ret=%d"
,
ret
);
}
dvr_enabled
=
false
;
}
SrsDvrAppendPlan
::
SrsDvrAppendPlan
()
{
last_update_time
=
0
;
...
...
@@ -977,6 +1030,29 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
return
ret
;
}
SrsApiDvrPool
*
SrsApiDvrPool
::
_instance
=
new
SrsApiDvrPool
();
SrsApiDvrPool
*
SrsApiDvrPool
::
instance
()
{
return
SrsApiDvrPool
::
_instance
;
}
SrsApiDvrPool
::
SrsApiDvrPool
()
{
}
SrsApiDvrPool
::~
SrsApiDvrPool
()
{
}
int
SrsApiDvrPool
::
dumps
(
stringstream
&
ss
)
{
int
ret
=
ERROR_SUCCESS
;
ss
<<
__SRS_JARRAY_START
<<
__SRS_JARRAY_END
;
return
ret
;
}
SrsDvr
::
SrsDvr
(
SrsSource
*
s
)
{
source
=
s
;
...
...
trunk/src/app/srs_app_dvr.hpp
查看文件 @
c67a4fd
...
...
@@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#include <string>
#include <sstream>
#ifdef SRS_AUTO_DVR
...
...
@@ -224,6 +225,19 @@ public:
};
/**
* api plan: reap flv by api.
*/
class
SrsDvrApiPlan
:
public
SrsDvrPlan
{
public
:
SrsDvrApiPlan
();
virtual
~
SrsDvrApiPlan
();
public
:
virtual
int
on_publish
();
virtual
void
on_unpublish
();
};
/**
* always append to flv file, never reap it.
*/
class
SrsDvrAppendPlan
:
public
SrsDvrPlan
...
...
@@ -283,6 +297,22 @@ private:
};
/**
* the api dvr pool.
*/
class
SrsApiDvrPool
{
private
:
static
SrsApiDvrPool
*
_instance
;
private
:
SrsApiDvrPool
();
public
:
static
SrsApiDvrPool
*
instance
();
virtual
~
SrsApiDvrPool
();
public
:
virtual
int
dumps
(
std
::
stringstream
&
ss
);
};
/**
* dvr(digital video recorder) to record RTMP stream to flv file.
* TODO: FIXME: add utest for it.
*/
...
...
trunk/src/app/srs_app_http.cpp
查看文件 @
c67a4fd
...
...
@@ -139,6 +139,9 @@ bool srs_go_http_body_allowd(int status)
// returns "application/octet-stream".
string
srs_go_http_detect
(
char
*
data
,
int
size
)
{
// detect only when data specified.
if
(
data
)
{
}
return
"application/octet-stream"
;
// fallback
}
...
...
@@ -715,8 +718,8 @@ int SrsGoHttpResponseWriter::final_request()
return
skt
->
write
((
void
*
)
ch
.
data
(),
(
int
)
ch
.
length
(),
NULL
);
}
// ignore when send with content length
return
ERROR_SUCCESS
;
// flush when send with content length
return
write
(
NULL
,
0
);
}
SrsGoHttpHeader
*
SrsGoHttpResponseWriter
::
header
()
...
...
@@ -744,6 +747,11 @@ int SrsGoHttpResponseWriter::write(char* data, int size)
return
ret
;
}
// ignore NULL content.
if
(
!
data
)
{
return
ret
;
}
// directly send with content length
if
(
content_length
!=
-
1
)
{
return
skt
->
write
((
void
*
)
data
,
size
,
NULL
);
...
...
trunk/src/app/srs_app_http.hpp
查看文件 @
c67a4fd
...
...
@@ -123,6 +123,29 @@ public:
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response.
// Usage 1, response with specified length content:
// ISrsGoHttpResponseWriter* w; // create or get response.
// std::string msg = "Hello, HTTP!";
// w->header()->set_content_type("text/plain; charset=utf-8");
// w->header()->set_content_length(msg.length());
// w->write_header(SRS_CONSTS_HTTP_OK);
// w->write((char*)msg.data(), (int)msg.length());
// w->final_request(); // optional flush.
// Usage 2, response with HTTP code only, zero content length.
// ISrsGoHttpResponseWriter* w; // create or get response.
// w->header()->set_content_length(0);
// w->write_header(SRS_CONSTS_HTTP_OK);
// w->final_request();
// Usage 3, response in chunked encoding.
// ISrsGoHttpResponseWriter* w; // create or get response.
// std::string msg = "Hello, HTTP!";
// w->header()->set_content_type("application/octet-stream");
// w->write_header(SRS_CONSTS_HTTP_OK);
// w->write((char*)msg.data(), (int)msg.length());
// w->write((char*)msg.data(), (int)msg.length());
// w->write((char*)msg.data(), (int)msg.length());
// w->write((char*)msg.data(), (int)msg.length());
// w->final_request(); // required to end the chunked and flush.
class
ISrsGoHttpResponseWriter
{
public
:
...
...
@@ -143,6 +166,7 @@ public:
// before writing the data. If the Header does not contain a
// Content-Type line, Write adds a Content-Type set to the result of passing
// the initial 512 bytes of written data to DetectContentType.
// @param data, the data to send. NULL to flush header only.
virtual
int
write
(
char
*
data
,
int
size
)
=
0
;
// WriteHeader sends an HTTP response header with status code.
...
...
trunk/src/app/srs_app_http_api.cpp
查看文件 @
c67a4fd
...
...
@@ -37,6 +37,8 @@ using namespace std;
#include <srs_app_utility.hpp>
#include <srs_app_statistic.hpp>
#include <srs_rtmp_sdk.hpp>
#include <srs_app_dvr.hpp>
#include <srs_app_config.hpp>
SrsGoApiRoot
::
SrsGoApiRoot
()
{
...
...
@@ -472,11 +474,48 @@ int SrsGoApiStreams::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
return
srs_go_http_response_json
(
w
,
ss
.
str
());
}
SrsGoApiDvrs
::
SrsGoApiDvrs
()
{
}
SrsGoApiDvrs
::~
SrsGoApiDvrs
()
{
}
int
SrsGoApiDvrs
::
serve_http
(
ISrsGoHttpResponseWriter
*
w
,
SrsHttpMessage
*
r
)
{
std
::
stringstream
ss
;
#ifndef SRS_AUTO_DVR
ss
<<
__SRS_JOBJECT_START
<<
__SRS_JFIELD_ERROR
(
ERROR_HTTP_DVR_DISABLED
)
<<
__SRS_JOBJECT_END
;
#else
SrsApiDvrPool
*
pool
=
SrsApiDvrPool
::
instance
();
if
(
r
->
is_http_get
())
{
std
::
stringstream
data
;
int
ret
=
pool
->
dumps
(
data
);
ss
<<
__SRS_JOBJECT_START
<<
__SRS_JFIELD_ERROR
(
ret
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_ORG
(
"dvrs"
,
data
.
str
())
<<
__SRS_JOBJECT_END
;
}
else
{
ss
<<
__SRS_JOBJECT_START
<<
__SRS_JFIELD_ERROR
(
ERROR_HTTP_DVR_REQUEST
)
<<
__SRS_JOBJECT_END
;
}
#endif
return
srs_go_http_response_json
(
w
,
ss
.
str
());
}
SrsHttpApi
::
SrsHttpApi
(
SrsServer
*
svr
,
st_netfd_t
fd
,
SrsGoHttpServeMux
*
m
)
:
SrsConnection
(
svr
,
fd
)
{
mux
=
m
;
parser
=
new
SrsHttpParser
();
crossdomain_required
=
false
;
}
SrsHttpApi
::~
SrsHttpApi
()
...
...
@@ -549,6 +588,29 @@ int SrsHttpApi::process_request(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
srs_trace
(
"HTTP %s %s, content-length=%"
PRId64
""
,
r
->
method_str
().
c_str
(),
r
->
url
().
c_str
(),
r
->
content_length
());
// method is OPTIONS and enable crossdomain, required crossdomain header.
if
(
r
->
is_http_options
()
&&
_srs_config
->
get_http_api_crossdomain
())
{
crossdomain_required
=
true
;
}
// whenever crossdomain required, set crossdomain header.
if
(
crossdomain_required
)
{
w
->
header
()
->
set
(
"Access-Control-Allow-Origin"
,
"*"
);
w
->
header
()
->
set
(
"Access-Control-Allow-Methods"
,
"GET, POST, HEAD, PUT, DELETE"
);
w
->
header
()
->
set
(
"Access-Control-Allow-Headers"
,
"Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type"
);
}
// handle the http options.
if
(
r
->
is_http_options
())
{
w
->
header
()
->
set_content_length
(
0
);
if
(
_srs_config
->
get_http_api_crossdomain
())
{
w
->
write_header
(
SRS_CONSTS_HTTP_OK
);
}
else
{
w
->
write_header
(
SRS_CONSTS_HTTP_MethodNotAllowed
);
}
return
w
->
final_request
();
}
// use default server mux to serve http request.
if
((
ret
=
mux
->
serve_http
(
w
,
r
))
!=
ERROR_SUCCESS
)
{
if
(
!
srs_is_client_gracefully_close
(
ret
))
{
...
...
trunk/src/app/srs_app_http_api.hpp
查看文件 @
c67a4fd
...
...
@@ -159,11 +159,21 @@ public:
virtual
int
serve_http
(
ISrsGoHttpResponseWriter
*
w
,
SrsHttpMessage
*
r
);
};
class
SrsGoApiDvrs
:
public
ISrsGoHttpHandler
{
public
:
SrsGoApiDvrs
();
virtual
~
SrsGoApiDvrs
();
public
:
virtual
int
serve_http
(
ISrsGoHttpResponseWriter
*
w
,
SrsHttpMessage
*
r
);
};
class
SrsHttpApi
:
public
SrsConnection
{
private
:
SrsHttpParser
*
parser
;
SrsGoHttpServeMux
*
mux
;
bool
crossdomain_required
;
public
:
SrsHttpApi
(
SrsServer
*
svr
,
st_netfd_t
fd
,
SrsGoHttpServeMux
*
m
);
virtual
~
SrsHttpApi
();
...
...
trunk/src/app/srs_app_server.cpp
查看文件 @
c67a4fd
...
...
@@ -529,6 +529,9 @@ int SrsServer::initialize()
if
((
ret
=
http_api_mux
->
handle
(
"/api/v1/streams"
,
new
SrsGoApiStreams
()))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
if
((
ret
=
http_api_mux
->
handle
(
"/api/v1/dvrs"
,
new
SrsGoApiDvrs
()))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
#endif
#ifdef SRS_AUTO_HTTP_SERVER
...
...
trunk/src/kernel/srs_kernel_error.hpp
查看文件 @
c67a4fd
...
...
@@ -209,6 +209,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_AAC_ADTS_HEADER 3047
#define ERROR_AAC_DATA_INVALID 3048
#define ERROR_HLS_TRY_MP3 3049
#define ERROR_HTTP_DVR_DISABLED 3050
#define ERROR_HTTP_DVR_REQUEST 3051
///////////////////////////////////////////////////////
// HTTP/StreamCaster protocol error.
...
...
请
注册
或
登录
后发表评论