|
@@ -33,63 +33,127 @@ if parentCtx == nil then
|
33
|
33
|
end
|
34
|
34
|
local token_util = module:require "token/util".new(parentCtx);
|
35
|
35
|
|
36
|
|
-local ASAPKeyServer
|
37
|
|
- = module:get_option_string("asap_key_server");
|
|
36
|
+local ASAPKeyServer;
|
|
37
|
+local ASAPKeyPath;
|
|
38
|
+local ASAPKeyId;
|
|
39
|
+local ASAPIssuer;
|
|
40
|
+local ASAPAudience;
|
|
41
|
+local ASAPAcceptedIssuers;
|
|
42
|
+local ASAPAcceptedAudiences;
|
|
43
|
+local ASAPTTL;
|
|
44
|
+local ASAPTTL_THRESHOLD;
|
|
45
|
+local ASAPKey;
|
|
46
|
+local JibriRegion;
|
|
47
|
+local disableTokenVerification;
|
|
48
|
+local muc_component_host;
|
|
49
|
+local external_api_url;
|
|
50
|
+local jwtKeyCacheSize;
|
|
51
|
+local jwtKeyCache;
|
|
52
|
+
|
|
53
|
+local function load_config()
|
|
54
|
+ ASAPKeyServer = module:get_option_string("asap_key_server");
|
|
55
|
+
|
|
56
|
+ if ASAPKeyServer then
|
|
57
|
+ module:log("debug", "ASAP Public Key URL %s", ASAPKeyServer);
|
|
58
|
+ token_util:set_asap_key_server(ASAPKeyServer);
|
|
59
|
+ end
|
38
|
60
|
|
39
|
|
-if ASAPKeyServer then
|
40
|
|
- module:log("debug", "ASAP Public Key URL %s", ASAPKeyServer);
|
41
|
|
- token_util:set_asap_key_server(ASAPKeyServer);
|
42
|
|
-end
|
|
61
|
+ ASAPKeyPath
|
|
62
|
+ = module:get_option_string("asap_key_path", '/etc/prosody/certs/asap.key');
|
43
|
63
|
|
44
|
|
-local ASAPKeyPath
|
45
|
|
- = module:get_option_string("asap_key_path", '/etc/prosody/certs/asap.key');
|
|
64
|
+ ASAPKeyId
|
|
65
|
+ = module:get_option_string("asap_key_id", 'jitsi');
|
46
|
66
|
|
47
|
|
-local ASAPKeyId
|
48
|
|
- = module:get_option_string("asap_key_id", 'jitsi');
|
|
67
|
+ ASAPIssuer
|
|
68
|
+ = module:get_option_string("asap_issuer", 'jitsi');
|
49
|
69
|
|
50
|
|
-local ASAPIssuer
|
51
|
|
- = module:get_option_string("asap_issuer", 'jitsi');
|
|
70
|
+ ASAPAudience
|
|
71
|
+ = module:get_option_string("asap_audience", 'jibri-queue');
|
52
|
72
|
|
53
|
|
-local ASAPAudience
|
54
|
|
- = module:get_option_string("asap_audience", 'jibri-queue');
|
|
73
|
+ ASAPAcceptedIssuers
|
|
74
|
+ = module:get_option_array('asap_accepted_issuers',{'jibri-queue'});
|
|
75
|
+ module:log("debug", "ASAP Accepted Issuers %s", ASAPAcceptedIssuers);
|
|
76
|
+ token_util:set_asap_accepted_issuers(ASAPAcceptedIssuers);
|
55
|
77
|
|
56
|
|
-local ASAPAcceptedIssuers
|
57
|
|
- = module:get_option_array('asap_accepted_issuers',{'jibri-queue'});
|
|
78
|
+ ASAPAcceptedAudiences
|
|
79
|
+ = module:get_option_array('asap_accepted_audiences',{'*'});
|
|
80
|
+ module:log("debug", "ASAP Accepted Audiences %s", ASAPAcceptedAudiences);
|
|
81
|
+ token_util:set_asap_accepted_audiences(ASAPAcceptedAudiences);
|
58
|
82
|
|
59
|
|
-module:log("debug", "ASAP Accepted Issuers %s", ASAPAcceptedIssuers);
|
60
|
|
-token_util:set_asap_accepted_issuers(ASAPAcceptedIssuers);
|
|
83
|
+ -- do not require room to be set on tokens for jibri queue
|
|
84
|
+ token_util:set_asap_require_room_claim(false);
|
61
|
85
|
|
62
|
|
-local ASAPAcceptedAudiences
|
63
|
|
- = module:get_option_array('asap_accepted_audiences',{'*'});
|
|
86
|
+ ASAPTTL
|
|
87
|
+ = module:get_option_number("asap_ttl", 3600);
|
|
88
|
+
|
|
89
|
+ ASAPTTL_THRESHOLD
|
|
90
|
+ = module:get_option_number("asap_ttl_threshold", 600);
|
64
|
91
|
|
65
|
|
-module:log("debug", "ASAP Accepted Audiences %s", ASAPAcceptedAudiences);
|
66
|
|
-token_util:set_asap_accepted_audiences(ASAPAcceptedAudiences);
|
|
92
|
+ queueServiceURL
|
|
93
|
+ = module:get_option_string("jibri_queue_url");
|
67
|
94
|
|
68
|
|
-token_util:set_asap_require_room_claim(false);
|
|
95
|
+ JibriRegion
|
|
96
|
+ = module:get_option_string("jibri_region", 'default');
|
69
|
97
|
|
70
|
|
-local ASAPTTL
|
71
|
|
- = module:get_option_number("asap_ttl", 3600);
|
|
98
|
+ -- option to enable/disable token verifications
|
|
99
|
+ disableTokenVerification
|
|
100
|
+ = module:get_option_boolean("disable_jibri_queue_token_verification", false);
|
72
|
101
|
|
73
|
|
-local ASAPTTL_THRESHOLD
|
74
|
|
- = module:get_option_number("asap_ttl_threshold", 600);
|
|
102
|
+ muc_component_host
|
|
103
|
+ = module:get_option_string("muc_component");
|
75
|
104
|
|
76
|
|
-local ASAPKey;
|
|
105
|
+ external_api_url = module:get_option_string("external_api_url",tostring(parentHostName));
|
|
106
|
+ module:log("debug", "External advertised API URL", external_api_url);
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+ -- TODO: Figure out a less arbitrary default cache size.
|
|
110
|
+ jwtKeyCacheSize
|
|
111
|
+ = module:get_option_number("jwt_pubkey_cache_size", 128);
|
|
112
|
+ jwtKeyCache = require"util.cache".new(jwtKeyCacheSize);
|
|
113
|
+
|
|
114
|
+ if queueServiceURL == nil then
|
|
115
|
+ log("error", "No jibri_queue_url specified. No service to contact!");
|
|
116
|
+ return;
|
|
117
|
+ end
|
|
118
|
+
|
|
119
|
+ if muc_component_host == nil then
|
|
120
|
+ log("error", "No muc_component specified. No muc to operate on for jibri queue!");
|
|
121
|
+ return;
|
|
122
|
+ end
|
|
123
|
+
|
|
124
|
+ -- Read ASAP key once on module startup
|
|
125
|
+ local f = io.open(ASAPKeyPath, "r");
|
|
126
|
+ if f then
|
|
127
|
+ ASAPKey = f:read("*all");
|
|
128
|
+ f:close();
|
|
129
|
+ if not ASAPKey then
|
|
130
|
+ module:log("warn", "No ASAP Key read from %s, disabling jibri queue component plugin", ASAPKeyPath);
|
|
131
|
+ return
|
|
132
|
+ end
|
|
133
|
+ else
|
|
134
|
+ module:log("warn", "Error reading ASAP Key %s, disabling jibri queue component plugin", ASAPKeyPath);
|
|
135
|
+ return
|
|
136
|
+ end
|
|
137
|
+
|
|
138
|
+ return true;
|
|
139
|
+end
|
77
|
140
|
|
78
|
|
-local queueServiceURL
|
79
|
|
- = module:get_option_string("jibri_queue_url");
|
|
141
|
+local function reload_config()
|
|
142
|
+ module:log("info", "Reloading configuration for jibri queue component");
|
|
143
|
+ local config_success = load_config();
|
80
|
144
|
|
81
|
|
-local JibriRegion
|
82
|
|
- = module:get_option_string("jibri_region", 'default');
|
|
145
|
+ if not config_success then
|
|
146
|
+ log("error", "Unsuccessful reconfiguration, jibri queue component may misbehave");
|
|
147
|
+ end
|
|
148
|
+end
|
83
|
149
|
|
84
|
|
-if queueServiceURL == nil then
|
85
|
|
- log("error", "No jibri_queue_url specified. No service to contact!");
|
|
150
|
+local config_success = load_config();
|
|
151
|
+
|
|
152
|
+if not config_success then
|
|
153
|
+ log("error", "Unsuccessful configuration step, jibri queue component disabled")
|
86
|
154
|
return;
|
87
|
155
|
end
|
88
|
156
|
|
89
|
|
-local disableTokenVerification
|
90
|
|
- = module:get_option_boolean("disable_jibri_queue_token_verification", false);
|
91
|
157
|
|
92
|
158
|
local http_headers = {
|
93
|
159
|
["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")",
|
|
@@ -103,35 +167,9 @@ if not have_async then
|
103
|
167
|
return;
|
104
|
168
|
end
|
105
|
169
|
|
106
|
|
-local muc_component_host = module:get_option_string("muc_component");
|
107
|
|
-if muc_component_host == nil then
|
108
|
|
- log("error", "No muc_component specified. No muc to operate on for jibri queue!");
|
109
|
|
- return;
|
110
|
|
-end
|
111
|
170
|
|
112
|
171
|
log("info", "Starting jibri queue handling for %s", muc_component_host);
|
113
|
172
|
|
114
|
|
-local external_api_url = module:get_option_string("external_api_url",tostring(parentHostName));
|
115
|
|
-module:log("debug", "External advertised API URL", external_api_url);
|
116
|
|
-
|
117
|
|
-local f = io.open(ASAPKeyPath, "r");
|
118
|
|
-if f then
|
119
|
|
- ASAPKey = f:read("*all");
|
120
|
|
- f:close();
|
121
|
|
- if not ASAPKey then
|
122
|
|
- module:log("warn", "No ASAP Key read, disabling muc_events plugin");
|
123
|
|
- return
|
124
|
|
- end
|
125
|
|
-else
|
126
|
|
- module:log("warn", "Error reading ASAP Key, disabling muc_events plugin");
|
127
|
|
- return
|
128
|
|
-end
|
129
|
|
-
|
130
|
|
-local jwtKeyCacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
|
131
|
|
-local jwtKeyCache = require"util.cache".new(jwtKeyCacheSize);
|
132
|
|
-
|
133
|
173
|
local function round(num, numDecimalPlaces)
|
134
|
174
|
local mult = 10^(numDecimalPlaces or 0)
|
135
|
175
|
return math.floor(num * mult + 0.5) / mult
|
|
@@ -179,12 +217,9 @@ end
|
179
|
217
|
local function sendIq(participant,action,requestId,time,position,token)
|
180
|
218
|
local iqId = uuid_gen();
|
181
|
219
|
local from = module:get_host();
|
182
|
220
|
local outStanza = st.iq({type = 'set', from = from, to = participant, id = iqId}):tag("jibri-queue",
|
183
|
221
|
{ xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId, action = action });
|
184
|
222
|
|
185
|
|
-
|
186
|
223
|
if token then
|
187
|
224
|
outStanza:tag("token"):text(token):up()
|
188
|
225
|
end
|
|
@@ -194,7 +229,7 @@ local function sendIq(participant,action,requestId,time,position,token)
|
194
|
229
|
if position then
|
195
|
230
|
outStanza:tag("position"):text(tostring(position)):up()
|
196
|
231
|
end
|
197
|
|
- -- module:log("debug","Oubound stanza %s",inspect(outStanza));
|
|
232
|
+
|
198
|
233
|
module:send(outStanza);
|
199
|
234
|
end
|
200
|
235
|
|
|
@@ -260,6 +295,14 @@ local function sendEvent(type,room_address,participant,requestId,replyIq,replyEr
|
260
|
295
|
end);
|
261
|
296
|
end
|
262
|
297
|
|
|
298
|
+function clearRoomQueueByOccupant(room, occupant)
|
|
299
|
+ room.jibriQueue[occupant.jid] = nil;
|
|
300
|
+end
|
|
301
|
+
|
|
302
|
+function addRoomQueueByOccupant(room, occupant, requestId)
|
|
303
|
+ room.jibriQueue[occupant.jid] = requestId;
|
|
304
|
+end
|
|
305
|
+
|
263
|
306
|
-- receives iq from client currently connected to the room
|
264
|
307
|
function on_iq(event)
|
265
|
308
|
local requestId;
|
|
@@ -300,7 +343,7 @@ function on_iq(event)
|
300
|
343
|
module:log("debug","Received join queue request for jid %s occupant %s requestId %s",roomAddress,occupant.jid,requestId);
|
301
|
344
|
|
302
|
345
|
-- now handle new jibri queue message
|
303
|
|
- room.jibriQueue[occupant.jid] = requestId;
|
|
346
|
+ addRoomQueueByOccupant(room, occupant, requestId);
|
304
|
347
|
reply:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
305
|
348
|
replyError:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
306
|
349
|
|
|
@@ -312,7 +355,7 @@ function on_iq(event)
|
312
|
355
|
module:log("debug","Received leave queue request for jid %s occupant %s requestId %s",roomAddress,occupant.jid,requestId);
|
313
|
356
|
|
314
|
357
|
-- TODO: check that requestId is the same as cached value
|
315
|
|
- room.jibriQueue[occupant.jid] = nil;
|
|
358
|
+ clearRoomQueueByOccupant(room, occupant);
|
316
|
359
|
reply:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
317
|
360
|
replyError:add_child(st.stanza("jibri-queue", { xmlns = 'http://jitsi.org/protocol/jibri-queue', requestId = requestId})):up()
|
318
|
361
|
|
|
@@ -424,12 +467,6 @@ function verify_token(token, room_jid, session)
|
424
|
467
|
return false;
|
425
|
468
|
end
|
426
|
469
|
|
427
|
|
- -- if not token_util:verify_room(session, room_jid) then
|
428
|
|
- -- log("warn", "Token %s not allowed to access: %s",
|
429
|
|
- -- tostring(token), tostring(room_jid));
|
430
|
|
- -- return false;
|
431
|
|
- -- end
|
432
|
|
-
|
433
|
470
|
return true;
|
434
|
471
|
end
|
435
|
472
|
|
|
@@ -437,31 +474,22 @@ end
|
437
|
474
|
-- @param event the http event, holds the request query
|
438
|
475
|
-- @return GET response, containing a json with response details
|
439
|
476
|
function handle_update_jibri_queue(event)
|
440
|
|
- -- if (not event.request.url.query) then
|
441
|
|
- -- return { status_code = 400; };
|
442
|
|
- -- end
|
443
|
|
-
|
444
|
477
|
local body = json.decode(event.request.body);
|
445
|
478
|
|
446
|
479
|
module:log("debug","Update Jibri Queue Event Received: %s",inspect(body));
|
447
|
480
|
|
448
|
|
- local token
|
|
481
|
+ local token = event.request.headers["authorization"];
|
449
|
482
|
if not token then
|
450
|
|
- token = event.request.headers["authorization"];
|
451
|
|
- if not token then
|
452
|
|
- token = ''
|
453
|
|
- else
|
454
|
|
- local prefixStart, prefixEnd = token:find("Bearer ");
|
455
|
|
- if prefixStart ~= 1 then
|
456
|
|
- module:log("error", "REST event: Invalid authorization header format. The header must start with the string 'Bearer '");
|
457
|
|
- return 403
|
458
|
|
- end
|
459
|
|
- token = token:sub(prefixEnd + 1);
|
|
483
|
+ token = ''
|
|
484
|
+ else
|
|
485
|
+ local prefixStart, prefixEnd = token:find("Bearer ");
|
|
486
|
+ if prefixStart ~= 1 then
|
|
487
|
+ module:log("error", "REST event: Invalid authorization header format. The header must start with the string 'Bearer '");
|
|
488
|
+ return 403
|
460
|
489
|
end
|
|
490
|
+ token = token:sub(prefixEnd + 1);
|
461
|
491
|
end
|
462
|
|
-
|
|
492
|
+
|
463
|
493
|
local user_jid = body["participant"];
|
464
|
494
|
local roomAddress = body["conference"];
|
465
|
495
|
local userJWT = body["token"];
|
|
@@ -470,6 +498,14 @@ function handle_update_jibri_queue(event)
|
470
|
498
|
local position = body["position"];
|
471
|
499
|
local requestId = body["requestId"];
|
472
|
500
|
|
|
501
|
+ if not action then
|
|
502
|
+ if userJWT then
|
|
503
|
+ action = 'token';
|
|
504
|
+ else
|
|
505
|
+ action = 'info';
|
|
506
|
+ end
|
|
507
|
+ end
|
|
508
|
+
|
473
|
509
|
local room_jid = room_jid_match_rewrite(roomAddress);
|
474
|
510
|
|
475
|
511
|
if not verify_token(token, room_jid, {}) then
|
|
@@ -494,19 +530,16 @@ function handle_update_jibri_queue(event)
|
494
|
530
|
return { status_code = 404; };
|
495
|
531
|
end
|
496
|
532
|
|
497
|
|
- if not action then
|
498
|
|
- if userJWT then
|
499
|
|
- action = 'token';
|
500
|
|
- else
|
501
|
|
- action = 'info';
|
502
|
|
- end
|
503
|
|
- end
|
504
|
|
-
|
505
|
533
|
if not requestId then
|
506
|
534
|
requestId = room.jibriQueue[occupant.jid];
|
507
|
535
|
end
|
508
|
536
|
|
509
|
|
- log("debug", "REST event: Sending update for occupant %s in conference %s to route action %s for requestId %s",occupant.jid,room.jid, action, requestId)
|
|
537
|
+ if action == 'token' and userJWT then
|
|
538
|
+ log("debug", "REST event: Token received for occupant %s in conference %s requestId %s, clearing room queue");
|
|
539
|
+ clearRoomQueueByOccupant(room, occupant);
|
|
540
|
+ end
|
|
541
|
+
|
|
542
|
+ log("debug", "REST event: Sending update for occupant %s in conference %s to route action %s for requestId %s",occupant.jid,room.jid, action, requestId);
|
510
|
543
|
sendIq(occupant.jid,action,requestId,time,position,userJWT);
|
511
|
544
|
return { status_code = 200; };
|
512
|
545
|
end
|
|
@@ -519,3 +552,5 @@ module:provides("http", {
|
519
|
552
|
["POST /jibriqueue/update"] = function (event) return async_handler_wrapper(event,handle_update_jibri_queue) end;
|
520
|
553
|
};
|
521
|
554
|
});
|
|
555
|
+
|
|
556
|
+module:hook_global('config-reloaded', reload_config);
|