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-01-03 15:33:23 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
dc11418c796e05992851ef0735d1ce51b798ff4c
dc11418c
1 parent
dd2c7e0b
fix #274: http-callback support on_dvr when reap a dvr file. 2.0.89
隐藏空白字符变更
内嵌
并排对比
正在显示
12 个修改的文件
包含
207 行增加
和
7 行删除
README.md
trunk/conf/full.conf
trunk/research/api-server/server.py
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_http_hooks.cpp
trunk/src/app/srs_app_http_hooks.hpp
trunk/src/app/srs_app_rtmp_conn.cpp
trunk/src/core/srs_core.hpp
trunk/src/rtmp/srs_protocol_rtmp.cpp
trunk/src/rtmp/srs_protocol_rtmp.hpp
README.md
查看文件 @
dc11418
...
...
@@ -501,6 +501,7 @@ Supported operating systems and hardware:
*
2013-10-17, Created.
<br/>
## History
*
v2.0, 2015-01-03, fix
[
#274
](
https://github.com/winlinvip/simple-rtmp-server/issues/274
)
, http-callback support on_dvr when reap a dvr file. 2.0.89
*
v2.0, 2015-01-03, hotfix to remove the pageUrl for http callback. 2.0.88
*
v2.0, 2015-01-03, fix
[
#179
](
https://github.com/winlinvip/simple-rtmp-server/issues/179
)
, dvr support custom filepath by variables. 2.0.87
*
v2.0, 2015-01-02, fix
[
#211
](
https://github.com/winlinvip/simple-rtmp-server/issues/211
)
, support security allow/deny publish/play all/ip. 2.0.86
...
...
trunk/conf/full.conf
查看文件 @
dc11418
...
...
@@ -296,6 +296,11 @@ vhost dvr.srs.com {
# 3. off, disable the time jitter algorithm, like atc.
# default: full
time_jitter
full
;
# on_dvr
# for the dvr http callback, @see http_hooks.on_dvr of vhost hooks.callback.srs.com
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#http-callback
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#http-callback
}
}
...
...
@@ -338,7 +343,7 @@ vhost ingest.srs.com {
}
}
# vhost for http
# vhost for http
server config in each vhost.
vhost
http
.
srs
.
com
{
# http vhost specified config
http
{
...
...
@@ -490,6 +495,20 @@ vhost hooks.callback.srs.com {
# support multiple api hooks, format:
# on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN
on_stop
http
://
127
.
0
.
0
.
1
:
8085
/
api
/
v1
/
sessions
http
://
localhost
:
8085
/
api
/
v1
/
sessions
;
# when srs reap a dvr file, call the hook,
# the request in the POST data string is a object encode by json:
# {
# "action": "on_dvr",
# "client_id": 1985,
# "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
# "stream": "livestream",
# "cwd": "/usr/local/srs",
# "file": "./objs/nginx/html/live/livestream.1420254068776.flv"
# }
# if valid, the hook must return HTTP code 200(Stauts OK) and response
# an int value specifies the error code(0 corresponding to success):
# 0
on_dvr
http
://
127
.
0
.
0
.
1
:
8085
/
api
/
v1
/
dvrs
http
://
localhost
:
8085
/
api
/
v1
/
dvrs
;
}
}
...
...
trunk/research/api-server/server.py
查看文件 @
dc11418
...
...
@@ -154,7 +154,7 @@ class RESTClients(object):
return
code
'''
handle the streams requests: publish/unpublish
/dvr
stream.
handle the streams requests: publish/unpublish stream.
'''
class
RESTStreams
(
object
):
exposed
=
True
...
...
@@ -241,6 +241,74 @@ class RESTStreams(object):
return
code
'''
handle the dvrs requests: dvr stream.
'''
class
RESTDvrs
(
object
):
exposed
=
True
def
GET
(
self
):
enable_crossdomain
()
dvrs
=
{}
return
json
.
dumps
(
dvrs
)
'''
for SRS hook: on_dvr
on_dvr:
when srs reap a dvr file, call the hook,
the request in the POST data string is a object encode by json:
{
"action": "on_dvr",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream",
"cwd": "/usr/local/srs",
"file": "./objs/nginx/html/live/livestream.1420254068776.flv"
}
if valid, the hook must return HTTP code 200(Stauts OK) and response
an int value specifies the error code(0 corresponding to success):
0
'''
def
POST
(
self
):
enable_crossdomain
()
# return the error code in str
code
=
Error
.
success
req
=
cherrypy
.
request
.
body
.
read
()
trace
(
"post to dvrs, req=
%
s"
%
(
req
))
try
:
json_req
=
json
.
loads
(
req
)
except
Exception
,
ex
:
code
=
Error
.
system_parse_json
trace
(
"parse the request to json failed, req=
%
s, ex=
%
s, code=
%
s"
%
(
req
,
ex
,
code
))
return
str
(
code
)
action
=
json_req
[
"action"
]
if
action
==
"on_dvr"
:
code
=
self
.
__on_dvr
(
json_req
)
else
:
trace
(
"invalid request action:
%
s"
%
(
json_req
[
"action"
]))
code
=
Error
.
request_invalid_action
return
str
(
code
)
def
OPTIONS
(
self
,
*
args
,
**
kwargs
):
enable_crossdomain
()
def
__on_dvr
(
self
,
req
):
code
=
Error
.
success
trace
(
"srs
%
s: client id=
%
s, ip=
%
s, vhost=
%
s, app=
%
s, stream=
%
s, cwd=
%
s, file=
%
s"
%
(
req
[
"action"
],
req
[
"client_id"
],
req
[
"ip"
],
req
[
"vhost"
],
req
[
"app"
],
req
[
"stream"
],
req
[
"cwd"
],
req
[
"file"
]
))
# TODO: process the on_dvr event
return
code
'''
handle the sessions requests: client play/stop stream
'''
class
RESTSessions
(
object
):
...
...
@@ -1039,6 +1107,7 @@ class V1(object):
self
.
clients
=
RESTClients
()
self
.
streams
=
RESTStreams
()
self
.
sessions
=
RESTSessions
()
self
.
dvrs
=
RESTDvrs
()
self
.
chats
=
RESTChats
()
self
.
servers
=
RESTServers
()
self
.
nodes
=
RESTNodes
()
...
...
@@ -1048,6 +1117,7 @@ class V1(object):
"clients"
:
"for srs http callback, to handle the clients requests: connect/disconnect vhost/app."
,
"streams"
:
"for srs http callback, to handle the streams requests: publish/unpublish stream."
,
"sessions"
:
"for srs http callback, to handle the sessions requests: client play/stop stream"
,
"dvrs"
:
"for srs http callback, to handle the dvr requests: dvr stream."
,
"chats"
:
"for srs demo meeting, the chat streams, public chat room."
,
"nodes"
:
{
"summary"
:
"for srs cdn node"
,
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
dc11418
...
...
@@ -1426,6 +1426,7 @@ int SrsConfig::check_config()
string
m
=
conf
->
at
(
j
)
->
name
.
c_str
();
if
(
m
!=
"enabled"
&&
m
!=
"on_connect"
&&
m
!=
"on_close"
&&
m
!=
"on_publish"
&&
m
!=
"on_unpublish"
&&
m
!=
"on_play"
&&
m
!=
"on_stop"
&&
m
!=
"on_dvr"
)
{
ret
=
ERROR_SYSTEM_CONFIG_INVALID
;
srs_error
(
"unsupported vhost http_hooks directive %s, ret=%d"
,
m
.
c_str
(),
ret
);
...
...
@@ -2335,6 +2336,17 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost)
return
conf
->
get
(
"on_stop"
);
}
SrsConfDirective
*
SrsConfig
::
get_vhost_on_dvr
(
string
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost_http_hooks
(
vhost
);
if
(
!
conf
)
{
return
NULL
;
}
return
conf
->
get
(
"on_dvr"
);
}
bool
SrsConfig
::
get_bw_check_enabled
(
string
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost
(
vhost
);
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
dc11418
...
...
@@ -610,6 +610,11 @@ public:
* @return the on_stop callback directive, the args is the url to callback.
*/
virtual
SrsConfDirective
*
get_vhost_on_stop
(
std
::
string
vhost
);
/**
* get the on_dvr callbacks of vhost.
* @return the on_dvr callback directive, the args is the url to callback.
*/
virtual
SrsConfDirective
*
get_vhost_on_dvr
(
std
::
string
vhost
);
// bwct(bandwidth check tool) section
public:
/**
...
...
trunk/src/app/srs_app_dvr.cpp
查看文件 @
dc11418
...
...
@@ -404,6 +404,30 @@ int SrsDvrPlan::flv_close()
return
ret
;
}
#ifdef SRS_AUTO_HTTP_CALLBACK
SrsRequest
*
req
=
_req
;
if
(
_srs_config
->
get_vhost_http_hooks_enabled
(
req
->
vhost
))
{
// HTTP: on_dvr
SrsConfDirective
*
on_dvr
=
_srs_config
->
get_vhost_on_dvr
(
req
->
vhost
);
if
(
!
on_dvr
)
{
srs_info
(
"ignore the empty http callback: on_dvr"
);
return
ret
;
}
int
connection_id
=
_srs_context
->
get_id
();
std
::
string
ip
=
req
->
ip
;
std
::
string
cwd
=
_srs_config
->
cwd
();
std
::
string
file
=
segment
->
path
;
for
(
int
i
=
0
;
i
<
(
int
)
on_dvr
->
args
.
size
();
i
++
)
{
std
::
string
url
=
on_dvr
->
args
.
at
(
i
);
if
((
ret
=
SrsHttpHooks
::
on_dvr
(
url
,
connection_id
,
ip
,
req
,
cwd
,
file
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"hook client on_dvr failed. url=%s, ret=%d"
,
url
.
c_str
(),
ret
);
return
ret
;
}
}
}
#endif
return
ret
;
}
...
...
trunk/src/app/srs_app_http_hooks.cpp
查看文件 @
dc11418
...
...
@@ -379,5 +379,61 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
return
;
}
#endif
int
SrsHttpHooks
::
on_dvr
(
string
url
,
int
client_id
,
string
ip
,
SrsRequest
*
req
,
string
cwd
,
string
file
)
{
int
ret
=
ERROR_SUCCESS
;
SrsHttpUri
uri
;
if
((
ret
=
uri
.
initialize
(
url
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"http uri parse on_dvr url failed, ignored. "
"client_id=%d, url=%s, ret=%d"
,
client_id
,
url
.
c_str
(),
ret
);
return
ret
;
}
std
::
stringstream
ss
;
ss
<<
__SRS_JOBJECT_START
<<
__SRS_JFIELD_STR
(
"action"
,
"on_dvr"
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_ORG
(
"client_id"
,
client_id
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"ip"
,
ip
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"vhost"
,
req
->
vhost
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"app"
,
req
->
app
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"stream"
,
req
->
stream
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"cwd"
,
cwd
)
<<
__SRS_JFIELD_CONT
<<
__SRS_JFIELD_STR
(
"file"
,
file
)
<<
__SRS_JOBJECT_END
;
std
::
string
data
=
ss
.
str
();
std
::
string
res
;
int
status_code
;
SrsHttpClient
http
;
if
((
ret
=
http
.
post
(
&
uri
,
data
,
status_code
,
res
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"http post on_dvr uri failed, ignored. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d"
,
client_id
,
url
.
c_str
(),
data
.
c_str
(),
res
.
c_str
(),
ret
);
return
ret
;
}
// ensure the http status is ok.
// https://github.com/winlinvip/simple-rtmp-server/issues/158
if
(
status_code
!=
SRS_CONSTS_HTTP_OK
)
{
ret
=
ERROR_HTTP_STATUS_INVLIAD
;
srs_error
(
"http hook on_dvr status failed. "
"client_id=%d, code=%d, ret=%d"
,
client_id
,
status_code
,
ret
);
return
ret
;
}
if
(
res
.
empty
()
||
res
!=
SRS_HTTP_RESPONSE_OK
)
{
ret
=
ERROR_HTTP_DATA_INVLIAD
;
srs_warn
(
"http hook on_dvr validate failed, ignored. "
"client_id=%d, res=%s, ret=%d"
,
client_id
,
res
.
c_str
(),
ret
);
return
ret
;
}
srs_trace
(
"http hook on_dvr success. "
"client_id=%d, url=%s, request=%s, response=%s, ret=%d"
,
client_id
,
url
.
c_str
(),
data
.
c_str
(),
res
.
c_str
(),
ret
);
return
ret
;
}
#endif
...
...
trunk/src/app/srs_app_http_hooks.hpp
查看文件 @
dc11418
...
...
@@ -58,7 +58,6 @@ public:
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
static
int
on_connect
(
std
::
string
url
,
int
client_id
,
std
::
string
ip
,
SrsRequest
*
req
);
/**
...
...
@@ -73,7 +72,6 @@ public:
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
static
int
on_publish
(
std
::
string
url
,
int
client_id
,
std
::
string
ip
,
SrsRequest
*
req
);
/**
...
...
@@ -88,7 +86,6 @@ public:
* @param client_id the id of client on server.
* @param url the api server url, to valid the client.
* ignore if empty.
* @return valid failed or connect to the url failed.
*/
static
int
on_play
(
std
::
string
url
,
int
client_id
,
std
::
string
ip
,
SrsRequest
*
req
);
/**
...
...
@@ -98,6 +95,15 @@ public:
* ignore if empty.
*/
static
void
on_stop
(
std
::
string
url
,
int
client_id
,
std
::
string
ip
,
SrsRequest
*
req
);
/**
* on_dvr hook, when reap a dvr file.
* @param client_id the id of client on server.
* @param url the api server url, to process the event.
* ignore if empty.
* @param cwd the current work directory, used to resolve the reltive file path.
* @param file the file path, can be relative or absolute path.
*/
static
int
on_dvr
(
std
::
string
url
,
int
client_id
,
std
::
string
ip
,
SrsRequest
*
req
,
std
::
string
cwd
,
std
::
string
file
);
};
#endif
...
...
trunk/src/app/srs_app_rtmp_conn.cpp
查看文件 @
dc11418
...
...
@@ -135,6 +135,9 @@ int SrsRtmpConn::do_cycle()
}
srs_verbose
(
"rtmp connect app success"
);
// set client ip to request.
req
->
ip
=
ip
;
// discovery vhost, resolve the vhost from config
SrsConfDirective
*
parsed_vhost
=
_srs_config
->
get_vhost
(
req
->
vhost
);
if
(
parsed_vhost
)
{
...
...
trunk/src/core/srs_core.hpp
查看文件 @
dc11418
...
...
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_REVISION 8
8
#define VERSION_REVISION 8
9
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
#define RTMP_SIG_SRS_ROLE "origin/edge server"
...
...
trunk/src/rtmp/srs_protocol_rtmp.cpp
查看文件 @
dc11418
...
...
@@ -91,6 +91,7 @@ SrsRequest* SrsRequest::copy()
{
SrsRequest
*
cp
=
new
SrsRequest
();
cp
->
ip
=
ip
;
cp
->
app
=
app
;
cp
->
objectEncoding
=
objectEncoding
;
cp
->
pageUrl
=
pageUrl
;
...
...
trunk/src/rtmp/srs_protocol_rtmp.hpp
查看文件 @
dc11418
...
...
@@ -54,6 +54,9 @@ class IMergeReadHandler;
class
SrsRequest
{
public
:
// client ip.
std
::
string
ip
;
public
:
/**
* tcUrl: rtmp://request_vhost:port/app/stream
* support pass vhost in query string, such as:
...
...
请
注册
或
登录
后发表评论