Browse code

kazoo: add basic kemi support

Author Yufei Tao authored on 11/05/2020 13:48:32 • lazedo committed on 21/05/2020 14:30:58
Showing 4 changed files
... ...
@@ -297,6 +297,28 @@ modparam("kazoo", "amqp_connection", "kazoo://guest:guest@otherhost:5672")
297 297
         </example>
298 298
     </section>
299 299
 
300
+<section>
301
+  <title><varname>event_callback</varname>(str)</title>
302
+    <para>
303
+        The name of the function in the kemi configuration file (embedded
304
+        scripting language such as Lua, Python, ...) to be executed instead
305
+        of event_route[...] blocks.
306
+    </para>
307
+    <para>
308
+        The function receives a string parameter with the name of the event,
309
+        the values can be: 'kazoo:mod-init', 'kazoo:consumer-event'.
310
+    </para>
311
+
312
+  <example>
313
+    <title>Set <varname>event_callback</varname> parameter</title>
314
+    <programlisting format="linespecific">
315
+    ...
316
+    modparam("kazoo", "event_callback", "ksr_kazoo_event")
317
+    ...
318
+    </programlisting>
319
+  </example>
320
+</section>
321
+
300 322
     
301 323
 
302 324
     
... ...
@@ -31,6 +31,7 @@
31 31
 #include "../../lib/srdb1/db.h"
32 32
 #include "../../core/dprint.h"
33 33
 #include "../../core/cfg/cfg_struct.h"
34
+#include "../../core/kemi.h"
34 35
 
35 36
 #include "kz_amqp.h"
36 37
 #include "kz_json.h"
... ...
@@ -46,6 +47,8 @@
46 47
 static int mod_init(void);
47 48
 static int  mod_child_init(int rank);
48 49
 static int fire_init_event(int rank);
50
+static int fire_init_event_cfg(void);
51
+static int fire_init_event_kemi(void);
49 52
 static void mod_destroy(void);
50 53
 
51 54
 str dbk_node_hostname = { 0, 0 };
... ...
@@ -122,6 +125,9 @@ pv_spec_t kz_query_result_spec;
122 125
 
123 126
 str kz_app_name = str_init(NAME);
124 127
 
128
+str kazoo_event_callback = STR_NULL;
129
+int kazoo_kemi_enabled=0;
130
+
125 131
 MODULE_VERSION
126 132
 
127 133
 static tr_export_t mod_trans[] = {
... ...
@@ -209,6 +215,7 @@ static param_export_t params[] = {
209 215
 	{"pua_lock_type", INT_PARAM, &kz_pua_lock_type},
210 216
     {"amqp_connect_timeout_micro", INT_PARAM, &kz_amqp_connect_timeout_tv.tv_usec},
211 217
     {"amqp_connect_timeout_sec", INT_PARAM, &kz_amqp_connect_timeout_tv.tv_sec},
218
+    {"event_callback",  PARAM_STR,    &kazoo_event_callback},
212 219
     {0, 0, 0}
213 220
 };
214 221
 
... ...
@@ -273,6 +280,7 @@ static int mod_init(void) {
273 280
    		return -1;
274 281
     }
275 282
 
283
+
276 284
     if(kz_timer_ms > 0) {
277 285
     	kz_timer_tv.tv_usec = (kz_timer_ms % 1000) * 1000;
278 286
     	kz_timer_tv.tv_sec = kz_timer_ms / 1000;
... ...
@@ -312,6 +320,16 @@ static int mod_init(void) {
312 320
 		}
313 321
     }
314 322
 
323
+	sr_kemi_eng_t *keng = NULL;
324
+	if(kazoo_event_callback.s!=NULL && kazoo_event_callback.len>0) {
325
+		keng = sr_kemi_eng_get();
326
+		if(keng==NULL) {
327
+			LM_ERR("failed to find kemi engine\n");
328
+			return -1;
329
+		}
330
+		kazoo_kemi_enabled=1;
331
+	}
332
+
315 333
 
316 334
     int total_workers = dbk_consumer_workers + (dbk_consumer_processes * kz_server_counter) + 2;
317 335
 
... ...
@@ -341,6 +359,20 @@ static int mod_init(void) {
341 359
     return 0;
342 360
 }
343 361
 
362
+static sr_kemi_t kazoo_kemi_exports[] = {
363
+	{ str_init("kazoo"), str_init("kazoo_publish"),
364
+		SR_KEMIP_INT, ki_kz_amqp_publish,
365
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
366
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
367
+	},
368
+	{ str_init("kazoo"), str_init("kazoo_subscribe"),
369
+		SR_KEMIP_INT, ki_kz_amqp_subscribe,
370
+		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
371
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
372
+	},
373
+	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
374
+};
375
+
344 376
 int mod_register(char *path, int *dlflags, void *p1, void *p2)
345 377
 {
346 378
 	if(kz_tr_init_buffers()<0)
... ...
@@ -348,6 +380,9 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
348 380
 		LM_ERR("failed to initialize transformations buffers\n");
349 381
 		return -1;
350 382
 	}
383
+
384
+	sr_kemi_modules_add(kazoo_kemi_exports);
385
+
351 386
 	return register_trans_mod(path, mod_trans);
352 387
 }
