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 |
-
请 注册 或 登录 后发表评论