support http hooks: on_connect/close/publish/unpublish/play/stop.
正在显示
11 个修改的文件
包含
969 行增加
和
49 行删除
| @@ -190,6 +190,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | @@ -190,6 +190,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw | ||
| 190 | * nginx v1.5.0: 139524 lines <br/> | 190 | * nginx v1.5.0: 139524 lines <br/> |
| 191 | 191 | ||
| 192 | ### History | 192 | ### History |
| 193 | +* v0.8, 2013-12-08, support http hooks: on_connect/close/publish/unpublish/play/stop. | ||
| 193 | * v0.8, 2013-12-08, support multiple http hooks for a event. | 194 | * v0.8, 2013-12-08, support multiple http hooks for a event. |
| 194 | * v0.8, 2013-12-07, support http callback hooks, on_connect. | 195 | * v0.8, 2013-12-07, support http callback hooks, on_connect. |
| 195 | * v0.8, 2013-12-07, support network based cli and json result, add CherryPy 3.2.4. | 196 | * v0.8, 2013-12-07, support network based cli and json result, add CherryPy 3.2.4. |
| @@ -139,6 +139,8 @@ vhost hooks.callback.vhost.com { | @@ -139,6 +139,8 @@ vhost hooks.callback.vhost.com { | ||
| 139 | # when client connect to vhost/app, call the hook, | 139 | # when client connect to vhost/app, call the hook, |
| 140 | # the request in the POST data string is a object encode by json: | 140 | # the request in the POST data string is a object encode by json: |
| 141 | # { | 141 | # { |
| 142 | + # "action": "on_connect", | ||
| 143 | + # "client_id": 1985, | ||
| 142 | # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | 144 | # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", |
| 143 | # "pageUrl": "http://www.test.com/live.html" | 145 | # "pageUrl": "http://www.test.com/live.html" |
| 144 | # } | 146 | # } |
| @@ -148,6 +150,75 @@ vhost hooks.callback.vhost.com { | @@ -148,6 +150,75 @@ vhost hooks.callback.vhost.com { | ||
| 148 | # support multiple api hooks, format: | 150 | # support multiple api hooks, format: |
| 149 | # on_connect http://xxx/api0 http://xxx/api1 http://xxx/apiN | 151 | # on_connect http://xxx/api0 http://xxx/api1 http://xxx/apiN |
| 150 | on_connect http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; | 152 | on_connect http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; |
| 153 | + # when client close/disconnect to vhost/app/stream, call the hook, | ||
| 154 | + # the request in the POST data string is a object encode by json: | ||
| 155 | + # { | ||
| 156 | + # "action": "on_close", | ||
| 157 | + # "client_id": 1985, | ||
| 158 | + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live" | ||
| 159 | + # } | ||
| 160 | + # if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 161 | + # an int value specifies the error code(0 corresponding to success): | ||
| 162 | + # 0 | ||
| 163 | + # support multiple api hooks, format: | ||
| 164 | + # on_close http://xxx/api0 http://xxx/api1 http://xxx/apiN | ||
| 165 | + on_close http://127.0.0.1:8085/api/v1/clients http://localhost:8085/api/v1/clients; | ||
| 166 | + # when client(encoder) publish to vhost/app/stream, call the hook, | ||
| 167 | + # the request in the POST data string is a object encode by json: | ||
| 168 | + # { | ||
| 169 | + # "action": "on_publish", | ||
| 170 | + # "client_id": 1985, | ||
| 171 | + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 172 | + # "stream": "livestream" | ||
| 173 | + # } | ||
| 174 | + # if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 175 | + # an int value specifies the error code(0 corresponding to success): | ||
| 176 | + # 0 | ||
| 177 | + # support multiple api hooks, format: | ||
| 178 | + # on_publish http://xxx/api0 http://xxx/api1 http://xxx/apiN | ||
| 179 | + on_publish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; | ||
| 180 | + # when client(encoder) stop publish to vhost/app/stream, call the hook, | ||
| 181 | + # the request in the POST data string is a object encode by json: | ||
| 182 | + # { | ||
| 183 | + # "action": "on_unpublish", | ||
| 184 | + # "client_id": 1985, | ||
| 185 | + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 186 | + # "stream": "livestream" | ||
| 187 | + # } | ||
| 188 | + # if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 189 | + # an int value specifies the error code(0 corresponding to success): | ||
| 190 | + # 0 | ||
| 191 | + # support multiple api hooks, format: | ||
| 192 | + # on_unpublish http://xxx/api0 http://xxx/api1 http://xxx/apiN | ||
| 193 | + on_unpublish http://127.0.0.1:8085/api/v1/streams http://localhost:8085/api/v1/streams; | ||
| 194 | + # when client start to play vhost/app/stream, call the hook, | ||
| 195 | + # the request in the POST data string is a object encode by json: | ||
| 196 | + # { | ||
| 197 | + # "action": "on_play", | ||
| 198 | + # "client_id": 1985, | ||
| 199 | + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 200 | + # "stream": "livestream" | ||
| 201 | + # } | ||
| 202 | + # if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 203 | + # an int value specifies the error code(0 corresponding to success): | ||
| 204 | + # 0 | ||
| 205 | + # support multiple api hooks, format: | ||
| 206 | + # on_play http://xxx/api0 http://xxx/api1 http://xxx/apiN | ||
| 207 | + on_play http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; | ||
| 208 | + # when client stop to play vhost/app/stream, call the hook, | ||
| 209 | + # the request in the POST data string is a object encode by json: | ||
| 210 | + # { | ||
| 211 | + # "action": "on_stop", | ||
| 212 | + # "client_id": 1985, | ||
| 213 | + # "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 214 | + # "stream": "livestream" | ||
| 215 | + # } | ||
| 216 | + # if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 217 | + # an int value specifies the error code(0 corresponding to success): | ||
| 218 | + # 0 | ||
| 219 | + # support multiple api hooks, format: | ||
| 220 | + # on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN | ||
| 221 | + on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions; | ||
| 151 | } | 222 | } |
| 152 | } | 223 | } |
| 153 | # the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction | 224 | # the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction |
| @@ -57,10 +57,11 @@ class Error: | @@ -57,10 +57,11 @@ class Error: | ||
| 57 | success = 0 | 57 | success = 0 |
| 58 | # error when parse json | 58 | # error when parse json |
| 59 | system_parse_json = 100 | 59 | system_parse_json = 100 |
| 60 | + # request action invalid | ||
| 61 | + request_invalid_action = 200 | ||
| 60 | 62 | ||
| 61 | ''' | 63 | ''' |
| 62 | -handle the clients requests: | ||
| 63 | -POST: create new client, handle the SRS on_connect callback. | 64 | +handle the clients requests: connect/disconnect vhost/app. |
| 64 | ''' | 65 | ''' |
| 65 | class RESTClients(object): | 66 | class RESTClients(object): |
| 66 | exposed = True | 67 | exposed = True |
| @@ -72,13 +73,24 @@ class RESTClients(object): | @@ -72,13 +73,24 @@ class RESTClients(object): | ||
| 72 | return json.dumps(clients) | 73 | return json.dumps(clients) |
| 73 | 74 | ||
| 74 | ''' | 75 | ''' |
| 75 | - for SRS hook: on_connect | ||
| 76 | - when client connect to vhost/app, call the hook, | ||
| 77 | - the request in the POST data string is a object encode by json: | ||
| 78 | - { | ||
| 79 | - "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 80 | - "pageUrl": "http://www.test.com/live.html" | ||
| 81 | - } | 76 | + for SRS hook: on_connect/on_close |
| 77 | + on_connect: | ||
| 78 | + when client connect to vhost/app, call the hook, | ||
| 79 | + the request in the POST data string is a object encode by json: | ||
| 80 | + { | ||
| 81 | + "action": "on_connect", | ||
| 82 | + "client_id": 1985, | ||
| 83 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 84 | + "pageUrl": "http://www.test.com/live.html" | ||
| 85 | + } | ||
| 86 | + on_close: | ||
| 87 | + when client close/disconnect to vhost/app/stream, call the hook, | ||
| 88 | + the request in the POST data string is a object encode by json: | ||
| 89 | + { | ||
| 90 | + "action": "on_close", | ||
| 91 | + "client_id": 1985, | ||
| 92 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live" | ||
| 93 | + } | ||
| 82 | if valid, the hook must return HTTP code 200(Stauts OK) and response | 94 | if valid, the hook must return HTTP code 200(Stauts OK) and response |
| 83 | an int value specifies the error code(0 corresponding to success): | 95 | an int value specifies the error code(0 corresponding to success): |
| 84 | 0 | 96 | 0 |
| @@ -87,29 +99,227 @@ class RESTClients(object): | @@ -87,29 +99,227 @@ class RESTClients(object): | ||
| 87 | enable_crossdomain() | 99 | enable_crossdomain() |
| 88 | 100 | ||
| 89 | # return the error code in str | 101 | # return the error code in str |
| 90 | - ret = Error.success | 102 | + code = Error.success |
| 91 | 103 | ||
| 92 | req = cherrypy.request.body.read() | 104 | req = cherrypy.request.body.read() |
| 93 | trace("post to clients, req=%s"%(req)) | 105 | trace("post to clients, req=%s"%(req)) |
| 94 | try: | 106 | try: |
| 95 | json_req = json.loads(req) | 107 | json_req = json.loads(req) |
| 96 | except Exception, ex: | 108 | except Exception, ex: |
| 97 | - ret = Error.system_parse_json | ||
| 98 | - trace("parse the request to json failed, req=%s, ex=%s, ret=%s"%(req, ex, ret)) | ||
| 99 | - return str(ret) | 109 | + code = Error.system_parse_json |
| 110 | + trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code)) | ||
| 111 | + return str(code) | ||
| 100 | 112 | ||
| 101 | - trace("srs on_connect: client ip=%s, vhost=%s, app=%s, pageUrl=%s"%( | ||
| 102 | - json_req["ip"], json_req["vhost"], json_req["app"], json_req["pageUrl"] | 113 | + action = json_req["action"] |
| 114 | + if action == "on_connect": | ||
| 115 | + code = self.__on_connect(json_req) | ||
| 116 | + elif action == "on_close": | ||
| 117 | + code = self.__on_close(json_req) | ||
| 118 | + else: | ||
| 119 | + trace("invalid request action: %s"%(json_req["action"])) | ||
| 120 | + code = Error.request_invalid_action | ||
| 121 | + | ||
| 122 | + return str(code) | ||
| 123 | + | ||
| 124 | + def OPTIONS(self): | ||
| 125 | + enable_crossdomain() | ||
| 126 | + | ||
| 127 | + def __on_connect(self, req): | ||
| 128 | + code = Error.success | ||
| 129 | + | ||
| 130 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, pageUrl=%s"%( | ||
| 131 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["pageUrl"] | ||
| 132 | + )) | ||
| 133 | + | ||
| 134 | + # TODO: process the on_connect event | ||
| 135 | + | ||
| 136 | + return code | ||
| 137 | + | ||
| 138 | + def __on_close(self, req): | ||
| 139 | + code = Error.success | ||
| 140 | + | ||
| 141 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s"%( | ||
| 142 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"] | ||
| 143 | + )) | ||
| 144 | + | ||
| 145 | + # TODO: process the on_close event | ||
| 146 | + | ||
| 147 | + return code | ||
| 148 | + | ||
| 149 | +''' | ||
| 150 | +handle the streams requests: publish/unpublish stream. | ||
| 151 | +''' | ||
| 152 | +class RESTStreams(object): | ||
| 153 | + exposed = True | ||
| 154 | + | ||
| 155 | + def GET(self): | ||
| 156 | + enable_crossdomain() | ||
| 157 | + | ||
| 158 | + streams = {} | ||
| 159 | + return json.dumps(streams) | ||
| 160 | + | ||
| 161 | + ''' | ||
| 162 | + for SRS hook: on_publish/on_unpublish | ||
| 163 | + on_publish: | ||
| 164 | + when client(encoder) publish to vhost/app/stream, call the hook, | ||
| 165 | + the request in the POST data string is a object encode by json: | ||
| 166 | + { | ||
| 167 | + "action": "on_publish", | ||
| 168 | + "client_id": 1985, | ||
| 169 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 170 | + "stream": "livestream" | ||
| 171 | + } | ||
| 172 | + on_unpublish: | ||
| 173 | + when client(encoder) stop publish to vhost/app/stream, call the hook, | ||
| 174 | + the request in the POST data string is a object encode by json: | ||
| 175 | + { | ||
| 176 | + "action": "on_unpublish", | ||
| 177 | + "client_id": 1985, | ||
| 178 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 179 | + "stream": "livestream" | ||
| 180 | + } | ||
| 181 | + if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 182 | + an int value specifies the error code(0 corresponding to success): | ||
| 183 | + 0 | ||
| 184 | + ''' | ||
| 185 | + def POST(self): | ||
| 186 | + enable_crossdomain() | ||
| 187 | + | ||
| 188 | + # return the error code in str | ||
| 189 | + code = Error.success | ||
| 190 | + | ||
| 191 | + req = cherrypy.request.body.read() | ||
| 192 | + trace("post to streams, req=%s"%(req)) | ||
| 193 | + try: | ||
| 194 | + json_req = json.loads(req) | ||
| 195 | + except Exception, ex: | ||
| 196 | + code = Error.system_parse_json | ||
| 197 | + trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code)) | ||
| 198 | + return str(code) | ||
| 199 | + | ||
| 200 | + action = json_req["action"] | ||
| 201 | + if action == "on_publish": | ||
| 202 | + code = self.__on_publish(json_req) | ||
| 203 | + elif action == "on_unpublish": | ||
| 204 | + code = self.__on_unpublish(json_req) | ||
| 205 | + else: | ||
| 206 | + trace("invalid request action: %s"%(json_req["action"])) | ||
| 207 | + code = Error.request_invalid_action | ||
| 208 | + | ||
| 209 | + return str(code) | ||
| 210 | + | ||
| 211 | + def OPTIONS(self): | ||
| 212 | + enable_crossdomain() | ||
| 213 | + | ||
| 214 | + def __on_publish(self, req): | ||
| 215 | + code = Error.success | ||
| 216 | + | ||
| 217 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s"%( | ||
| 218 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"] | ||
| 103 | )) | 219 | )) |
| 104 | 220 | ||
| 105 | - # TODO: valid the client. | 221 | + # TODO: process the on_publish event |
| 222 | + | ||
| 223 | + return code | ||
| 224 | + | ||
| 225 | + def __on_unpublish(self, req): | ||
| 226 | + code = Error.success | ||
| 227 | + | ||
| 228 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s"%( | ||
| 229 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"] | ||
| 230 | + )) | ||
| 231 | + | ||
| 232 | + # TODO: process the on_unpublish event | ||
| 233 | + | ||
| 234 | + return code | ||
| 235 | + | ||
| 236 | +''' | ||
| 237 | +handle the sessions requests: client play/stop stream | ||
| 238 | +''' | ||
| 239 | +class RESTSessions(object): | ||
| 240 | + exposed = True | ||
| 241 | + | ||
| 242 | + def GET(self): | ||
| 243 | + enable_crossdomain() | ||
| 244 | + | ||
| 245 | + sessions = {} | ||
| 246 | + return json.dumps(sessions) | ||
| 247 | + | ||
| 248 | + ''' | ||
| 249 | + for SRS hook: on_play/on_stop | ||
| 250 | + on_play: | ||
| 251 | + when client(encoder) publish to vhost/app/stream, call the hook, | ||
| 252 | + the request in the POST data string is a object encode by json: | ||
| 253 | + { | ||
| 254 | + "action": "on_play", | ||
| 255 | + "client_id": 1985, | ||
| 256 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 257 | + "stream": "livestream" | ||
| 258 | + } | ||
| 259 | + on_stop: | ||
| 260 | + when client(encoder) stop publish to vhost/app/stream, call the hook, | ||
| 261 | + the request in the POST data string is a object encode by json: | ||
| 262 | + { | ||
| 263 | + "action": "on_stop", | ||
| 264 | + "client_id": 1985, | ||
| 265 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 266 | + "stream": "livestream" | ||
| 267 | + } | ||
| 268 | + if valid, the hook must return HTTP code 200(Stauts OK) and response | ||
| 269 | + an int value specifies the error code(0 corresponding to success): | ||
| 270 | + 0 | ||
| 271 | + ''' | ||
| 272 | + def POST(self): | ||
| 273 | + enable_crossdomain() | ||
| 274 | + | ||
| 275 | + # return the error code in str | ||
| 276 | + code = Error.success | ||
| 277 | + | ||
| 278 | + req = cherrypy.request.body.read() | ||
| 279 | + trace("post to sessions, req=%s"%(req)) | ||
| 280 | + try: | ||
| 281 | + json_req = json.loads(req) | ||
| 282 | + except Exception, ex: | ||
| 283 | + code = Error.system_parse_json | ||
| 284 | + trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code)) | ||
| 285 | + return str(code) | ||
| 286 | + | ||
| 287 | + action = json_req["action"] | ||
| 288 | + if action == "on_play": | ||
| 289 | + code = self.__on_play(json_req) | ||
| 290 | + elif action == "on_stop": | ||
| 291 | + code = self.__on_stop(json_req) | ||
| 292 | + else: | ||
| 293 | + trace("invalid request action: %s"%(json_req["action"])) | ||
| 294 | + code = Error.request_invalid_action | ||
| 106 | 295 | ||
| 107 | - trace("valid clients post request success.") | ||
| 108 | - return str(ret) | 296 | + return str(code) |
| 109 | 297 | ||
| 110 | def OPTIONS(self): | 298 | def OPTIONS(self): |
| 111 | enable_crossdomain() | 299 | enable_crossdomain() |
| 112 | 300 | ||
| 301 | + def __on_play(self, req): | ||
| 302 | + code = Error.success | ||
| 303 | + | ||
| 304 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s"%( | ||
| 305 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"] | ||
| 306 | + )) | ||
| 307 | + | ||
| 308 | + # TODO: process the on_play event | ||
| 309 | + | ||
| 310 | + return code | ||
| 311 | + | ||
| 312 | + def __on_stop(self, req): | ||
| 313 | + code = Error.success | ||
| 314 | + | ||
| 315 | + trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s"%( | ||
| 316 | + req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"] | ||
| 317 | + )) | ||
| 318 | + | ||
| 319 | + # TODO: process the on_stop event | ||
| 320 | + | ||
| 321 | + return code | ||
| 322 | + | ||
| 113 | # HTTP RESTful path. | 323 | # HTTP RESTful path. |
| 114 | class Root(object): | 324 | class Root(object): |
| 115 | def __init__(self): | 325 | def __init__(self): |
| @@ -123,6 +333,8 @@ class Api(object): | @@ -123,6 +333,8 @@ class Api(object): | ||
| 123 | class V1(object): | 333 | class V1(object): |
| 124 | def __init__(self): | 334 | def __init__(self): |
| 125 | self.clients = RESTClients() | 335 | self.clients = RESTClients() |
| 336 | + self.streams = RESTStreams() | ||
| 337 | + self.sessions = RESTSessions() | ||
| 126 | 338 | ||
| 127 | ''' | 339 | ''' |
| 128 | main code start. | 340 | main code start. |
| @@ -108,12 +108,16 @@ int SrsClient::do_cycle() | @@ -108,12 +108,16 @@ int SrsClient::do_cycle() | ||
| 108 | req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), | 108 | req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), |
| 109 | req->app.c_str()); | 109 | req->app.c_str()); |
| 110 | 110 | ||
| 111 | - if ((ret = refer->check(req->pageUrl, config->get_refer(req->vhost))) != ERROR_SUCCESS) { | ||
| 112 | - srs_error("check refer failed. ret=%d", ret); | ||
| 113 | - return ret; | ||
| 114 | - } | ||
| 115 | - srs_verbose("check refer success."); | ||
| 116 | - | 111 | + ret = service_cycle(); |
| 112 | + on_close(); | ||
| 113 | + | ||
| 114 | + return ret; | ||
| 115 | +} | ||
| 116 | + | ||
| 117 | +int SrsClient::service_cycle() | ||
| 118 | +{ | ||
| 119 | + int ret = ERROR_SUCCESS; | ||
| 120 | + | ||
| 117 | if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) { | 121 | if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) { |
| 118 | srs_error("set window acknowledgement size failed. ret=%d", ret); | 122 | srs_error("set window acknowledgement size failed. ret=%d", ret); |
| 119 | return ret; | 123 | return ret; |
| @@ -188,8 +192,14 @@ int SrsClient::do_cycle() | @@ -188,8 +192,14 @@ int SrsClient::do_cycle() | ||
| 188 | srs_error("start to play stream failed. ret=%d", ret); | 192 | srs_error("start to play stream failed. ret=%d", ret); |
| 189 | return ret; | 193 | return ret; |
| 190 | } | 194 | } |
| 195 | + if ((ret = on_play()) != ERROR_SUCCESS) { | ||
| 196 | + srs_error("http hook on_play failed. ret=%d", ret); | ||
| 197 | + return ret; | ||
| 198 | + } | ||
| 191 | srs_info("start to play stream %s success", req->stream.c_str()); | 199 | srs_info("start to play stream %s success", req->stream.c_str()); |
| 192 | - return playing(source); | 200 | + ret = playing(source); |
| 201 | + on_stop(); | ||
| 202 | + return ret; | ||
| 193 | } | 203 | } |
| 194 | case SrsClientFMLEPublish: { | 204 | case SrsClientFMLEPublish: { |
| 195 | srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); | 205 | srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); |
| @@ -198,9 +208,14 @@ int SrsClient::do_cycle() | @@ -198,9 +208,14 @@ int SrsClient::do_cycle() | ||
| 198 | srs_error("start to publish stream failed. ret=%d", ret); | 208 | srs_error("start to publish stream failed. ret=%d", ret); |
| 199 | return ret; | 209 | return ret; |
| 200 | } | 210 | } |
| 211 | + if ((ret = on_publish()) != ERROR_SUCCESS) { | ||
| 212 | + srs_error("http hook on_publish failed. ret=%d", ret); | ||
| 213 | + return ret; | ||
| 214 | + } | ||
| 201 | srs_info("start to publish stream %s success", req->stream.c_str()); | 215 | srs_info("start to publish stream %s success", req->stream.c_str()); |
| 202 | ret = publish(source, true); | 216 | ret = publish(source, true); |
| 203 | source->on_unpublish(); | 217 | source->on_unpublish(); |
| 218 | + on_unpublish(); | ||
| 204 | return ret; | 219 | return ret; |
| 205 | } | 220 | } |
| 206 | case SrsClientFlashPublish: { | 221 | case SrsClientFlashPublish: { |
| @@ -210,9 +225,14 @@ int SrsClient::do_cycle() | @@ -210,9 +225,14 @@ int SrsClient::do_cycle() | ||
| 210 | srs_error("flash start to publish stream failed. ret=%d", ret); | 225 | srs_error("flash start to publish stream failed. ret=%d", ret); |
| 211 | return ret; | 226 | return ret; |
| 212 | } | 227 | } |
| 228 | + if ((ret = on_publish()) != ERROR_SUCCESS) { | ||
| 229 | + srs_error("http hook on_publish failed. ret=%d", ret); | ||
| 230 | + return ret; | ||
| 231 | + } | ||
| 213 | srs_info("flash start to publish stream %s success", req->stream.c_str()); | 232 | srs_info("flash start to publish stream %s success", req->stream.c_str()); |
| 214 | ret = publish(source, false); | 233 | ret = publish(source, false); |
| 215 | source->on_unpublish(); | 234 | source->on_unpublish(); |
| 235 | + on_unpublish(); | ||
| 216 | return ret; | 236 | return ret; |
| 217 | } | 237 | } |
| 218 | default: { | 238 | default: { |
| @@ -249,22 +269,15 @@ int SrsClient::check_vhost() | @@ -249,22 +269,15 @@ int SrsClient::check_vhost() | ||
| 249 | req->vhost = vhost->arg0(); | 269 | req->vhost = vhost->arg0(); |
| 250 | } | 270 | } |
| 251 | 271 | ||
| 252 | -#ifdef SRS_HTTP | ||
| 253 | - // HTTP: on_connect | ||
| 254 | - SrsConfDirective* on_connect = config->get_vhost_on_connect(req->vhost); | ||
| 255 | - if (!on_connect) { | ||
| 256 | - srs_info("ignore the empty http callback: on_connect"); | 272 | + if ((ret = refer->check(req->pageUrl, config->get_refer(req->vhost))) != ERROR_SUCCESS) { |
| 273 | + srs_error("check refer failed. ret=%d", ret); | ||
| 257 | return ret; | 274 | return ret; |
| 258 | } | 275 | } |
| 276 | + srs_verbose("check refer success."); | ||
| 259 | 277 | ||
| 260 | - for (int i = 0; i < (int)on_connect->args.size(); i++) { | ||
| 261 | - std::string url = on_connect->args.at(i); | ||
| 262 | - if ((ret = http_hooks->on_connect(url, ip, req)) != ERROR_SUCCESS) { | ||
| 263 | - srs_error("hook client failed. url=%s, ret=%d", url.c_str(), ret); | ||
| 264 | - return ret; | ||
| 265 | - } | 278 | + if ((ret = on_connect()) != ERROR_SUCCESS) { |
| 279 | + return ret; | ||
| 266 | } | 280 | } |
| 267 | -#endif | ||
| 268 | 281 | ||
| 269 | return ret; | 282 | return ret; |
| 270 | } | 283 | } |
| @@ -545,3 +558,129 @@ int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* | @@ -545,3 +558,129 @@ int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* | ||
| 545 | return ret; | 558 | return ret; |
| 546 | } | 559 | } |
| 547 | 560 | ||
| 561 | +int SrsClient::on_connect() | ||
| 562 | +{ | ||
| 563 | + int ret = ERROR_SUCCESS; | ||
| 564 | + | ||
| 565 | +#ifdef SRS_HTTP | ||
| 566 | + // HTTP: on_connect | ||
| 567 | + SrsConfDirective* on_connect = config->get_vhost_on_connect(req->vhost); | ||
| 568 | + if (!on_connect) { | ||
| 569 | + srs_info("ignore the empty http callback: on_connect"); | ||
| 570 | + return ret; | ||
| 571 | + } | ||
| 572 | + | ||
| 573 | + for (int i = 0; i < (int)on_connect->args.size(); i++) { | ||
| 574 | + std::string url = on_connect->args.at(i); | ||
| 575 | + if ((ret = http_hooks->on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) { | ||
| 576 | + srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret); | ||
| 577 | + return ret; | ||
| 578 | + } | ||
| 579 | + } | ||
| 580 | +#endif | ||
| 581 | + | ||
| 582 | + return ret; | ||
| 583 | +} | ||
| 584 | + | ||
| 585 | +void SrsClient::on_close() | ||
| 586 | +{ | ||
| 587 | +#ifdef SRS_HTTP | ||
| 588 | + // whatever the ret code, notify the api hooks. | ||
| 589 | + // HTTP: on_close | ||
| 590 | + SrsConfDirective* on_close = config->get_vhost_on_close(req->vhost); | ||
| 591 | + if (!on_close) { | ||
| 592 | + srs_info("ignore the empty http callback: on_close"); | ||
| 593 | + return; | ||
| 594 | + } | ||
| 595 | + | ||
| 596 | + for (int i = 0; i < (int)on_close->args.size(); i++) { | ||
| 597 | + std::string url = on_close->args.at(i); | ||
| 598 | + http_hooks->on_close(url, connection_id, ip, req); | ||
| 599 | + } | ||
| 600 | +#endif | ||
| 601 | +} | ||
| 602 | + | ||
| 603 | +int SrsClient::on_publish() | ||
| 604 | +{ | ||
| 605 | + int ret = ERROR_SUCCESS; | ||
| 606 | + | ||
| 607 | +#ifdef SRS_HTTP | ||
| 608 | + // HTTP: on_publish | ||
| 609 | + SrsConfDirective* on_publish = config->get_vhost_on_publish(req->vhost); | ||
| 610 | + if (!on_publish) { | ||
| 611 | + srs_info("ignore the empty http callback: on_publish"); | ||
| 612 | + return ret; | ||
| 613 | + } | ||
| 614 | + | ||
| 615 | + for (int i = 0; i < (int)on_publish->args.size(); i++) { | ||
| 616 | + std::string url = on_publish->args.at(i); | ||
| 617 | + if ((ret = http_hooks->on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) { | ||
| 618 | + srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret); | ||
| 619 | + return ret; | ||
| 620 | + } | ||
| 621 | + } | ||
| 622 | +#endif | ||
| 623 | + | ||
| 624 | + return ret; | ||
| 625 | +} | ||
| 626 | + | ||
| 627 | +void SrsClient::on_unpublish() | ||
| 628 | +{ | ||
| 629 | +#ifdef SRS_HTTP | ||
| 630 | + // whatever the ret code, notify the api hooks. | ||
| 631 | + // HTTP: on_unpublish | ||
| 632 | + SrsConfDirective* on_unpublish = config->get_vhost_on_unpublish(req->vhost); | ||
| 633 | + if (!on_unpublish) { | ||
| 634 | + srs_info("ignore the empty http callback: on_unpublish"); | ||
| 635 | + return; | ||
| 636 | + } | ||
| 637 | + | ||
| 638 | + for (int i = 0; i < (int)on_unpublish->args.size(); i++) { | ||
| 639 | + std::string url = on_unpublish->args.at(i); | ||
| 640 | + http_hooks->on_unpublish(url, connection_id, ip, req); | ||
| 641 | + } | ||
| 642 | +#endif | ||
| 643 | +} | ||
| 644 | + | ||
| 645 | +int SrsClient::on_play() | ||
| 646 | +{ | ||
| 647 | + int ret = ERROR_SUCCESS; | ||
| 648 | + | ||
| 649 | +#ifdef SRS_HTTP | ||
| 650 | + // HTTP: on_play | ||
| 651 | + SrsConfDirective* on_play = config->get_vhost_on_play(req->vhost); | ||
| 652 | + if (!on_play) { | ||
| 653 | + srs_info("ignore the empty http callback: on_play"); | ||
| 654 | + return ret; | ||
| 655 | + } | ||
| 656 | + | ||
| 657 | + for (int i = 0; i < (int)on_play->args.size(); i++) { | ||
| 658 | + std::string url = on_play->args.at(i); | ||
| 659 | + if ((ret = http_hooks->on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) { | ||
| 660 | + srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret); | ||
| 661 | + return ret; | ||
| 662 | + } | ||
| 663 | + } | ||
| 664 | +#endif | ||
| 665 | + | ||
| 666 | + return ret; | ||
| 667 | +} | ||
| 668 | + | ||
| 669 | +void SrsClient::on_stop() | ||
| 670 | +{ | ||
| 671 | +#ifdef SRS_HTTP | ||
| 672 | + // whatever the ret code, notify the api hooks. | ||
| 673 | + // HTTP: on_stop | ||
| 674 | + SrsConfDirective* on_stop = config->get_vhost_on_stop(req->vhost); | ||
| 675 | + if (!on_stop) { | ||
| 676 | + srs_info("ignore the empty http callback: on_stop"); | ||
| 677 | + return; | ||
| 678 | + } | ||
| 679 | + | ||
| 680 | + for (int i = 0; i < (int)on_stop->args.size(); i++) { | ||
| 681 | + std::string url = on_stop->args.at(i); | ||
| 682 | + http_hooks->on_stop(url, connection_id, ip, req); | ||
| 683 | + } | ||
| 684 | +#endif | ||
| 685 | +} | ||
| 686 | + |
| @@ -63,12 +63,21 @@ public: | @@ -63,12 +63,21 @@ public: | ||
| 63 | protected: | 63 | protected: |
| 64 | virtual int do_cycle(); | 64 | virtual int do_cycle(); |
| 65 | private: | 65 | private: |
| 66 | + // when valid and connected to vhost/app, service the client. | ||
| 67 | + virtual int service_cycle(); | ||
| 66 | virtual int check_vhost(); | 68 | virtual int check_vhost(); |
| 67 | virtual int playing(SrsSource* source); | 69 | virtual int playing(SrsSource* source); |
| 68 | virtual int publish(SrsSource* source, bool is_fmle); | 70 | virtual int publish(SrsSource* source, bool is_fmle); |
| 69 | virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle); | 71 | virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle); |
| 70 | virtual int get_peer_ip(); | 72 | virtual int get_peer_ip(); |
| 71 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); | 73 | virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); |
| 74 | +private: | ||
| 75 | + virtual int on_connect(); | ||
| 76 | + virtual void on_close(); | ||
| 77 | + virtual int on_publish(); | ||
| 78 | + virtual void on_unpublish(); | ||
| 79 | + virtual int on_play(); | ||
| 80 | + virtual void on_stop(); | ||
| 72 | }; | 81 | }; |
| 73 | 82 | ||
| 74 | #endif | 83 | #endif |
| @@ -578,6 +578,86 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) | @@ -578,6 +578,86 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) | ||
| 578 | return conf->get("on_connect"); | 578 | return conf->get("on_connect"); |
| 579 | } | 579 | } |
| 580 | 580 | ||
| 581 | +SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) | ||
| 582 | +{ | ||
| 583 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 584 | + | ||
| 585 | + if (!conf) { | ||
| 586 | + return NULL; | ||
| 587 | + } | ||
| 588 | + | ||
| 589 | + conf = conf->get("http_hooks"); | ||
| 590 | + if (!conf) { | ||
| 591 | + return NULL; | ||
| 592 | + } | ||
| 593 | + | ||
| 594 | + return conf->get("on_close"); | ||
| 595 | +} | ||
| 596 | + | ||
| 597 | +SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) | ||
| 598 | +{ | ||
| 599 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 600 | + | ||
| 601 | + if (!conf) { | ||
| 602 | + return NULL; | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + conf = conf->get("http_hooks"); | ||
| 606 | + if (!conf) { | ||
| 607 | + return NULL; | ||
| 608 | + } | ||
| 609 | + | ||
| 610 | + return conf->get("on_publish"); | ||
| 611 | +} | ||
| 612 | + | ||
| 613 | +SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) | ||
| 614 | +{ | ||
| 615 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 616 | + | ||
| 617 | + if (!conf) { | ||
| 618 | + return NULL; | ||
| 619 | + } | ||
| 620 | + | ||
| 621 | + conf = conf->get("http_hooks"); | ||
| 622 | + if (!conf) { | ||
| 623 | + return NULL; | ||
| 624 | + } | ||
| 625 | + | ||
| 626 | + return conf->get("on_unpublish"); | ||
| 627 | +} | ||
| 628 | + | ||
| 629 | +SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) | ||
| 630 | +{ | ||
| 631 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 632 | + | ||
| 633 | + if (!conf) { | ||
| 634 | + return NULL; | ||
| 635 | + } | ||
| 636 | + | ||
| 637 | + conf = conf->get("http_hooks"); | ||
| 638 | + if (!conf) { | ||
| 639 | + return NULL; | ||
| 640 | + } | ||
| 641 | + | ||
| 642 | + return conf->get("on_play"); | ||
| 643 | +} | ||
| 644 | + | ||
| 645 | +SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) | ||
| 646 | +{ | ||
| 647 | + SrsConfDirective* conf = get_vhost(vhost); | ||
| 648 | + | ||
| 649 | + if (!conf) { | ||
| 650 | + return NULL; | ||
| 651 | + } | ||
| 652 | + | ||
| 653 | + conf = conf->get("http_hooks"); | ||
| 654 | + if (!conf) { | ||
| 655 | + return NULL; | ||
| 656 | + } | ||
| 657 | + | ||
| 658 | + return conf->get("on_stop"); | ||
| 659 | +} | ||
| 660 | + | ||
| 581 | bool SrsConfig::get_vhost_enabled(std::string vhost) | 661 | bool SrsConfig::get_vhost_enabled(std::string vhost) |
| 582 | { | 662 | { |
| 583 | SrsConfDirective* vhost_conf = get_vhost(vhost); | 663 | SrsConfDirective* vhost_conf = get_vhost(vhost); |
| @@ -120,6 +120,11 @@ public: | @@ -120,6 +120,11 @@ public: | ||
| 120 | virtual SrsConfDirective* get_vhost(std::string vhost); | 120 | virtual SrsConfDirective* get_vhost(std::string vhost); |
| 121 | virtual bool get_vhost_enabled(std::string vhost); | 121 | virtual bool get_vhost_enabled(std::string vhost); |
| 122 | virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); | 122 | virtual SrsConfDirective* get_vhost_on_connect(std::string vhost); |
| 123 | + virtual SrsConfDirective* get_vhost_on_close(std::string vhost); | ||
| 124 | + virtual SrsConfDirective* get_vhost_on_publish(std::string vhost); | ||
| 125 | + virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost); | ||
| 126 | + virtual SrsConfDirective* get_vhost_on_play(std::string vhost); | ||
| 127 | + virtual SrsConfDirective* get_vhost_on_stop(std::string vhost); | ||
| 123 | virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); | 128 | virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); |
| 124 | virtual bool get_transcode_enabled(SrsConfDirective* transcode); | 129 | virtual bool get_transcode_enabled(SrsConfDirective* transcode); |
| 125 | virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); | 130 | virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); |
| @@ -31,6 +31,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | @@ -31,6 +31,7 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) | ||
| 31 | { | 31 | { |
| 32 | server = srs_server; | 32 | server = srs_server; |
| 33 | stfd = client_stfd; | 33 | stfd = client_stfd; |
| 34 | + connection_id = 0; | ||
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | SrsConnection::~SrsConnection() | 37 | SrsConnection::~SrsConnection() |
| @@ -65,6 +66,8 @@ void SrsConnection::cycle() | @@ -65,6 +66,8 @@ void SrsConnection::cycle() | ||
| 65 | int ret = ERROR_SUCCESS; | 66 | int ret = ERROR_SUCCESS; |
| 66 | 67 | ||
| 67 | log_context->generate_id(); | 68 | log_context->generate_id(); |
| 69 | + connection_id = log_context->get_id(); | ||
| 70 | + | ||
| 68 | ret = do_cycle(); | 71 | ret = do_cycle(); |
| 69 | 72 | ||
| 70 | // if socket io error, set to closed. | 73 | // if socket io error, set to closed. |
| @@ -38,6 +38,7 @@ class SrsConnection | @@ -38,6 +38,7 @@ class SrsConnection | ||
| 38 | protected: | 38 | protected: |
| 39 | SrsServer* server; | 39 | SrsServer* server; |
| 40 | st_netfd_t stfd; | 40 | st_netfd_t stfd; |
| 41 | + int connection_id; | ||
| 41 | public: | 42 | public: |
| 42 | SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); | 43 | SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd); |
| 43 | virtual ~SrsConnection(); | 44 | virtual ~SrsConnection(); |
| @@ -400,25 +400,35 @@ SrsHttpHooks::~SrsHttpHooks() | @@ -400,25 +400,35 @@ SrsHttpHooks::~SrsHttpHooks() | ||
| 400 | { | 400 | { |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | -int SrsHttpHooks::on_connect(std::string url, std::string ip, SrsRequest* req) | 403 | +int SrsHttpHooks::on_connect(std::string url, int client_id, std::string ip, SrsRequest* req) |
| 404 | { | 404 | { |
| 405 | int ret = ERROR_SUCCESS; | 405 | int ret = ERROR_SUCCESS; |
| 406 | 406 | ||
| 407 | SrsHttpUri uri; | 407 | SrsHttpUri uri; |
| 408 | if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | 408 | if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { |
| 409 | - srs_error("http uri parse url failed. " | ||
| 410 | - "url=%s, ret=%d", url.c_str(), ret); | 409 | + srs_error("http uri parse on_connect url failed. " |
| 410 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 411 | return ret; | 411 | return ret; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | /** | 414 | /** |
| 415 | { | 415 | { |
| 416 | + "action": "on_connect", | ||
| 417 | + "client_id": 1985, | ||
| 416 | "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | 418 | "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", |
| 417 | "pageUrl": "http://www.test.com/live.html" | 419 | "pageUrl": "http://www.test.com/live.html" |
| 418 | } | 420 | } |
| 419 | */ | 421 | */ |
| 420 | std::stringstream ss; | 422 | std::stringstream ss; |
| 421 | ss << "{" | 423 | ss << "{" |
| 424 | + // action | ||
| 425 | + << '"' << "action" << '"' << ':' | ||
| 426 | + << '"' << "on_connect" << '"' | ||
| 427 | + << ',' | ||
| 428 | + // client_id | ||
| 429 | + << '"' << "client_id" << '"' << ':' | ||
| 430 | + << std::dec << client_id | ||
| 431 | + << ',' | ||
| 422 | // ip | 432 | // ip |
| 423 | << '"' << "ip" << '"' << ':' | 433 | << '"' << "ip" << '"' << ':' |
| 424 | << '"' << ip << '"' | 434 | << '"' << ip << '"' |
| @@ -441,24 +451,375 @@ int SrsHttpHooks::on_connect(std::string url, std::string ip, SrsRequest* req) | @@ -441,24 +451,375 @@ int SrsHttpHooks::on_connect(std::string url, std::string ip, SrsRequest* req) | ||
| 441 | 451 | ||
| 442 | SrsHttpClient http; | 452 | SrsHttpClient http; |
| 443 | if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | 453 | if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { |
| 444 | - srs_error("http post uri failed. " | ||
| 445 | - "url=%s, request=%s, response=%s, ret=%d", | ||
| 446 | - url.c_str(), data.c_str(), res.c_str(), ret); | 454 | + srs_error("http post on_connect uri failed. " |
| 455 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 456 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 447 | return ret; | 457 | return ret; |
| 448 | } | 458 | } |
| 449 | 459 | ||
| 450 | if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | 460 | if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { |
| 451 | ret = ERROR_HTTP_DATA_INVLIAD; | 461 | ret = ERROR_HTTP_DATA_INVLIAD; |
| 452 | - srs_error("http hook validate failed. " | ||
| 453 | - "res=%s, ret=%d", res.c_str(), ret); | 462 | + srs_error("http hook on_connect validate failed. " |
| 463 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 454 | return ret; | 464 | return ret; |
| 455 | } | 465 | } |
| 456 | 466 | ||
| 457 | srs_trace("http hook on_connect success. " | 467 | srs_trace("http hook on_connect success. " |
| 458 | - "url=%s, request=%s, response=%s, ret=%d", | ||
| 459 | - url.c_str(), data.c_str(), res.c_str(), ret); | 468 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", |
| 469 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 460 | 470 | ||
| 461 | return ret; | 471 | return ret; |
| 462 | } | 472 | } |
| 463 | 473 | ||
| 474 | +void SrsHttpHooks::on_close(std::string url, int client_id, std::string ip, SrsRequest* req) | ||
| 475 | +{ | ||
| 476 | + int ret = ERROR_SUCCESS; | ||
| 477 | + | ||
| 478 | + SrsHttpUri uri; | ||
| 479 | + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | ||
| 480 | + srs_warn("http uri parse on_close url failed, ignored. " | ||
| 481 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 482 | + return; | ||
| 483 | + } | ||
| 484 | + | ||
| 485 | + /** | ||
| 486 | + { | ||
| 487 | + "action": "on_close", | ||
| 488 | + "client_id": 1985, | ||
| 489 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 490 | + "stream": "livestream" | ||
| 491 | + } | ||
| 492 | + */ | ||
| 493 | + std::stringstream ss; | ||
| 494 | + ss << "{" | ||
| 495 | + // action | ||
| 496 | + << '"' << "action" << '"' << ':' | ||
| 497 | + << '"' << "on_close" << '"' | ||
| 498 | + << ',' | ||
| 499 | + // client_id | ||
| 500 | + << '"' << "client_id" << '"' << ':' | ||
| 501 | + << std::dec << client_id | ||
| 502 | + << ',' | ||
| 503 | + // ip | ||
| 504 | + << '"' << "ip" << '"' << ':' | ||
| 505 | + << '"' << ip << '"' | ||
| 506 | + << ',' | ||
| 507 | + // vhost | ||
| 508 | + << '"' << "vhost" << '"' << ':' | ||
| 509 | + << '"' << req->vhost << '"' | ||
| 510 | + << ',' | ||
| 511 | + // app | ||
| 512 | + << '"' << "app" << '"' << ':' | ||
| 513 | + << '"' << req->app << '"' | ||
| 514 | + //<< ',' | ||
| 515 | + << "}"; | ||
| 516 | + std::string data = ss.str(); | ||
| 517 | + std::string res; | ||
| 518 | + | ||
| 519 | + SrsHttpClient http; | ||
| 520 | + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | ||
| 521 | + srs_warn("http post on_close uri failed, ignored. " | ||
| 522 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 523 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 524 | + return; | ||
| 525 | + } | ||
| 526 | + | ||
| 527 | + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | ||
| 528 | + ret = ERROR_HTTP_DATA_INVLIAD; | ||
| 529 | + srs_warn("http hook on_close validate failed, ignored. " | ||
| 530 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 531 | + return; | ||
| 532 | + } | ||
| 533 | + | ||
| 534 | + srs_trace("http hook on_close success. " | ||
| 535 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 536 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 537 | + | ||
| 538 | + return; | ||
| 539 | +} | ||
| 540 | + | ||
| 541 | +int SrsHttpHooks::on_publish(std::string url, int client_id, std::string ip, SrsRequest* req) | ||
| 542 | +{ | ||
| 543 | + int ret = ERROR_SUCCESS; | ||
| 544 | + | ||
| 545 | + SrsHttpUri uri; | ||
| 546 | + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | ||
| 547 | + srs_error("http uri parse on_publish url failed. " | ||
| 548 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 549 | + return ret; | ||
| 550 | + } | ||
| 551 | + | ||
| 552 | + /** | ||
| 553 | + { | ||
| 554 | + "action": "on_publish", | ||
| 555 | + "client_id": 1985, | ||
| 556 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 557 | + "stream": "livestream" | ||
| 558 | + } | ||
| 559 | + */ | ||
| 560 | + std::stringstream ss; | ||
| 561 | + ss << "{" | ||
| 562 | + // action | ||
| 563 | + << '"' << "action" << '"' << ':' | ||
| 564 | + << '"' << "on_publish" << '"' | ||
| 565 | + << ',' | ||
| 566 | + // client_id | ||
| 567 | + << '"' << "client_id" << '"' << ':' | ||
| 568 | + << std::dec << client_id | ||
| 569 | + << ',' | ||
| 570 | + // ip | ||
| 571 | + << '"' << "ip" << '"' << ':' | ||
| 572 | + << '"' << ip << '"' | ||
| 573 | + << ',' | ||
| 574 | + // vhost | ||
| 575 | + << '"' << "vhost" << '"' << ':' | ||
| 576 | + << '"' << req->vhost << '"' | ||
| 577 | + << ',' | ||
| 578 | + // app | ||
| 579 | + << '"' << "app" << '"' << ':' | ||
| 580 | + << '"' << req->app << '"' | ||
| 581 | + << ',' | ||
| 582 | + // stream | ||
| 583 | + << '"' << "stream" << '"' << ':' | ||
| 584 | + << '"' << req->stream << '"' | ||
| 585 | + //<< ',' | ||
| 586 | + << "}"; | ||
| 587 | + std::string data = ss.str(); | ||
| 588 | + std::string res; | ||
| 589 | + | ||
| 590 | + SrsHttpClient http; | ||
| 591 | + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | ||
| 592 | + srs_error("http post on_publish uri failed. " | ||
| 593 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 594 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 595 | + return ret; | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | ||
| 599 | + ret = ERROR_HTTP_DATA_INVLIAD; | ||
| 600 | + srs_error("http hook on_publish validate failed. " | ||
| 601 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 602 | + return ret; | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + srs_trace("http hook on_publish success. " | ||
| 606 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 607 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 608 | + | ||
| 609 | + return ret; | ||
| 610 | +} | ||
| 611 | + | ||
| 612 | +void SrsHttpHooks::on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req) | ||
| 613 | +{ | ||
| 614 | + int ret = ERROR_SUCCESS; | ||
| 615 | + | ||
| 616 | + SrsHttpUri uri; | ||
| 617 | + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | ||
| 618 | + srs_warn("http uri parse on_unpublish url failed, ignored. " | ||
| 619 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 620 | + return; | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + /** | ||
| 624 | + { | ||
| 625 | + "action": "on_unpublish", | ||
| 626 | + "client_id": 1985, | ||
| 627 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 628 | + "stream": "livestream" | ||
| 629 | + } | ||
| 630 | + */ | ||
| 631 | + std::stringstream ss; | ||
| 632 | + ss << "{" | ||
| 633 | + // action | ||
| 634 | + << '"' << "action" << '"' << ':' | ||
| 635 | + << '"' << "on_unpublish" << '"' | ||
| 636 | + << ',' | ||
| 637 | + // client_id | ||
| 638 | + << '"' << "client_id" << '"' << ':' | ||
| 639 | + << std::dec << client_id | ||
| 640 | + << ',' | ||
| 641 | + // ip | ||
| 642 | + << '"' << "ip" << '"' << ':' | ||
| 643 | + << '"' << ip << '"' | ||
| 644 | + << ',' | ||
| 645 | + // vhost | ||
| 646 | + << '"' << "vhost" << '"' << ':' | ||
| 647 | + << '"' << req->vhost << '"' | ||
| 648 | + << ',' | ||
| 649 | + // app | ||
| 650 | + << '"' << "app" << '"' << ':' | ||
| 651 | + << '"' << req->app << '"' | ||
| 652 | + << ',' | ||
| 653 | + // stream | ||
| 654 | + << '"' << "stream" << '"' << ':' | ||
| 655 | + << '"' << req->stream << '"' | ||
| 656 | + //<< ',' | ||
| 657 | + << "}"; | ||
| 658 | + std::string data = ss.str(); | ||
| 659 | + std::string res; | ||
| 660 | + | ||
| 661 | + SrsHttpClient http; | ||
| 662 | + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | ||
| 663 | + srs_warn("http post on_unpublish uri failed, ignored. " | ||
| 664 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 665 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 666 | + return; | ||
| 667 | + } | ||
| 668 | + | ||
| 669 | + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | ||
| 670 | + ret = ERROR_HTTP_DATA_INVLIAD; | ||
| 671 | + srs_warn("http hook on_unpublish validate failed, ignored. " | ||
| 672 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 673 | + return; | ||
| 674 | + } | ||
| 675 | + | ||
| 676 | + srs_trace("http hook on_unpublish success. " | ||
| 677 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 678 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 679 | + | ||
| 680 | + return; | ||
| 681 | +} | ||
| 682 | + | ||
| 683 | +int SrsHttpHooks::on_play(std::string url, int client_id, std::string ip, SrsRequest* req) | ||
| 684 | +{ | ||
| 685 | + int ret = ERROR_SUCCESS; | ||
| 686 | + | ||
| 687 | + SrsHttpUri uri; | ||
| 688 | + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | ||
| 689 | + srs_error("http uri parse on_play url failed. " | ||
| 690 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 691 | + return ret; | ||
| 692 | + } | ||
| 693 | + | ||
| 694 | + /** | ||
| 695 | + { | ||
| 696 | + "action": "on_play", | ||
| 697 | + "client_id": 1985, | ||
| 698 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 699 | + "stream": "livestream" | ||
| 700 | + } | ||
| 701 | + */ | ||
| 702 | + std::stringstream ss; | ||
| 703 | + ss << "{" | ||
| 704 | + // action | ||
| 705 | + << '"' << "action" << '"' << ':' | ||
| 706 | + << '"' << "on_play" << '"' | ||
| 707 | + << ',' | ||
| 708 | + // client_id | ||
| 709 | + << '"' << "client_id" << '"' << ':' | ||
| 710 | + << std::dec << client_id | ||
| 711 | + << ',' | ||
| 712 | + // ip | ||
| 713 | + << '"' << "ip" << '"' << ':' | ||
| 714 | + << '"' << ip << '"' | ||
| 715 | + << ',' | ||
| 716 | + // vhost | ||
| 717 | + << '"' << "vhost" << '"' << ':' | ||
| 718 | + << '"' << req->vhost << '"' | ||
| 719 | + << ',' | ||
| 720 | + // app | ||
| 721 | + << '"' << "app" << '"' << ':' | ||
| 722 | + << '"' << req->app << '"' | ||
| 723 | + << ',' | ||
| 724 | + // stream | ||
| 725 | + << '"' << "stream" << '"' << ':' | ||
| 726 | + << '"' << req->stream << '"' | ||
| 727 | + //<< ',' | ||
| 728 | + << "}"; | ||
| 729 | + std::string data = ss.str(); | ||
| 730 | + std::string res; | ||
| 731 | + | ||
| 732 | + SrsHttpClient http; | ||
| 733 | + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | ||
| 734 | + srs_error("http post on_play uri failed. " | ||
| 735 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 736 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 737 | + return ret; | ||
| 738 | + } | ||
| 739 | + | ||
| 740 | + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | ||
| 741 | + ret = ERROR_HTTP_DATA_INVLIAD; | ||
| 742 | + srs_error("http hook on_play validate failed. " | ||
| 743 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 744 | + return ret; | ||
| 745 | + } | ||
| 746 | + | ||
| 747 | + srs_trace("http hook on_play success. " | ||
| 748 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 749 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 750 | + | ||
| 751 | + return ret; | ||
| 752 | +} | ||
| 753 | + | ||
| 754 | +void SrsHttpHooks::on_stop(std::string url, int client_id, std::string ip, SrsRequest* req) | ||
| 755 | +{ | ||
| 756 | + int ret = ERROR_SUCCESS; | ||
| 757 | + | ||
| 758 | + SrsHttpUri uri; | ||
| 759 | + if ((ret = uri.initialize(url)) != ERROR_SUCCESS) { | ||
| 760 | + srs_warn("http uri parse on_stop url failed, ignored. " | ||
| 761 | + "client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret); | ||
| 762 | + return; | ||
| 763 | + } | ||
| 764 | + | ||
| 765 | + /** | ||
| 766 | + { | ||
| 767 | + "action": "on_stop", | ||
| 768 | + "client_id": 1985, | ||
| 769 | + "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live", | ||
| 770 | + "stream": "livestream" | ||
| 771 | + } | ||
| 772 | + */ | ||
| 773 | + std::stringstream ss; | ||
| 774 | + ss << "{" | ||
| 775 | + // action | ||
| 776 | + << '"' << "action" << '"' << ':' | ||
| 777 | + << '"' << "on_stop" << '"' | ||
| 778 | + << ',' | ||
| 779 | + // client_id | ||
| 780 | + << '"' << "client_id" << '"' << ':' | ||
| 781 | + << std::dec << client_id | ||
| 782 | + << ',' | ||
| 783 | + // ip | ||
| 784 | + << '"' << "ip" << '"' << ':' | ||
| 785 | + << '"' << ip << '"' | ||
| 786 | + << ',' | ||
| 787 | + // vhost | ||
| 788 | + << '"' << "vhost" << '"' << ':' | ||
| 789 | + << '"' << req->vhost << '"' | ||
| 790 | + << ',' | ||
| 791 | + // app | ||
| 792 | + << '"' << "app" << '"' << ':' | ||
| 793 | + << '"' << req->app << '"' | ||
| 794 | + << ',' | ||
| 795 | + // stream | ||
| 796 | + << '"' << "stream" << '"' << ':' | ||
| 797 | + << '"' << req->stream << '"' | ||
| 798 | + //<< ',' | ||
| 799 | + << "}"; | ||
| 800 | + std::string data = ss.str(); | ||
| 801 | + std::string res; | ||
| 802 | + | ||
| 803 | + SrsHttpClient http; | ||
| 804 | + if ((ret = http.post(&uri, data, res)) != ERROR_SUCCESS) { | ||
| 805 | + srs_warn("http post on_stop uri failed, ignored. " | ||
| 806 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 807 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 808 | + return; | ||
| 809 | + } | ||
| 810 | + | ||
| 811 | + if (res.empty() || res != SRS_HTTP_RESPONSE_OK) { | ||
| 812 | + ret = ERROR_HTTP_DATA_INVLIAD; | ||
| 813 | + srs_warn("http hook on_stop validate failed, ignored. " | ||
| 814 | + "client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret); | ||
| 815 | + return; | ||
| 816 | + } | ||
| 817 | + | ||
| 818 | + srs_trace("http hook on_stop success. " | ||
| 819 | + "client_id=%d, url=%s, request=%s, response=%s, ret=%d", | ||
| 820 | + client_id, url.c_str(), data.c_str(), res.c_str(), ret); | ||
| 821 | + | ||
| 822 | + return; | ||
| 823 | +} | ||
| 824 | + | ||
| 464 | #endif | 825 | #endif |
| @@ -120,12 +120,50 @@ public: | @@ -120,12 +120,50 @@ public: | ||
| 120 | virtual ~SrsHttpHooks(); | 120 | virtual ~SrsHttpHooks(); |
| 121 | public: | 121 | public: |
| 122 | /** | 122 | /** |
| 123 | - * on_connect hook, | 123 | + * on_connect hook, when client connect to srs. |
| 124 | + * @param client_id the id of client on server. | ||
| 124 | * @param url the api server url, to valid the client. | 125 | * @param url the api server url, to valid the client. |
| 125 | * ignore if empty. | 126 | * ignore if empty. |
| 126 | * @return valid failed or connect to the url failed. | 127 | * @return valid failed or connect to the url failed. |
| 127 | */ | 128 | */ |
| 128 | - virtual int on_connect(std::string url, std::string ip, SrsRequest* req); | 129 | + virtual int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req); |
| 130 | + /** | ||
| 131 | + * on_close hook, when client disconnect to srs, where client is valid by on_connect. | ||
| 132 | + * @param client_id the id of client on server. | ||
| 133 | + * @param url the api server url, to process the event. | ||
| 134 | + * ignore if empty. | ||
| 135 | + */ | ||
| 136 | + virtual void on_close(std::string url, int client_id, std::string ip, SrsRequest* req); | ||
| 137 | + /** | ||
| 138 | + * on_publish hook, when client(encoder) start to publish stream | ||
| 139 | + * @param client_id the id of client on server. | ||
| 140 | + * @param url the api server url, to valid the client. | ||
| 141 | + * ignore if empty. | ||
| 142 | + * @return valid failed or connect to the url failed. | ||
| 143 | + */ | ||
| 144 | + virtual int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req); | ||
| 145 | + /** | ||
| 146 | + * on_unpublish hook, when client(encoder) stop publish stream. | ||
| 147 | + * @param client_id the id of client on server. | ||
| 148 | + * @param url the api server url, to process the event. | ||
| 149 | + * ignore if empty. | ||
| 150 | + */ | ||
| 151 | + virtual void on_unpublish(std::string url, int client_id, std::string ip, SrsRequest* req); | ||
| 152 | + /** | ||
| 153 | + * on_play hook, when client start to play stream. | ||
| 154 | + * @param client_id the id of client on server. | ||
| 155 | + * @param url the api server url, to valid the client. | ||
| 156 | + * ignore if empty. | ||
| 157 | + * @return valid failed or connect to the url failed. | ||
| 158 | + */ | ||
| 159 | + virtual int on_play(std::string url, int client_id, std::string ip, SrsRequest* req); | ||
| 160 | + /** | ||
| 161 | + * on_stop hook, when client stop to play the stream. | ||
| 162 | + * @param client_id the id of client on server. | ||
| 163 | + * @param url the api server url, to process the event. | ||
| 164 | + * ignore if empty. | ||
| 165 | + */ | ||
| 166 | + virtual void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req); | ||
| 129 | }; | 167 | }; |
| 130 | 168 | ||
| 131 | #endif | 169 | #endif |
-
请 注册 或 登录 后发表评论