353 388
 
... ...
@@ -430,16 +465,12 @@ static int mod_child_init(int rank)
430 465
 	return 0;
431 466
 }
432 467
 
433
-static int fire_init_event(int rank)
468
+static int fire_init_event_cfg(void)
434 469
 {
435 470
 	struct sip_msg *fmsg;
436 471
 	struct run_act_ctx ctx;
437 472
 	int rtb, rt;
438 473
 
439
-	LM_DBG("rank is (%d)\n", rank);
440
-	if (rank!=PROC_INIT)
441
-		return 0;
442
-
443 474
 	rt = route_get(&event_rt, "kazoo:mod-init");
444 475
 	if(rt>=0 && event_rt.rlist[rt]!=NULL) {
445 476
 		LM_DBG("executing event_route[kazoo:mod-init] (%d)\n", rt);
... ...
@@ -461,11 +492,50 @@ static int fire_init_event(int rank)
461 492
 	return 0;
462 493
 }
463 494
 
495
+static int fire_init_event_kemi(void)
496
+{
497
+	struct sip_msg *fmsg;
498
+	int rtb;
499
+	sr_kemi_eng_t *keng = NULL;
500
+
501
+	keng = sr_kemi_eng_get();
502
+	if(keng!=NULL) {
503
+		str evrtname = str_init("kazoo:mod-init");
504
+		rtb = get_route_type();
505
+		if(faked_msg_init()<0)
506
+			return -1;
507
+		fmsg = faked_msg_next();
508
+		if(sr_kemi_route(keng, fmsg, EVENT_ROUTE, &kazoo_event_callback, &evrtname)<0) {
509
+			LM_ERR("error running event route kemi callback\n");
510
+		}
511
+		set_route_type(rtb);
512
+	} 
513
+	else {
514
+		LM_ERR("no event route or kemi callback found for execution\n");
515
+	}
516
+
517
+	return 0;
518
+}
519
+
520
+static int fire_init_event(int rank)
521
+{
522
+	LM_DBG("rank is (%d)\n", rank);
523
+	if (rank!=PROC_INIT)
524
+		return 0;
525
+
526
+	if (kazoo_kemi_enabled) {
527
+		return fire_init_event_kemi();
528
+	}
529
+	else {
530
+		return fire_init_event_cfg();
531
+	}
532
+
533
+	return 0;
534
+}
535
+
464 536
 
465 537
 static void mod_destroy(void) {
466 538
 	kz_amqp_destroy();
467 539
     if (kz_worker_pipes_fds) { shm_free(kz_worker_pipes_fds); }
468 540
     if (kz_worker_pipes) { shm_free(kz_worker_pipes); }
469 541
 }
470
-
471
-
... ...
@@ -46,7 +46,7 @@
46 46
 #include "../../core/receive.h"
47 47
 #include "../../core/action.h"
48 48
 #include "../../core/script_cb.h"
49
-
49
+#include "../../core/kemi.h"
50 50
 
51 51
 #include "kz_amqp.h"
52 52
 #include "kz_json.h"
... ...
@@ -81,6 +81,9 @@ extern int kz_amqps_verify_hostname;
81 81
 
82 82
 extern pv_spec_t kz_query_timeout_spec;
83 83
 
84
+extern int kazoo_kemi_enabled;
85
+extern str kazoo_event_callback;
86
+
84 87
 const amqp_bytes_t kz_amqp_empty_bytes = { 0, NULL };
85 88
 const amqp_table_t kz_amqp_empty_table = { 0, NULL };
86 89
 
... ...
@@ -1215,7 +1218,7 @@ int kz_amqp_pipe_send_receive(str *str_exchange, str *str_routing_key, str *str_
1215 1218
 
1216 1219
 int kz_amqp_publish_ex(struct sip_msg* msg, char* exchange, char* routing_key, char* payload, char* _pub_flags)
1217 1220
 {
1218
-	  str json_s;
1221
+	  str pl_s;
1219 1222
 	  str exchange_s;
1220 1223
 	  str routing_key_s;
1221 1224
 
... ...
@@ -1229,7 +1232,7 @@ int kz_amqp_publish_ex(struct sip_msg* msg, char* exchange, char* routing_key, c
1229 1232
 			return -1;
1230 1233
 		}
1231 1234
 
1232
-		if (fixup_get_svalue(msg, (gparam_p)payload, &json_s) != 0) {
1235
+		if (fixup_get_svalue(msg, (gparam_p)payload, &pl_s) != 0) {
1233 1236
 			LM_ERR("cannot get json string value : %s\n", payload);
1234 1237
 			return -1;
1235 1238
 		}
... ...
@@ -1239,19 +1242,22 @@ int kz_amqp_publish_ex(struct sip_msg* msg, char* exchange, char* routing_key, c
1239 1242
 			return -1;
1240 1243
 		}
1241 1244
 
1242
-		struct json_object *j = json_tokener_parse(json_s.s);
1243
-
1244
-		if (j==NULL) {
1245
-			LM_ERR("empty or invalid JSON payload : %.*s\n", json_s.len, json_s.s);
1246
-			return -1;
1247
-		}
1248
-
1249
-		json_object_put(j);
1250
-
1251
-		return kz_amqp_pipe_send(&exchange_s, &routing_key_s, &json_s );
1245
+		return ki_kz_amqp_publish(msg, (char*)&exchange_s, (char*)&routing_key_s, (char*)&pl_s);
1246
+};
1252 1247
 
1248
+int ki_kz_amqp_publish(struct sip_msg* msg, char* exchange, char* routing_key, char* payload)
1249
+{
1250
+	  char *pl = ((str*)payload)->s;
1251
+	  struct json_object *j = json_tokener_parse(pl);
1253 1252
 
1254
-};
1253
+	  if (j==NULL) {
1254
+	  	  LM_ERR("empty or invalid JSON payload : %.*s\n", ((str*)payload)->len, ((str*)payload)->s);
1255
+	  	  return -1;
1256
+	  }
1257
+	  
1258
+	  json_object_put(j);
1259
+	  return kz_amqp_pipe_send((str*)exchange, (str*)routing_key, (str*)payload);
1260
+}
1255 1261
 
1256 1262
 int kz_amqp_publish(struct sip_msg* msg, char* exchange, char* routing_key, char* payload)
1257 1263
 {
... ...
@@ -1793,10 +1799,21 @@ kz_amqp_exchange_binding_ptr kz_amqp_exchange_binding_from_json(json_object* JOb
1793 1799
 }
1794 1800
 
1795 1801
 int kz_amqp_subscribe(struct sip_msg* msg, char* payload)
1802
+{
1803
+	str payload_s = STR_NULL;
1804
+    
1805
+	if (fixup_get_svalue(msg, (gparam_p)payload, &payload_s) != 0) {
1806
+		LM_ERR("cannot get payload value\n");
1807
+		return -1;
1808
+	}
1809
+
1810
+	return ki_kz_amqp_subscribe(msg, (char*)(&payload_s));
1811
+}
1812
+
1813
+int ki_kz_amqp_subscribe(struct sip_msg* msg, char* payload)
1796 1814
 {
1797 1815
 	str exchange_s = STR_NULL;
1798 1816
 	str queue_s = STR_NULL;
1799
-	str payload_s = STR_NULL;
1800 1817
 	str key_s = STR_NULL;
1801 1818
 	str subkey_s = STR_NULL;
1802 1819
 	int no_ack = 1;
... ...
@@ -1816,12 +1833,9 @@ int kz_amqp_subscribe(struct sip_msg* msg, char* payload)
1816 1833
 	kz_amqp_bind_ptr bind = NULL;
1817 1834
 	kz_amqp_binding_ptr binding = NULL;
1818 1835
 
1819
-	if (fixup_get_svalue(msg, (gparam_p)payload, &payload_s) != 0) {
1820
-		LM_ERR("cannot get payload value\n");
1821
-		return -1;
1822
-	}
1836
+	char* pl = ((str*)payload)->s;
1837
+	json_obj = kz_json_parse(pl);
1823 1838
 
1824
-	json_obj = kz_json_parse(payload_s.s);
1825 1839
 	if (json_obj == NULL)
1826 1840
 		return -1;
1827 1841
     
... ...
@@ -1873,7 +1887,7 @@ int kz_amqp_subscribe(struct sip_msg* msg, char* payload)
1873 1887
 	}
1874 1888
 
1875 1889
 	if(routing == NULL) {
1876
-		LM_INFO("creating empty routing key : %s\n", payload_s.s);
1890
+		LM_INFO("creating empty routing key : %s\n", pl);
1877 1891
 		routing = kz_amqp_routing_new("");
1878 1892
 	}
1879 1893
 
... ...
@@ -2331,63 +2345,99 @@ int kz_amqp_consumer_fire_event(char *eventkey)
2331 2345
 	return 0;
2332 2346
 }
2333 2347
 
2334
-void kz_amqp_consumer_event(kz_amqp_consumer_delivery_ptr Evt)
2348
+static void kz_amqp_consumer_event_cfg(kz_amqp_consumer_delivery_ptr Evt, json_obj_ptr json_obj)
2335 2349
 {
2336
-    json_obj_ptr json_obj = NULL;
2337
-    str ev_name = {0, 0}, ev_category = {0, 0};
2338
-    char buffer[512];
2339
-    char * p;
2350
+	str ev_name = {0, 0}, ev_category = {0, 0};
2351
+	char buffer[512];
2352
+	char * p;
2340 2353
 
2341
-    eventData = Evt->payload;
2342
-    if(Evt->routing_key) {
2343
-    	eventKey = Evt->routing_key->s;
2344
-    }
2345 2354
 
2346
-    json_obj = kz_json_parse(Evt->payload);
2347
-    if (json_obj == NULL)
2348
-		return;
2349
-
2350
-    char* key = (Evt->event_key == NULL ? dbk_consumer_event_key.s : Evt->event_key);
2351
-    char* subkey = (Evt->event_subkey == NULL ? dbk_consumer_event_subkey.s : Evt->event_subkey);
2355
+	char* key = (Evt->event_key == NULL ? dbk_consumer_event_key.s : Evt->event_key);
2356
+	char* subkey = (Evt->event_subkey == NULL ? dbk_consumer_event_subkey.s : Evt->event_subkey);
2352 2357
 
2353
-    json_extract_field(key, ev_category);
2354
-    if(ev_category.len == 0 && Evt->event_key) {
2355
-	    ev_category.s = Evt->event_key;
2356
-	    ev_category.len = strlen(Evt->event_key);
2357
-    }
2358
+	json_extract_field(key, ev_category);
2359
+	if(ev_category.len == 0 && Evt->event_key) {
2360
+		ev_category.s = Evt->event_key;
2361
+		ev_category.len = strlen(Evt->event_key);
2362
+	}
2358 2363
 
2359
-    json_extract_field(subkey, ev_name);
2360
-    if(ev_name.len == 0 && Evt->event_subkey) {
2361
-	    ev_name.s = Evt->event_subkey;
2362
-	    ev_name.len = strlen(Evt->event_subkey);
2363
-    }
2364
+	json_extract_field(subkey, ev_name);
2365
+	if(ev_name.len == 0 && Evt->event_subkey) {
2366
+		ev_name.s = Evt->event_subkey;
2367
+		ev_name.len = strlen(Evt->event_subkey);
2368
+	}
2364 2369
 
2365
-    sprintf(buffer, "kazoo:consumer-event-%.*s-%.*s",ev_category.len, ev_category.s, ev_name.len, ev_name.s);
2366
-    for (p=buffer ; *p; ++p) *p = tolower(*p);
2367
-    for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2368
-    if(kz_amqp_consumer_fire_event(buffer) != 0) {
2369
-        sprintf(buffer, "kazoo:consumer-event-%.*s",ev_category.len, ev_category.s);
2370
-        for (p=buffer ; *p; ++p) *p = tolower(*p);
2371
-        for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2372
-        if(kz_amqp_consumer_fire_event(buffer) != 0) {
2373
-            sprintf(buffer, "kazoo:consumer-event-%s-%s", key, subkey);
2374
-            for (p=buffer ; *p; ++p) *p = tolower(*p);
2375
-            for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2376
-            if(kz_amqp_consumer_fire_event(buffer) != 0) {
2377
-                sprintf(buffer, "kazoo:consumer-event-%s", key);
2378
-                for (p=buffer ; *p; ++p) *p = tolower(*p);
2379
-                for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2370
+	sprintf(buffer, "kazoo:consumer-event-%.*s-%.*s",ev_category.len, ev_category.s, ev_name.len, ev_name.s);
2371
+	for (p=buffer ; *p; ++p) *p = tolower(*p);
2372
+	for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2373
+	if(kz_amqp_consumer_fire_event(buffer) != 0) {
2374
+		sprintf(buffer, "kazoo:consumer-event-%.*s",ev_category.len, ev_category.s);
2375
+		for (p=buffer ; *p; ++p) *p = tolower(*p);
2376
+		for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2377
+		if(kz_amqp_consumer_fire_event(buffer) != 0) {
2378
+			sprintf(buffer, "kazoo:consumer-event-%s-%s", key, subkey);
2379
+			for (p=buffer ; *p; ++p) *p = tolower(*p);
2380
+			for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2381
+			if(kz_amqp_consumer_fire_event(buffer) != 0) {
2382
+				sprintf(buffer, "kazoo:consumer-event-%s", key);
2383
+				for (p=buffer ; *p; ++p) *p = tolower(*p);
2384
+				for (p=buffer ; *p; ++p) if(*p == '_') *p = '-';
2380 2385
 				if(kz_amqp_consumer_fire_event(buffer) != 0) {
2381 2386
 					sprintf(buffer, "kazoo:consumer-event");
2382 2387
 					if(kz_amqp_consumer_fire_event(buffer) != 0) {
2383 2388
 						LM_ERR("kazoo:consumer-event not found\n");
2384 2389
 					}
2385 2390
 				}
2386
-            }
2387
-        }
2388
-    }
2391
+			}
2392
+		}
2393
+	}
2394
+}
2395
+
2396
+static void kz_amqp_consumer_event_kemi(void)
2397
+{
2398
+	sr_kemi_eng_t *keng = NULL;
2399
+    int rtb;
2400
+	
2401
+	keng = sr_kemi_eng_get();
2402
+	if(keng!=NULL) {
2403
+		sip_msg_t *msg;
2404
+		str evrtname = str_init("kazoo:consumer-event");
2405
+
2406
+		rtb = get_route_type();
2407
+		msg = faked_msg_next();
2408
+		if(sr_kemi_route(keng, msg, EVENT_ROUTE, &kazoo_event_callback, &evrtname)<0)                {
2409
+			LM_ERR("error running event route kemi callback\n");
2410
+		}
2411
+
2412
+		set_route_type(rtb);
2413
+	} else {
2414
+		LM_ERR("no event route or kemi callback found for execution\n");
2415
+	}
2416
+
2417
+}
2418
+
2419
+void kz_amqp_consumer_event(kz_amqp_consumer_delivery_ptr Evt)
2420
+{
2421
+	json_obj_ptr json_obj = NULL;
2422
+
2423
+	eventData = Evt->payload;
2424
+	if(Evt->routing_key) {
2425
+		eventKey = Evt->routing_key->s;
2426
+	}
2427
+
2428
+	json_obj = kz_json_parse(Evt->payload);
2429
+	if (json_obj == NULL)
2430
+		return;
2431
+
2432
+	if (kazoo_kemi_enabled) {
2433
+		kz_amqp_consumer_event_kemi();
2434
+	} 
2435
+	else {
2436
+		kz_amqp_consumer_event_cfg(Evt, json_obj);
2437
+	}
2438
+
2389 2439
 	if(json_obj)
2390
-    	json_object_put(json_obj);
2440
+		json_object_put(json_obj);
2391 2441
 
2392 2442
 	eventData = NULL;
2393 2443
 	eventKey = NULL;
... ...
@@ -274,9 +274,11 @@ int kz_amqp_add_connection(modparam_t type, void* val);
274 274
 
275 275
 int kz_amqp_publish(struct sip_msg* msg, char* exchange, char* routing_key, char* payload);
276 276
 int kz_amqp_publish_ex(struct sip_msg* msg, char* exchange, char* routing_key, char* payload, char* _pub_flags);
277
+int ki_kz_amqp_publish(struct sip_msg* msg, char* exchange, char* routing_key, char* payload);
277 278
 int kz_amqp_query(struct sip_msg* msg, char* exchange, char* routing_key, char* payload, char* dst);
278 279
 int kz_amqp_query_ex(struct sip_msg* msg, char* exchange, char* routing_key, char* payload);
279 280
 int kz_amqp_subscribe(struct sip_msg* msg, char* payload);
281
+int ki_kz_amqp_subscribe(struct sip_msg* msg, char* payload);
280 282
 int kz_amqp_subscribe_simple(struct sip_msg* msg, char* exchange, char* exchange_type, char* queue_name, char* routing_key);
281 283
 int kz_amqp_encode(struct sip_msg* msg, char* unencoded, char* encoded);
282 284
 int kz_amqp_encode_ex(str* unencoded, pv_value_p dst_val);