sip-lab 1.11.2 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/sip.cpp CHANGED
@@ -34,12 +34,17 @@
34
34
 
35
35
  #include "log.hpp"
36
36
 
37
+ #include "rapidjson/document.h"
38
+
39
+ using namespace rapidjson;
37
40
  using namespace std;
38
41
 
39
42
  #define EVT_DATA_SEP "|"
40
43
 
41
44
  #define IDS_MAX (2000)
42
45
 
46
+ #define MAX_JSON_INPUT 4096
47
+
43
48
  IdManager g_transport_ids(IDS_MAX);
44
49
  IdManager g_account_ids(IDS_MAX);
45
50
  IdManager g_call_ids(IDS_MAX);
@@ -64,8 +69,8 @@ static pj_caching_pool cp;
64
69
  static pj_pool_t *g_pool;
65
70
  static pjmedia_endpt *g_med_endpt;
66
71
 
67
- static pj_thread_t *g_thread = NULL;
68
- static pj_bool_t g_thread_quit_flag;
72
+ //static pj_thread_t *g_thread = NULL;
73
+ //static pj_bool_t g_thread_quit_flag;
69
74
 
70
75
  static deque<string> g_events;
71
76
  static pthread_mutex_t g_mutex;
@@ -76,15 +81,119 @@ void clear_error() {
76
81
  pjw_errorstring[0] = 0;
77
82
  }
78
83
 
84
+ /*
79
85
  void set_error(char *err) {
80
86
  //printf("set_error: %s\n", err);
81
87
  strcpy(pjw_errorstring, err);
82
88
  }
89
+ */
90
+
91
+ void set_error(const char* format, ...)
92
+ {
93
+ va_list args;
94
+ va_start(args, format);
95
+ vsnprintf(pjw_errorstring, sizeof(pjw_errorstring), format, args);
96
+ va_end(args);
97
+ }
83
98
 
84
99
  char *pjw_get_error() {
85
100
  return pjw_errorstring;
86
101
  }
87
102
 
103
+ int check_uri(const char *uri) {
104
+ return (strstr(uri, "sip:") != NULL);
105
+ }
106
+
107
+ bool parse_json(Document &document, const char *json, char *buffer, long unsigned int len) {
108
+ if(strlen(json) > len -1) {
109
+ set_error("JSON too large");
110
+ return false;
111
+ }
112
+
113
+ strcpy(buffer, json);
114
+ if (document.ParseInsitu(buffer).HasParseError()) {
115
+ set_error("Failed to parse JSON");
116
+ return false;
117
+ }
118
+
119
+ if(!document.IsObject()) {
120
+ set_error("Invalid JSON root. Must be an object");
121
+ return false;
122
+ }
123
+
124
+ return true;
125
+ }
126
+
127
+ bool json_get_string_param(Document &document, const char *param, bool optional, char **dest) {
128
+ printf("json_get_string_param %s\n", param);
129
+ if(!document.HasMember(param)) {
130
+ if(optional) {
131
+ return true;
132
+ }
133
+ set_error("Parameter %s is required", param);
134
+ return false;
135
+ }
136
+
137
+ if(!document[param].IsString()) {
138
+ set_error("Parameter %s must be a string", param);
139
+ return false;
140
+ }
141
+ *dest = (char*)document[param].GetString();
142
+ return true;
143
+ }
144
+
145
+ bool json_get_int_param(Document &document, const char *param, bool optional, int *dest) {
146
+ if(!document.HasMember(param)) {
147
+ if(optional) {
148
+ return true;
149
+ }
150
+ set_error("Parameter %s is required", param);
151
+ return false;
152
+ }
153
+
154
+ if(!document[param].IsInt()) {
155
+ set_error("Parameter %s must be an integer", param);
156
+ return false;
157
+ }
158
+ *dest = document[param].GetInt();
159
+ return true;
160
+ }
161
+
162
+ bool json_get_bool_param(Document &document, const char *param, bool optional, bool *dest) {
163
+ if(!document.HasMember(param)) {
164
+ if(optional) {
165
+ return true;
166
+ }
167
+ set_error("Parameter %s is required", param);
168
+ return false;
169
+ }
170
+
171
+ if(!document[param].IsBool()) {
172
+ set_error("Parameter %s must be a boolean", param);
173
+ return false;
174
+ }
175
+ *dest = document[param].GetBool();
176
+ return true;
177
+ }
178
+
179
+
180
+ bool json_get_and_check_uri(Document &document, const char *param, bool optional, char **dest) {
181
+ if(!json_get_string_param(document, param, optional, dest)) {
182
+ return false;
183
+ }
184
+
185
+ if(*dest && *dest[0]) {
186
+ if(!check_uri(*dest)) {
187
+ set_error("Invalid %s", param);
188
+ return false;
189
+ }
190
+ }
191
+
192
+ return true;
193
+ }
194
+
195
+
196
+
88
197
  #define PJW_LOCK() pthread_mutex_lock(&g_mutex)
89
198
  #define PJW_UNLOCK() pthread_mutex_unlock(&g_mutex)
90
199
 
@@ -117,7 +226,7 @@ unsigned g_flags = 0;
117
226
 
118
227
  pjsip_route_hdr route_set;
119
228
  pjsip_route_hdr *route;
120
- const pj_str_t hname = { "Route", 5 };
229
+ const pj_str_t hname = pj_str((char*)"Route");
121
230
 
122
231
  #define MAXDIGITS 256
123
232
  #define INITIAL_DIGITBUFFERLENGTH 1
@@ -205,6 +314,7 @@ PackageSet g_PackageSet;
205
314
 
206
315
  #define DEFAULT_EXPIRES 600
207
316
 
317
+ /*
208
318
  static void pool_callback(pj_pool_t *pool, pj_size_t size)
209
319
  {
210
320
  PJ_CHECK_STACK();
@@ -213,18 +323,21 @@ static void pool_callback(pj_pool_t *pool, pj_size_t size)
213
323
 
214
324
  PJ_THROW(PJ_NO_MEMORY_EXCEPTION);
215
325
  }
326
+ */
216
327
 
217
328
  void handle_events(){
218
- unsigned count = 0;
329
+ //unsigned count = 0;
219
330
  //pj_time_val tv = {0, 500};
220
331
  //pj_time_val tv = {0,10};
221
332
  //pj_time_val tv = {0,100};
222
333
  pj_time_val tv = {0,1};
223
334
  //pj_time_val_normalize(&tv);
224
- pj_status_t status;
225
- status = pjsip_endpt_handle_events(g_sip_endpt, &tv);
335
+ //pj_status_t status;
336
+ //status = pjsip_endpt_handle_events(g_sip_endpt, &tv);
337
+ pjsip_endpt_handle_events(g_sip_endpt, &tv);
226
338
  }
227
339
 
340
+ /*
228
341
  static int worker_thread(void *arg)
229
342
  {
230
343
  //addon_log(LOG_LEVEL_DEBUG, "Starting worker_thread\n");
@@ -246,6 +359,7 @@ static int worker_thread(void *arg)
246
359
  }
247
360
  return 0;
248
361
  }
362
+ */
249
363
 
250
364
  void init_tpselector(Transport *t, pjsip_tpselector *sel) {
251
365
  unsigned flag;
@@ -312,10 +426,10 @@ static void server_on_evsub_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, i
312
426
 
313
427
  bool dlg_create(pjsip_dialog **dlg, Transport *transport, const char *from_uri, const char *to_uri, const char *request_uri, const char *realm, const char *username, const char *password, const char *local_contact);
314
428
 
315
- static int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, const char *additional_headers);
429
+ static int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, Document &document);
316
430
 
317
- static int subscription_create(pjsip_dialog *dlg, const char *event, const char *proxy_uri, const char *additional_headers);
318
- bool subscription_subscribe(Subscription *s, int expires, const char *additional_headers);
431
+ bool subscription_subscribe_no_headers(Subscription *s, int expires);
432
+ bool subscription_subscribe(Subscription *s, int expires, Document &document);
319
433
 
320
434
  static pjmedia_transport *create_media_transport(const pj_str_t *addr);
321
435
  void close_media_transport(pjmedia_transport *med_transport);
@@ -333,11 +447,12 @@ bool set_proxy(pjsip_dialog *dlg, const char *proxy_uri);
333
447
  void build_local_contact(char *dest, pjsip_transport *transport, const char *contact_username);
334
448
  void build_local_contact_from_tpfactory(char *dest, pjsip_tpfactory *tpfactory, const char *contact_username, pjsip_transport_type_e type);
335
449
 
336
- pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers);
450
+ //pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers);
451
+ pj_bool_t add_headers(pj_pool_t *pool, pjsip_tx_data *tdata, Document &document);
337
452
 
338
- pj_bool_t add_additional_headers_for_account(pjsip_regc* regc, const char *additional_headers);
453
+ pj_bool_t add_headers_for_account(pjsip_regc* regc, Document &document);
339
454
 
340
- pj_bool_t get_content_type_and_subtype_from_additional_headers(const char *additional_headers, char *type, char *subtype);
455
+ pj_bool_t get_content_type_and_subtype_from_headers(Document &document, char *type, char *subtype);
341
456
 
342
457
  bool build_subscribe_info(ostringstream *oss, pjsip_rx_data *rdata, Subscriber *s);
343
458
  //bool build_notify_info(pjsip_rx_data *rdata, Subscription *s);
@@ -372,7 +487,7 @@ void append_status(ostringstream *oss, pj_status_t s);
372
487
  static pjsip_module mod_tester =
373
488
  {
374
489
  NULL, NULL, /* prev, next. */
375
- { "mod_tester", 10 }, /* Name. */
490
+ { (char*)"mod_tester", 10 }, /* Name. */
376
491
  -1, /* Id */
377
492
  //PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
378
493
  PJSIP_MOD_PRIORITY_DIALOG_USAGE, /* Priority */
@@ -400,10 +515,6 @@ Timer _timer;
400
515
 
401
516
  void dispatch_event(const char * evt);
402
517
 
403
- int check_uri(const char *uri) {
404
- return (strstr(uri, "sip:") != NULL);
405
- }
406
-
407
518
  const char *translate_pjsip_inv_state(int state)
408
519
  {
409
520
  switch(state)
@@ -489,11 +600,12 @@ void dispatch_event(const char * evt)
489
600
  }
490
601
 
491
602
  static char *get_media_mode_str(int mode) {
492
- if(mode == SENDRECV) return "sendrecv";
493
- if(mode == SENDONLY) return "sendonly";
494
- if(mode == RECVONLY) return "recvonly";
495
- if(mode == INACTIVE) return "inactive";
496
- if(mode == UNKNOWN) return "unknown";
603
+ if(mode == SENDRECV) return (char*)"sendrecv";
604
+ if(mode == SENDONLY) return (char*)"sendonly";
605
+ if(mode == RECVONLY) return (char*)"recvonly";
606
+ if(mode == INACTIVE) return (char*)"inactive";
607
+ if(mode == UNKNOWN) return (char*)"unknown";
608
+ return (char*)"unexpected";
497
609
  }
498
610
 
499
611
  static int get_media_mode(pjmedia_sdp_attr **attrs, int count) {
@@ -541,7 +653,7 @@ int __pjw_init()
541
653
 
542
654
  pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
543
655
 
544
- char *sip_endpt_name = "mysip";
656
+ char *sip_endpt_name = (char*)"mysip";
545
657
 
546
658
  status = pjsip_endpt_create(&cp.factory, sip_endpt_name, &g_sip_endpt);
547
659
  if(status != PJ_SUCCESS)
@@ -560,9 +672,9 @@ int __pjw_init()
560
672
  return 1;
561
673
  }
562
674
 
563
- const pj_str_t msg_tag = { "MESSAGE", 7 };
564
- const pj_str_t STR_MIME_TEXT_PLAIN = { "text/plain", 10 };
565
- const pj_str_t STR_MIME_APP_ISCOMPOSING = { "application/im-iscomposing+xml", 30 };
675
+ const pj_str_t msg_tag = { (char*)"MESSAGE", 7 };
676
+ const pj_str_t STR_MIME_TEXT_PLAIN = { (char*)"text/plain", 10 };
677
+ const pj_str_t STR_MIME_APP_ISCOMPOSING = { (char*)"application/im-iscomposing+xml", 30 };
566
678
 
567
679
  /* Register support for MESSAGE method. */
568
680
  status = pjsip_endpt_add_capability(g_sip_endpt, &mod_tester, PJSIP_H_ALLOW,
@@ -818,7 +930,7 @@ pjsip_transport *allocate_udp_transport(pjsip_endpoint* sip_endpt, pj_str_t *ipa
818
930
 
819
931
  pjsip_transport *create_udp_transport(pjsip_endpoint* sip_endpt, pj_str_t *ipaddr, int *allocated_port)
820
932
  {
821
- pj_status_t status;
933
+ //pj_status_t status;
822
934
  pjsip_transport *transport;
823
935
 
824
936
  int port = 5060;
@@ -836,11 +948,11 @@ pjsip_transport *create_udp_transport(pjsip_endpoint* sip_endpt, pj_str_t *ipadd
836
948
  }
837
949
 
838
950
  pjsip_tpfactory *allocate_tcp_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipaddr, int port) {
839
- printf("allocate_tcp_tpfactory ipaddr=%.*s port=%i\n", ipaddr->slen, ipaddr->ptr, port);
951
+ printf("allocate_tcp_tpfactory ipaddr=%.*s port=%i\n", (int)ipaddr->slen, ipaddr->ptr, port);
840
952
  pj_status_t status;
841
953
  pjsip_tpfactory *tpfactory;
842
954
  pj_sockaddr local_addr;
843
- pjsip_host_port a_name;
955
+ //pjsip_host_port a_name;
844
956
 
845
957
  int af;
846
958
  af = pj_AF_INET();
@@ -864,7 +976,7 @@ pjsip_tpfactory *allocate_tcp_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipa
864
976
 
865
977
  pjsip_tpfactory *create_tcp_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipaddr, int *allocated_port)
866
978
  {
867
- pj_status_t status;
979
+ //pj_status_t status;
868
980
  pjsip_tpfactory *tpfactory;
869
981
 
870
982
  int port = 6060;
@@ -886,7 +998,7 @@ pjsip_tpfactory *allocate_tls_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipa
886
998
  pj_status_t status;
887
999
  pjsip_tpfactory *tpfactory;
888
1000
  pj_sockaddr local_addr;
889
- pjsip_host_port a_name;
1001
+ //pjsip_host_port a_name;
890
1002
 
891
1003
  int af;
892
1004
  af = pj_AF_INET();
@@ -913,7 +1025,7 @@ pjsip_tpfactory *allocate_tls_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipa
913
1025
 
914
1026
  pjsip_tpfactory *create_tls_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipaddr, int *allocated_port)
915
1027
  {
916
- pj_status_t status;
1028
+ //pj_status_t status;
917
1029
  pjsip_tpfactory *tpfactory;
918
1030
 
919
1031
  int port = 6060;
@@ -930,31 +1042,83 @@ pjsip_tpfactory *create_tls_tpfactory(pjsip_endpoint* sip_endpt, pj_str_t *ipadd
930
1042
  return NULL;
931
1043
  }
932
1044
 
933
- int pjw_transport_create(const char *sip_ipaddr, int port, pjsip_transport_type_e type, int *out_t_id, int *out_port)
1045
+ //int pjw_transport_create(const char *sip_ipaddr, int port, pjsip_transport_type_e type, int *out_t_id, int *out_port)
1046
+ int pjw_transport_create(const char *json, int *out_t_id, char *out_t_address, int *out_port)
934
1047
  {
935
1048
  PJW_LOCK();
936
1049
  clear_error();
937
1050
 
938
- pj_str_t ipaddr = pj_str((char*)sip_ipaddr);
1051
+ char *addr;
1052
+ pj_str_t address; // = pj_str((char*)sip_ipaddr);
1053
+ int port = 0;
1054
+ pjsip_transport_type_e type = PJSIP_TRANSPORT_UDP;
939
1055
 
940
1056
  pj_status_t status;
941
1057
  Transport *t = NULL;
942
1058
  long t_id;
943
1059
 
1060
+ char buffer[MAX_JSON_INPUT];
1061
+
1062
+ Document document;
1063
+
1064
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1065
+ goto out;
1066
+ }
1067
+
1068
+ // address
1069
+ if(!document.HasMember("address")) {
1070
+ set_error("Parameter address is required");
1071
+ goto out;
1072
+ }
1073
+
1074
+ if(!document["address"].IsString()) {
1075
+ set_error("Parameter address must be a string");
1076
+ goto out;
1077
+ }
1078
+ addr = (char*)document["address"].GetString();
1079
+ address = pj_str((char*)addr);
1080
+
1081
+ // port
1082
+ if(document.HasMember("port")) {
1083
+ if(!document["port"].IsInt()) {
1084
+ set_error("Parameter port must be an integer");
1085
+ goto out;
1086
+ }
1087
+ port = document["port"].GetInt();
1088
+ }
1089
+
1090
+ // type
1091
+ if(document.HasMember("type")) {
1092
+ if(!document["type"].IsString()) {
1093
+ set_error("Parameter type must be a string");
1094
+ goto out;
1095
+ }
1096
+ const char *t = document["type"].GetString();
1097
+ if(stricmp(t, "UDP") == 0) {
1098
+ type = PJSIP_TRANSPORT_UDP;
1099
+ } else if(stricmp(t, "TCP") == 0) {
1100
+ type = PJSIP_TRANSPORT_TCP;
1101
+ } else if(stricmp(t, "TLS") == 0) {
1102
+ type = PJSIP_TRANSPORT_TLS;
1103
+ } else {
1104
+ set_error("Invalid type %s. It must be one of 'UDP' (default), 'TCP' or 'TLS'", type);
1105
+ goto out;
1106
+ }
1107
+ }
1108
+
944
1109
  if(type == PJSIP_TRANSPORT_UDP) {
945
1110
  pjsip_transport *sip_transport = NULL;
946
1111
 
947
1112
  if(port != 0) {
948
- sip_transport = allocate_udp_transport(g_sip_endpt, &ipaddr, port);
1113
+ sip_transport = allocate_udp_transport(g_sip_endpt, &address, port);
949
1114
  } else {
950
- sip_transport = create_udp_transport(g_sip_endpt, &ipaddr, &port);
1115
+ sip_transport = create_udp_transport(g_sip_endpt, &address, &port);
951
1116
  }
952
1117
 
953
1118
  if(!sip_transport)
954
1119
  {
955
- PJW_UNLOCK();
956
1120
  set_error("Unable to start UDP transport");
957
- return -1;
1121
+ goto out;
958
1122
  }
959
1123
 
960
1124
  t = new Transport;
@@ -963,32 +1127,27 @@ int pjw_transport_create(const char *sip_ipaddr, int port, pjsip_transport_type_
963
1127
 
964
1128
  if(!g_transport_ids.add((long)t, t_id)){
965
1129
  status = pjsip_udp_transport_pause(sip_transport,PJSIP_UDP_TRANSPORT_DESTROY_SOCKET);
966
- //ToDo: log status
967
-
968
- PJW_UNLOCK();
1130
+ printf("pjsip_dup_transport_pause status=%i\n", status);
969
1131
  set_error("Failed to allocate id");
970
- return -1;
1132
+ goto out;
971
1133
  }
972
1134
 
973
- if(type == PJSIP_TRANSPORT_UDP) {
974
- g_SipTransportMap.insert(make_pair(sip_transport, t_id));
975
- }
1135
+ g_SipTransportMap.insert(make_pair(sip_transport, t_id));
976
1136
  } else if(type == PJSIP_TRANSPORT_TCP) {
977
1137
  pjsip_tpfactory *tpfactory;
978
- int af;
1138
+ //int af;
979
1139
 
980
1140
 
981
1141
  if(port != 0) {
982
- tpfactory = allocate_tcp_tpfactory(g_sip_endpt, &ipaddr, port);
1142
+ tpfactory = allocate_tcp_tpfactory(g_sip_endpt, &address, port);
983
1143
  } else {
984
- tpfactory = create_tcp_tpfactory(g_sip_endpt, &ipaddr, &port);
1144
+ tpfactory = create_tcp_tpfactory(g_sip_endpt, &address, &port);
985
1145
  }
986
1146
 
987
1147
  if(!tpfactory)
988
1148
  {
989
- PJW_UNLOCK();
990
1149
  set_error("Unable to start TCP transport");
991
- return -1;
1150
+ goto out;
992
1151
  }
993
1152
 
994
1153
  t = new Transport;
@@ -998,40 +1157,37 @@ int pjw_transport_create(const char *sip_ipaddr, int port, pjsip_transport_type_
998
1157
  if(!g_transport_ids.add((long)t, t_id)){
999
1158
  status = (tpfactory->destroy)(tpfactory);
1000
1159
 
1001
- PJW_UNLOCK();
1002
1160
  set_error("Failed to allocate id");
1003
- return -1;
1161
+ goto out;
1004
1162
  }
1005
1163
 
1006
1164
  g_TcpTransportId = t_id;
1007
1165
  } else {
1008
1166
  pjsip_tpfactory *tpfactory;
1009
- int af;
1167
+ //int af;
1010
1168
 
1011
1169
 
1012
1170
  if(port != 0) {
1013
- tpfactory = allocate_tls_tpfactory(g_sip_endpt, &ipaddr, port);
1171
+ tpfactory = allocate_tls_tpfactory(g_sip_endpt, &address, port);
1014
1172
  } else {
1015
- tpfactory = create_tls_tpfactory(g_sip_endpt, &ipaddr, &port);
1173
+ tpfactory = create_tls_tpfactory(g_sip_endpt, &address, &port);
1016
1174
  }
1017
1175
 
1018
1176
  if(!tpfactory)
1019
1177
  {
1020
- PJW_UNLOCK();
1021
1178
  set_error("Unable to start TLS transport");
1022
- return -1;
1179
+ goto out;
1023
1180
  }
1024
1181
 
1025
1182
  t = new Transport;
1026
1183
  t->type = PJSIP_TRANSPORT_TLS;
1027
1184
  t->tpfactory = tpfactory;
1028
1185
 
1029
- if(!g_transport_ids.add((long)t, t_id)){
1186
+ if(!g_transport_ids.add((long)t, t_id)) {
1030
1187
  status = (tpfactory->destroy)(tpfactory);
1031
1188
 
1032
- PJW_UNLOCK();
1033
1189
  set_error("Failed to allocate id");
1034
- return -1;
1190
+ goto out;
1035
1191
  }
1036
1192
 
1037
1193
  g_TlsTransportId = t_id;
@@ -1039,14 +1195,18 @@ int pjw_transport_create(const char *sip_ipaddr, int port, pjsip_transport_type_
1039
1195
 
1040
1196
  t->id = t_id;
1041
1197
 
1042
- PJW_UNLOCK();
1043
-
1044
1198
  if(g_PacketDumper) {
1045
- g_PacketDumper->add_endpoint( inet_addr(sip_ipaddr), htons(port) );
1199
+ g_PacketDumper->add_endpoint( inet_addr(addr), htons(port) );
1046
1200
  }
1047
-
1201
+
1048
1202
  *out_t_id = t_id;
1203
+ strcpy(out_t_address, addr);
1049
1204
  *out_port = port;
1205
+ out:
1206
+ PJW_UNLOCK();
1207
+ if(pjw_errorstring[0]){
1208
+ return -1;
1209
+ }
1050
1210
  return 0;
1051
1211
  }
1052
1212
 
@@ -1056,71 +1216,122 @@ int pjw_transport_get_info(int t_id, char *out_sip_ipaddr, int *out_port)
1056
1216
  clear_error();
1057
1217
 
1058
1218
  long val;
1219
+ Transport *t;
1220
+
1221
+ int port;
1222
+ int len;
1059
1223
 
1060
1224
  if(!g_transport_ids.get(t_id, val)){
1061
- PJW_UNLOCK();
1062
1225
  set_error("Invalid transport_id");
1063
- return -1;
1226
+ goto out;
1064
1227
  }
1228
+ t = (Transport*)val;
1065
1229
 
1066
- Transport *t = (Transport*)val;
1067
-
1068
- int port = t->sip_transport->local_name.port;
1069
- int len = t->sip_transport->local_name.host.slen;
1070
- char addr[100];
1230
+ port = t->sip_transport->local_name.port;
1231
+ len = t->sip_transport->local_name.host.slen;
1071
1232
  strncpy(out_sip_ipaddr, t->sip_transport->local_name.host.ptr, len);
1072
1233
  out_sip_ipaddr[len] = 0;
1073
1234
  *out_port = port;
1074
1235
 
1236
+ out:
1075
1237
  PJW_UNLOCK();
1238
+ if(pjw_errorstring[0]){
1239
+ return -1;
1240
+ }
1076
1241
  return 0;
1077
1242
  }
1078
1243
 
1079
- int pjw_account_create(int t_id, const char *domain, const char *server, const char *username, const char *password, const char *additional_headers, const char *c_to_url, int expires, int *out_acc_id)
1244
+ //int pjw_account_create(int t_id, const char *domain, const char *server, const char *username, const char *password, const char *additional_headers, const char *c_to_url, int expires, int *out_acc_id)
1245
+ int pjw_account_create(int t_id, const char *json, int *out_acc_id)
1080
1246
  {
1081
- //printf("domain=%s, server=%s, username=%s, password=%s, additional_headers=%s, c_to_url=%s expires=%u\n", domain, server, username, password, additional_headers, c_to_url, expires);
1082
1247
  PJW_LOCK();
1083
1248
  clear_error();
1084
1249
 
1085
1250
  long val;
1086
1251
 
1252
+ pj_status_t status;
1253
+ pjsip_regc *regc;
1254
+
1255
+ char *domain;
1256
+ char *server;
1257
+ char *username;
1258
+ char *password;
1259
+ char *c_to_uri = NULL;
1260
+ int expires = 60;
1261
+
1262
+ pj_str_t server_uri;
1263
+ pj_str_t from_uri;
1264
+ pj_str_t to_uri;
1265
+ pj_str_t contact;
1266
+
1267
+ long acc_id;
1268
+
1269
+ Transport *t;
1270
+
1271
+ int local_port;
1272
+ int len;
1273
+ char local_addr[100];
1274
+
1275
+ char temp[400];
1276
+ char *p;
1277
+
1278
+ pjsip_cred_info cred;
1279
+ pjsip_tpselector sel;
1280
+
1281
+ char buffer[MAX_JSON_INPUT];
1282
+
1283
+ Document document;
1284
+
1087
1285
  if(!g_transport_ids.get(t_id, val)){
1088
- PJW_UNLOCK();
1089
1286
  set_error("Invalid transport id");
1090
- return -1;
1287
+ goto out;
1091
1288
  }
1289
+ t = (Transport*)val;
1290
+
1291
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1292
+ goto out;
1293
+ }
1092
1294
 
1093
- Transport *t = (Transport*)val;
1295
+ if(!json_get_string_param(document, "domain", false, &domain)) {
1296
+ goto out;
1297
+ }
1094
1298
 
1095
- pj_status_t status;
1096
- pjsip_regc *regc;
1299
+ if(!json_get_string_param(document, "server", false, &server)) {
1300
+ goto out;
1301
+ }
1302
+
1303
+ if(!json_get_string_param(document, "username", false, &username)) {
1304
+ goto out;
1305
+ }
1306
+
1307
+ if(!json_get_string_param(document, "password", false, &password)) {
1308
+ goto out;
1309
+ }
1310
+
1311
+ if(!json_get_string_param(document, "to_uri", true, &c_to_uri)) {
1312
+ goto out;
1313
+ }
1314
+
1315
+ if(!json_get_int_param(document, "expires", true, &expires)) {
1316
+ goto out;
1317
+ }
1097
1318
 
1098
1319
  status = pjsip_regc_create(g_sip_endpt, NULL, on_registration_status, &regc);
1099
1320
  if(status != PJ_SUCCESS)
1100
1321
  {
1101
- PJW_UNLOCK();
1102
- set_error("pjsip_regc_create failed");
1103
- return -1;
1322
+ set_error("pjsip_regc_create failed with status=%i", status);
1323
+ goto out;
1104
1324
  }
1105
1325
 
1106
- if(additional_headers) {
1107
- if(!add_additional_headers_for_account(regc, additional_headers)) {
1108
- PJW_UNLOCK();
1109
- set_error("add_additional_headers_for_account failed");
1110
- return -1;
1111
- }
1326
+ if(!add_headers_for_account(regc, document)) {
1327
+ goto out;
1112
1328
  }
1113
1329
 
1114
- long acc_id;
1115
1330
  if(!g_account_ids.add((long)regc, acc_id)){
1116
- PJW_UNLOCK();
1117
1331
  set_error("Failed to allocate id");
1118
- return -1;
1332
+ goto out;
1119
1333
  }
1120
1334
 
1121
- int local_port;
1122
- int len;
1123
- char local_addr[100];
1124
1335
  if(t->type == PJSIP_TRANSPORT_UDP) {
1125
1336
  local_port = t->sip_transport->local_name.port;
1126
1337
  len= t->sip_transport->local_name.host.slen;
@@ -1132,50 +1343,47 @@ int pjw_account_create(int t_id, const char *domain, const char *server, const c
1132
1343
  }
1133
1344
  local_addr[len] = 0;
1134
1345
 
1135
- char temp[400];
1136
- char *p = temp;
1346
+ p = temp;
1137
1347
 
1138
1348
  len = sprintf(p, "sip:%s", server);
1139
- pj_str_t server_url = pj_str(p);
1349
+ printf("server_uri=%s\n", p);
1350
+ server_uri = pj_str(p);
1140
1351
  p += len + 2;
1141
1352
 
1142
1353
  len = sprintf(p, "<sip:%s@%s>", username, domain);
1143
- pj_str_t from_url = pj_str(p);
1354
+ printf("from_uri=%s\n", p);
1355
+ from_uri = pj_str(p);
1144
1356
  p += len + 2;
1145
1357
 
1146
- pj_str_t to_url = from_url;
1147
-
1148
- if(c_to_url && c_to_url[0]) {
1149
- to_url = pj_str((char*)c_to_url);
1150
- }
1358
+ to_uri = from_uri;
1151
1359
 
1152
- if(expires <= 0) {
1153
- expires = 60;
1360
+ if(c_to_uri && c_to_uri[0]) {
1361
+ printf("c_to_uri=%s\n", c_to_uri);
1362
+ to_uri = pj_str((char*)c_to_uri);
1154
1363
  }
1155
1364
 
1156
1365
  len = sprintf(p, "sip:%s@%s:%u", username, local_addr, local_port);
1157
- pj_str_t contact = pj_str(p);
1366
+ printf("contact=%s\n", p);
1367
+ contact = pj_str(p);
1158
1368
  p += len + 2;
1159
1369
 
1160
1370
  status = pjsip_regc_init(regc,
1161
- &server_url,
1162
- &from_url,
1163
- &to_url,
1371
+ &server_uri,
1372
+ &from_uri,
1373
+ &to_uri,
1164
1374
  1, &contact,
1165
1375
  expires);
1166
1376
  if(status != PJ_SUCCESS)
1167
1377
  {
1168
1378
  status = pjsip_regc_destroy(regc);
1169
1379
  //ToDo: log status
1170
- PJW_UNLOCK();
1171
1380
  set_error("pjsip_regc_init failed");
1172
- return -1;
1381
+ goto out;
1173
1382
  }
1174
1383
 
1175
- pjsip_cred_info cred;
1176
1384
  pj_bzero(&cred, sizeof(cred));
1177
- cred.realm = pj_str("*");
1178
- cred.scheme = pj_str("digest");
1385
+ cred.realm = pj_str((char*)"*");
1386
+ cred.scheme = pj_str((char*)"digest");
1179
1387
  cred.username = pj_str((char*)username);
1180
1388
  cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
1181
1389
  cred.data = pj_str((char*)password);
@@ -1184,12 +1392,10 @@ int pjw_account_create(int t_id, const char *domain, const char *server, const c
1184
1392
  {
1185
1393
  status = pjsip_regc_destroy(regc);
1186
1394
  //ToDo: log status
1187
- PJW_UNLOCK();
1188
1395
  set_error("pjsip_regc_set_credentials failed");
1189
- return -1;
1396
+ goto out;
1190
1397
  }
1191
1398
 
1192
- pjsip_tpselector sel;
1193
1399
  pj_bzero(&sel, sizeof(sel));
1194
1400
  if(t->type == PJSIP_TRANSPORT_UDP) {
1195
1401
  sel.type = PJSIP_TPSELECTOR_TRANSPORT;
@@ -1204,50 +1410,72 @@ int pjw_account_create(int t_id, const char *domain, const char *server, const c
1204
1410
  {
1205
1411
  status = pjsip_regc_destroy(regc);
1206
1412
  //ToDo: log status
1207
- PJW_UNLOCK();
1208
1413
  set_error("pjsip_regc_set_transport failed");
1209
- return -1;
1414
+ goto out;
1210
1415
  }
1416
+
1417
+ out:
1211
1418
  PJW_UNLOCK();
1419
+ if(pjw_errorstring[0]){
1420
+ return -1;
1421
+ }
1422
+
1212
1423
  *out_acc_id = acc_id;
1213
1424
  return 0;
1214
1425
  }
1215
1426
 
1216
- int pjw_account_register(long acc_id, pj_bool_t autoreg)
1427
+ //int pjw_account_register(long acc_id, pj_bool_t autoreg)
1428
+ int pjw_account_register(long acc_id, const char *json)
1217
1429
  {
1218
1430
  PJW_LOCK();
1219
1431
  clear_error();
1220
1432
 
1221
1433
  long val;
1434
+ pjsip_regc *regc;
1435
+
1436
+ pj_status_t status;
1437
+ pjsip_tx_data *tdata;
1438
+
1439
+ char buffer[MAX_JSON_INPUT];
1440
+
1441
+ bool auto_register = false;
1442
+
1443
+ Document document;
1222
1444
 
1223
1445
  if(!g_account_ids.get(acc_id, val)){
1224
- PJW_UNLOCK();
1225
1446
  set_error("Invalid account_id");
1226
- return -1;
1447
+ goto out;
1227
1448
  }
1449
+ regc = (pjsip_regc*)val;
1228
1450
 
1229
- pjsip_regc *regc = (pjsip_regc*)val;
1451
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1452
+ goto out;
1453
+ }
1230
1454
 
1231
- pj_status_t status;
1232
- pjsip_tx_data *tdata;
1455
+ if(!json_get_bool_param(document, "auto_register", true, &auto_register)) {
1456
+ goto out;
1457
+ }
1233
1458
 
1234
- status = pjsip_regc_register(regc, autoreg, &tdata);
1459
+ status = pjsip_regc_register(regc, auto_register, &tdata);
1235
1460
  if(status != PJ_SUCCESS)
1236
1461
  {
1237
- PJW_UNLOCK();
1238
1462
  set_error("pjsip_regc_register failed");
1239
- return -1;
1463
+ goto out;
1240
1464
  }
1241
1465
 
1242
1466
  status = pjsip_regc_send(regc, tdata);
1243
1467
  if(status != PJ_SUCCESS)
1244
1468
  {
1245
- PJW_UNLOCK();
1246
1469
  set_error("pjsip_regc_send failed");
1247
- return -1;
1470
+ goto out;
1248
1471
  }
1249
1472
 
1473
+ out:
1250
1474
  PJW_UNLOCK();
1475
+ if(pjw_errorstring[0]){
1476
+ return -1;
1477
+ }
1478
+
1251
1479
  return 0;
1252
1480
  }
1253
1481
 
@@ -1258,63 +1486,88 @@ int pjw_account_unregister(long acc_id)
1258
1486
 
1259
1487
  long val;
1260
1488
 
1261
- if(!g_account_ids.get(acc_id, val)){
1262
- PJW_UNLOCK();
1263
- set_error("Invalid account_id");
1264
- return -1;
1265
- }
1266
-
1267
- pjsip_regc *regc = (pjsip_regc*)val;
1489
+ pjsip_regc *regc;
1268
1490
 
1269
1491
  pj_status_t status;
1270
1492
  pjsip_tx_data *tdata;
1271
1493
 
1494
+ if(!g_account_ids.get(acc_id, val)){
1495
+ set_error("Invalid account_id");
1496
+ goto out;
1497
+ }
1498
+ regc = (pjsip_regc*)val;
1499
+
1272
1500
  status = pjsip_regc_unregister(regc, &tdata);
1273
1501
  if(status != PJ_SUCCESS)
1274
1502
  {
1275
- PJW_UNLOCK();
1276
- set_error("pjsip_regc_unregister failed");
1277
- return -1;
1503
+ set_error("pjsip_regc_unregister failed with status=%i", status);
1504
+ goto out;
1278
1505
  }
1279
1506
 
1280
1507
  status = pjsip_regc_send(regc, tdata);
1281
1508
  if(status != PJ_SUCCESS)
1282
1509
  {
1283
- PJW_UNLOCK();
1284
- set_error("pjsip_regc_send failed");
1285
- return -1;
1510
+ set_error("pjsip_regc_send failed with status=%i", status);
1511
+ goto out;
1286
1512
  }
1287
1513
 
1514
+ out:
1288
1515
  PJW_UNLOCK();
1516
+ if(pjw_errorstring[0]){
1517
+ return -1;
1518
+ }
1519
+
1289
1520
  return 0;
1290
1521
  }
1291
1522
 
1292
- int pjw_call_respond(long call_id, int code, const char *reason, const char *additional_headers)
1523
+ //int pjw_call_respond(long call_id, int code, const char *reason, const char *additional_headers)
1524
+ int pjw_call_respond(long call_id, const char *json)
1293
1525
  {
1294
- printf("pjw_call_respond: call_id=%i code=%i reason=%s additional_headers=%s\n", call_id, code, reason, additional_headers);
1526
+ printf("pjw_call_respond: call_id=%lu json=%s\n", call_id, json);
1295
1527
  PJW_LOCK();
1528
+ clear_error();
1296
1529
 
1297
1530
  long val;
1298
1531
 
1532
+ int code;
1533
+ char *reason;
1534
+
1535
+ pj_str_t r;// pj_str((char*)reason);
1536
+
1537
+ pj_status_t status;
1538
+
1539
+ pjsip_tx_data *tdata;
1540
+
1541
+ Call *call;
1542
+
1543
+ char buffer[MAX_JSON_INPUT];
1544
+
1545
+ Document document;
1546
+
1299
1547
  if(!g_call_ids.get(call_id, val)){
1300
- PJW_UNLOCK();
1301
1548
  set_error("Invalid call_id");
1302
- return -1;
1549
+ goto out;
1303
1550
  }
1304
-
1305
- Call *call = (Call*)val;
1551
+ call = (Call*)val;
1306
1552
 
1307
1553
  if(call->outgoing) {
1308
- PJW_UNLOCK();
1309
1554
  set_error("You cannot respond an outgoing call");
1310
- return -1;
1555
+ goto out;
1311
1556
  }
1312
1557
 
1313
- pj_str_t r = pj_str((char*)reason);
1558
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1559
+ goto out;
1560
+ }
1561
+
1562
+ if(!json_get_int_param(document, "code", true, &code)) {
1563
+ goto out;
1564
+ }
1314
1565
 
1315
- pj_status_t status;
1566
+ if(!json_get_string_param(document, "reason", true, &reason)) {
1567
+ goto out;
1568
+ }
1316
1569
 
1317
- pjsip_tx_data *tdata;
1570
+ r = pj_str((char*)reason);
1318
1571
 
1319
1572
  if(call->initial_invite_rdata) {
1320
1573
  status = pjsip_inv_initial_answer(call->inv, call->initial_invite_rdata,
@@ -1323,16 +1576,14 @@ int pjw_call_respond(long call_id, int code, const char *reason, const char *add
1323
1576
  NULL,
1324
1577
  &tdata);
1325
1578
  if(status != PJ_SUCCESS) {
1326
- PJW_UNLOCK();
1327
- set_error("pjsip_inv_initial_answer failed");
1328
- return -1;
1579
+ set_error("pjsip_inv_initial_answer failed with status=%i", status);
1580
+ goto out;
1329
1581
  }
1330
1582
 
1331
1583
  status = pjsip_rx_data_free_cloned(call->initial_invite_rdata);
1332
1584
  if(status != PJ_SUCCESS) {
1333
- PJW_UNLOCK();
1334
- set_error("pjsip_rx_data_free_cloned failed");
1335
- return -1;
1585
+ set_error("pjsip_rx_data_free_cloned failed with status=%i", status);
1586
+ goto out;
1336
1587
  }
1337
1588
  call->initial_invite_rdata = 0;
1338
1589
  } else {
@@ -1343,150 +1594,210 @@ int pjw_call_respond(long call_id, int code, const char *reason, const char *add
1343
1594
  &tdata);
1344
1595
 
1345
1596
  if(status != PJ_SUCCESS){
1346
- PJW_UNLOCK();
1347
- set_error("pjsip_inv_answer failed");
1348
- return -1;
1597
+ set_error("pjsip_inv_answer failed with status=%i", status);
1598
+ goto out;
1349
1599
  }
1350
1600
 
1351
- if(!add_additional_headers(call->inv->dlg->pool, tdata, additional_headers)) {
1601
+ if(!add_headers(call->inv->dlg->pool, tdata, document)) {
1352
1602
  goto out;
1353
1603
  }
1354
1604
  }
1355
1605
 
1356
1606
  status = pjsip_inv_send_msg(call->inv, tdata);
1357
1607
  if(status != PJ_SUCCESS){
1358
- PJW_UNLOCK();
1359
- set_error("pjsip_inv_send_msg failed");
1360
- return -1;
1608
+ set_error("pjsip_inv_send_msg failed with status=%i", status);
1609
+ goto out;
1361
1610
  }
1362
1611
 
1363
1612
  out:
1364
1613
  PJW_UNLOCK();
1365
-
1366
1614
  if(pjw_errorstring[0]) {
1367
1615
  return -1;
1368
1616
  }
1369
-
1370
1617
  return 0;
1371
1618
  }
1372
1619
 
1373
- int pjw_call_terminate(long call_id, int code, const char *reason, const char *additional_headers)
1620
+ //int pjw_call_terminate(long call_id, int code, const char *reason, const char *additional_headers)
1621
+ int pjw_call_terminate(long call_id, const char *json)
1374
1622
  {
1375
1623
  PJW_LOCK();
1624
+ clear_error();
1376
1625
 
1377
1626
  long val;
1627
+ pjsip_tx_data *tdata;
1628
+ pj_status_t status;
1629
+ int code = 0;
1630
+ char *reason = (char*)"";
1631
+ pj_str_t r;// = pj_str((char*)reason);
1632
+
1633
+ Call *call;
1634
+
1635
+ char buffer[MAX_JSON_INPUT];
1636
+
1637
+ Document document;
1378
1638
 
1379
1639
  if(!g_call_ids.get(call_id, val)){
1380
- PJW_UNLOCK();
1381
1640
  set_error("Invalid call_id");
1382
- return -1;
1641
+ goto out;
1383
1642
  }
1643
+ call = (Call*)val;
1384
1644
 
1385
- Call *call = (Call*)val;
1645
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1646
+ goto out;
1647
+ }
1386
1648
 
1387
- pj_str_t r = pj_str((char*)reason);
1649
+ if(!json_get_int_param(document, "code", true, &code)) {
1650
+ goto out;
1651
+ }
1652
+
1653
+ if(!json_get_string_param(document, "reason", true, &reason)) {
1654
+ goto out;
1655
+ }
1656
+
1657
+ r = pj_str((char*)reason);
1388
1658
 
1389
- pjsip_tx_data *tdata;
1390
- pj_status_t status;
1391
1659
  status = pjsip_inv_end_session(call->inv,
1392
1660
  code,
1393
1661
  &r,
1394
1662
  &tdata);
1395
1663
  if(status != PJ_SUCCESS){
1396
- PJW_UNLOCK();
1397
1664
  set_error("pjsip_inv_end_session failed");
1398
- return -1;
1665
+ goto out;
1399
1666
  }
1400
1667
 
1401
1668
  if(!tdata)
1402
1669
  {
1403
1670
  //if tdata was not set by pjsip_inv_end_session, it means we didn't receive any response yet (100 Trying) and we cannot send CANCEL in this situation. So we just can return here without calling pjsip_inv_send_msg.
1404
- PJW_UNLOCK();
1405
- return 0;
1671
+ goto out;
1406
1672
  }
1407
1673
 
1408
- if(!add_additional_headers(call->inv->dlg->pool, tdata, additional_headers)) {
1409
- PJW_UNLOCK();
1410
- set_error("add_additional_headers failed");
1411
- return -1;
1674
+ if(!add_headers(call->inv->dlg->pool, tdata, document)) {
1675
+ goto out;
1412
1676
  }
1413
1677
 
1414
1678
  status = pjsip_inv_send_msg(call->inv, tdata);
1415
1679
  if(status != PJ_SUCCESS){
1416
- PJW_UNLOCK();
1417
- set_error("pjsip_inv_send_msg failed");
1418
- return -1;
1680
+ set_error("pjsip_inv_send_msg failed with status=%i", status);
1681
+ goto out;
1419
1682
  }
1420
1683
 
1684
+ out:
1421
1685
  PJW_UNLOCK();
1686
+ if(pjw_errorstring[0]){
1687
+ return -1;
1688
+ }
1689
+
1422
1690
  return 0;
1423
1691
  }
1424
1692
 
1425
1693
 
1426
- int pjw_call_create(long t_id, unsigned flags, const char *from_uri, const char *to_uri, const char *request_uri, const char *proxy_uri, const char *additional_headers, const char *realm, const char *username, const char *password, long *out_call_id, char *out_sip_call_id)
1694
+ //int pjw_call_create(long t_id, unsigned flags, const char *from_uri, const char *to_uri, const char *request_uri, const char *proxy_uri, const char *additional_headers, const char *realm, const char *username, const char *password, long *out_call_id, char *out_sip_call_id)
1695
+ int pjw_call_create(long t_id, const char *json, long *out_call_id, char *out_sip_call_id)
1427
1696
  {
1428
1697
  PJW_LOCK();
1429
1698
  clear_error();
1430
1699
 
1431
- int n;
1700
+ //int n;
1432
1701
  long val;
1433
1702
  Transport *t;
1434
- char *start;
1435
- char *end;
1703
+ //char *start;
1704
+ //char *end;
1436
1705
  char local_contact[400];
1437
- char *p;
1438
- int len;
1706
+ //char *p;
1707
+ //int len;
1439
1708
  const char *contact_username = "sip";
1440
1709
  int call_id;
1441
1710
 
1711
+ char *from_uri = NULL;
1712
+ char *to_uri = NULL;
1713
+ char *request_uri = NULL;
1714
+ char *proxy_uri = NULL;
1715
+
1716
+ char *realm = NULL;
1717
+ char *username = NULL;
1718
+ char *password = NULL;
1719
+
1720
+ unsigned flags = 0;
1442
1721
 
1443
1722
  pjsip_dialog *dlg;
1444
1723
 
1724
+ char buffer[MAX_JSON_INPUT];
1725
+
1726
+ Document document;
1727
+
1445
1728
  if(!g_transport_ids.get(t_id, val)){
1446
1729
  set_error("Invalid transport_id");
1447
1730
  goto out;
1448
1731
  }
1449
1732
  t = (Transport*)val;
1450
1733
 
1451
- if(!check_uri(from_uri)) {
1452
- set_error("Invalid from_uri");
1453
- goto out;
1454
- }
1734
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
1735
+ goto out;
1736
+ }
1455
1737
 
1456
- if(!check_uri(to_uri)) {
1457
- set_error("Invalid to_uri");
1458
- goto out;
1459
- }
1738
+ if(!json_get_and_check_uri(document, "from_uri", false, &from_uri)) {
1739
+ goto out;
1740
+ }
1741
+
1742
+ if(!json_get_and_check_uri(document, "to_uri", false, &to_uri)) {
1743
+ goto out;
1744
+ }
1460
1745
 
1461
- if(request_uri){
1462
- if(request_uri[0]) {
1463
- if(!check_uri(request_uri)) {
1464
- set_error("Invalid request_uri");
1465
- goto out;
1466
- }
1746
+ request_uri = to_uri;
1747
+ if(!json_get_and_check_uri(document, "request_uri", true, &request_uri)) {
1748
+ goto out;
1749
+ }
1750
+
1751
+ if(!json_get_and_check_uri(document, "proxy_uri", true, &proxy_uri)) {
1752
+ goto out;
1753
+ }
1754
+
1755
+ if(document.HasMember("auth")) {
1756
+ if(!document["auth"].IsObject()) {
1757
+ set_error("Parameter auth must be an object");
1758
+ goto out;
1759
+ } else {
1760
+ const Value& auth = document["auth"];
1761
+
1762
+ for (Value::ConstMemberIterator itr = auth.MemberBegin(); itr != auth.MemberEnd(); ++itr) {
1763
+ const char *name = itr->name.GetString();
1764
+ if(strcmp(name, "realm") == 0) {
1765
+ if(!itr->value.IsString()) {
1766
+ set_error("%s must be a string", itr->name.GetString());
1767
+ goto out;
1768
+ }
1769
+ realm = (char*)itr->value.GetString();
1770
+ } else if(strcmp(name, "username") == 0) {
1771
+ if(!itr->value.IsString()) {
1772
+ set_error("%s must be a string", itr->name.GetString());
1773
+ goto out;
1774
+ }
1775
+ username = (char*)itr->value.GetString();
1776
+ contact_username = username;
1777
+ } else if(strcmp(name, "password") == 0) {
1778
+ if(!itr->value.IsString()) {
1779
+ set_error("%s must be a string", itr->name.GetString());
1780
+ goto out;
1781
+ }
1782
+ password = (char*)itr->value.GetString();
1467
1783
  } else {
1468
- request_uri = to_uri;
1784
+ set_error("Unknown auth paramter %s", itr->name.GetString());
1785
+ goto out;
1469
1786
  }
1470
- }else{
1471
- request_uri = to_uri;
1787
+ }
1472
1788
  }
1789
+ }
1473
1790
 
1474
- if(proxy_uri){
1475
- if(proxy_uri[0]) {
1476
- if(!check_uri(proxy_uri)) {
1477
- set_error("Invalid proxy_uri");
1478
- goto out;
1479
- }
1480
- }
1791
+ if(document.HasMember("delayed_media")) {
1792
+ if(!document["delayed_media"].IsBool()) {
1793
+ set_error("Parameter delayed_media must be a boolean");
1794
+ goto out;
1795
+ } else {
1796
+ if(document["delayed_media"].GetBool()) {
1797
+ flags = flags | CALL_FLAG_DELAYED_MEDIA;
1798
+ }
1481
1799
  }
1482
-
1483
- if(realm){
1484
- if(!username || !password) {
1485
- set_error("Incomplete credentials");
1486
- goto out;
1487
- }
1488
- contact_username = username;
1489
- }
1800
+ }
1490
1801
 
1491
1802
  if(t->type == PJSIP_TRANSPORT_UDP) {
1492
1803
  build_local_contact(local_contact, t->sip_transport, contact_username);
@@ -1498,7 +1809,7 @@ int pjw_call_create(long t_id, unsigned flags, const char *from_uri, const char
1498
1809
  goto out;
1499
1810
  }
1500
1811
 
1501
- call_id = call_create(t, flags, dlg, proxy_uri, additional_headers);
1812
+ call_id = call_create(t, flags, dlg, proxy_uri, document);
1502
1813
  if(call_id < 0) {
1503
1814
  goto out;
1504
1815
  }
@@ -1620,6 +1931,7 @@ bool set_proxy(pjsip_dialog *dlg, const char *proxy_uri) {
1620
1931
  NULL);
1621
1932
  if(!route){
1622
1933
  status = pjsip_dlg_terminate(dlg); //ToDo:
1934
+ printf("pjsip_dlg_terminate status=%i\n", status);
1623
1935
  set_error("pjsip_parse_hdr failed");
1624
1936
  return false;
1625
1937
  }
@@ -1658,7 +1970,7 @@ bool dlg_create(pjsip_dialog **dlg, Transport *transport, const char *from_uri,
1658
1970
 
1659
1971
  if(realm && realm[0]){
1660
1972
  pjsip_cred_info cred[1];
1661
- cred[0].scheme = pj_str("digest");
1973
+ cred[0].scheme = pj_str((char*)"digest");
1662
1974
  cred[0].realm = pj_str((char*)realm);
1663
1975
  cred[0].username = pj_str((char*)username);
1664
1976
  cred[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
@@ -1671,11 +1983,12 @@ bool dlg_create(pjsip_dialog **dlg, Transport *transport, const char *from_uri,
1671
1983
  }
1672
1984
  }
1673
1985
 
1674
- return *dlg = p_dlg;
1986
+ *dlg = p_dlg;
1987
+ return true;
1675
1988
  }
1676
1989
 
1677
1990
 
1678
- int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, const char *additional_headers)
1991
+ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, Document &document)
1679
1992
  {
1680
1993
  pjsip_inv_session *inv;
1681
1994
  //in_addr addr;
@@ -1706,7 +2019,7 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *pro
1706
2019
 
1707
2020
  pjmedia_sdp_session *sdp = 0;
1708
2021
 
1709
- if(!(flags & CALL_FLAG_LATE_NEGOTIATION)) {
2022
+ if(!(flags & CALL_FLAG_DELAYED_MEDIA)) {
1710
2023
  status = pjmedia_endpt_create_sdp( g_med_endpt,
1711
2024
  dlg->pool,
1712
2025
  1,
@@ -1760,7 +2073,7 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *pro
1760
2073
 
1761
2074
 
1762
2075
 
1763
- if(!add_additional_headers(dlg->pool, tdata, additional_headers)) {
2076
+ if(!add_headers(dlg->pool, tdata, document)) {
1764
2077
  g_call_ids.remove(call_id, (long &)call);
1765
2078
  close_media_transport(med_transport); //Todo:
1766
2079
  status = pjsip_dlg_terminate(dlg); //ToDo:
@@ -1800,7 +2113,8 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *pro
1800
2113
  return call_id;
1801
2114
  }
1802
2115
 
1803
- int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
2116
+ //int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
2117
+ int pjw_call_send_dtmf(long call_id, const char *json)
1804
2118
  {
1805
2119
  #define ON_DURATION 200
1806
2120
  #define OFF_DURATION 50
@@ -1808,38 +2122,61 @@ int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
1808
2122
  #define MAX_LENGTH 31 // pjsip allows for 31 digits (inband allows for 32 digits)
1809
2123
 
1810
2124
  PJW_LOCK();
1811
- int len = strlen(digits);
2125
+ clear_error();
1812
2126
 
1813
- if(mode != DTMF_MODE_RFC2833 && mode != DTMF_MODE_INBAND) {
1814
- PJW_UNLOCK();
1815
- set_error("Invalid DTMF mode");
1816
- return -1;
1817
- }
2127
+ long val;
2128
+ char *digits;
2129
+ int mode = 0;;
1818
2130
 
1819
- if(len > MAX_LENGTH) {
1820
- set_error("DTMF list too long");
1821
- return -1;
1822
- }
2131
+ int len;
1823
2132
 
1824
- long val;
2133
+ char adjusted_digits[MAX_LENGTH+1]; // use the greater size
2134
+
2135
+ pj_str_t ds;
2136
+ pj_status_t status;
2137
+
2138
+ Call *call;
2139
+
2140
+ char buffer[MAX_JSON_INPUT];
2141
+
2142
+ Document document;
2143
+
2144
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2145
+ goto out;
2146
+ }
1825
2147
 
1826
2148
  if(!g_call_ids.get(call_id, val)){
1827
- PJW_UNLOCK();
1828
2149
  set_error("Invalid call_id");
1829
- return -1;
2150
+ goto out;
1830
2151
  }
2152
+ call = (Call*)val;
1831
2153
 
1832
- Call *call = (Call*)val;
2154
+ if(!json_get_string_param(document, "digits", false, &digits)) {
2155
+ goto out;
2156
+ }
2157
+
2158
+ if(!json_get_int_param(document, "mode", false, &mode)) {
2159
+ goto out;
2160
+ }
2161
+
2162
+ if(mode != DTMF_MODE_RFC2833 && mode != DTMF_MODE_INBAND) {
2163
+ set_error("Invalid DTMF mode. It must be eiter 0 (RFC2833) or 1 (INBAND).");
2164
+ goto out;
2165
+ }
2166
+
2167
+ len = strlen(digits);
2168
+
2169
+ if(len > MAX_LENGTH) {
2170
+ set_error("DTMF string too long");
2171
+ goto out;
2172
+ }
1833
2173
 
1834
2174
  if(!call->med_stream)
1835
2175
  {
1836
- PJW_UNLOCK();
1837
2176
  set_error("Unable to send DTMF: Media not ready");
1838
- return -1;
2177
+ goto out;
1839
2178
  }
1840
2179
 
1841
- char adjusted_digits[MAX_LENGTH+1]; // use the greater size
1842
-
1843
2180
  for(int i=0; i<len ; ++i) {
1844
2181
  if( !(digits[i] >= '0' && digits[i] <= '9') &&
1845
2182
  !(digits[i] >= 'a' && digits[i] <= 'f') &&
@@ -1847,9 +2184,8 @@ int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
1847
2184
  !(digits[i] == '*') &&
1848
2185
  !(digits[i] == '#') )
1849
2186
  {
1850
- PJW_UNLOCK();
1851
2187
  set_error("Invalid character");
1852
- return -1;
2188
+ goto out;
1853
2189
  }
1854
2190
  char d = digits[i];
1855
2191
  if(d == 'e' || d == 'E') {
@@ -1863,22 +2199,19 @@ int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
1863
2199
  adjusted_digits[len] = 0;
1864
2200
  //addon_log(LOG_LEVEL_DEBUG, ">>%s<<\n", adjusted_digits);
1865
2201
 
1866
- pj_str_t ds = pj_str((char*)adjusted_digits);
1867
- pj_status_t status;
2202
+ ds = pj_str((char*)adjusted_digits);
1868
2203
 
1869
2204
  if(DTMF_MODE_RFC2833 == mode) {
1870
2205
  status = pjmedia_stream_dial_dtmf(call->med_stream, &ds);
1871
2206
  if(status != PJ_SUCCESS)
1872
2207
  {
1873
- PJW_UNLOCK();
1874
2208
  set_error("pjmedia_stream_dial_dtmf failed.");
1875
- return -1;
2209
+ goto out;
1876
2210
  }
1877
2211
  } else {
1878
2212
  if(!prepare_tonegen(call)) {
1879
- PJW_UNLOCK();
1880
2213
  set_error("prepare_tonegen failed.");
1881
- return -1;
2214
+ goto out;
1882
2215
  }
1883
2216
 
1884
2217
  for(int i=0; i<len ; ++i) {
@@ -1889,38 +2222,72 @@ int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
1889
2222
  tone.volume = 0;
1890
2223
  status = chainlink_tonegen_play_digits((pjmedia_port*)call->tonegen, 1, &tone, 0);
1891
2224
  if(status != PJ_SUCCESS) {
1892
- PJW_UNLOCK();
1893
2225
  set_error("chainlink_tonegen_play_digits failed.");
1894
- return -1;
2226
+ goto out;
1895
2227
  }
1896
2228
  }
1897
2229
  }
1898
2230
 
2231
+ out:
1899
2232
  PJW_UNLOCK();
2233
+ if(pjw_errorstring[0]){
2234
+ return -1;
2235
+ }
2236
+
1900
2237
  return 0;
1901
2238
  }
1902
2239
 
1903
- int pjw_call_reinvite(long call_id, int hold, unsigned flags)
2240
+ //int pjw_call_reinvite(long call_id, int hold, unsigned flags)
2241
+ int pjw_call_reinvite(long call_id, const char *json)
1904
2242
  {
1905
2243
  PJW_LOCK();
2244
+ clear_error();
2245
+
2246
+ bool hold = false;
2247
+ unsigned flags;
1906
2248
 
1907
2249
  long val;
2250
+ Call *call;
2251
+
2252
+ pj_status_t status;
2253
+
2254
+ const pjmedia_sdp_session *old_sdp = NULL;
2255
+
2256
+ pjsip_tx_data *tdata;
2257
+ pjmedia_sdp_session *sdp = 0;
2258
+
2259
+ char buffer[MAX_JSON_INPUT];
2260
+
2261
+ Document document;
1908
2262
 
1909
2263
  if(!g_call_ids.get(call_id, val)){
1910
- PJW_UNLOCK();
1911
- set_error("Invalid call_id");
1912
- return -1;
2264
+ set_error("Invalid call_id");
2265
+ goto out;
1913
2266
  }
2267
+ call = (Call*)val;
1914
2268
 
1915
- Call *call = (Call*)val;
2269
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2270
+ goto out;
2271
+ }
1916
2272
 
1917
- pj_status_t status;
2273
+ if(!json_get_bool_param(document, "hold", true, &hold)) {
2274
+ goto out;
2275
+ }
1918
2276
 
1919
- pjmedia_sdp_session *sdp = 0;
2277
+ if(document.HasMember("delayed_media")) {
2278
+ if(!document["delayed_media"].IsBool()) {
2279
+ set_error("Parameter delayed_media must be a boolean");
2280
+ goto out;
2281
+ } else {
2282
+ if(document["delayed_media"].GetBool()) {
2283
+ flags = flags | CALL_FLAG_DELAYED_MEDIA;
2284
+ }
2285
+ }
2286
+ }
1920
2287
 
1921
2288
  call->local_hold = hold;
1922
2289
 
1923
- if(!(flags & CALL_FLAG_LATE_NEGOTIATION)) {
2290
+ if(!(flags & CALL_FLAG_DELAYED_MEDIA)) {
1924
2291
  pjmedia_transport_info tpinfo;
1925
2292
  pjmedia_transport_info_init(&tpinfo);
1926
2293
  pjmedia_transport_get_info(call->med_transport,&tpinfo);
@@ -1931,9 +2298,8 @@ int pjw_call_reinvite(long call_id, int hold, unsigned flags)
1931
2298
  &tpinfo.sock_info,
1932
2299
  &sdp);
1933
2300
  if(status != PJ_SUCCESS){
1934
- PJW_UNLOCK();
1935
2301
  set_error("pjmedia_endpt_create_sdp failed");
1936
- return -1;
2302
+ goto out;
1937
2303
  }
1938
2304
 
1939
2305
  pjmedia_sdp_attr *attr;
@@ -1957,47 +2323,54 @@ int pjw_call_reinvite(long call_id, int hold, unsigned flags)
1957
2323
 
1958
2324
  pjmedia_sdp_media_add_attr(sdp->media[0], attr);
1959
2325
 
1960
- const pjmedia_sdp_session *old_sdp = NULL;
2326
+ old_sdp = NULL;
1961
2327
 
1962
2328
  status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &old_sdp);
1963
2329
  if (status != PJ_SUCCESS || old_sdp == NULL){
1964
- PJW_UNLOCK();
1965
2330
  set_error("pjmedia_sdp_neg_get_active failed");
1966
- return -1;
2331
+ goto out;
1967
2332
  }
1968
2333
 
1969
2334
  sdp->origin.version = old_sdp->origin.version + 1;
1970
2335
  }
1971
2336
 
1972
- pjsip_tx_data *tdata;
1973
2337
  status = pjsip_inv_reinvite(call->inv, NULL, sdp, &tdata);
1974
2338
  if(status != PJ_SUCCESS){
1975
- PJW_UNLOCK();
1976
2339
  set_error("pjsip_inv_reinvite failed");
1977
- return -1;
2340
+ goto out;
1978
2341
  }
1979
2342
 
1980
2343
  status = pjsip_inv_send_msg(call->inv, tdata);
1981
2344
  if(status != PJ_SUCCESS){
1982
- PJW_UNLOCK();
1983
2345
  set_error("pjsip_inv_send_msg failed");
1984
- return -1;
2346
+ goto out;
1985
2347
  }
1986
2348
 
2349
+ out:
1987
2350
  PJW_UNLOCK();
2351
+ if(pjw_errorstring[0]){
2352
+ return -1;
2353
+ }
2354
+
1988
2355
  return 0;
1989
2356
  }
1990
2357
 
1991
2358
  //To send INFO and other requests inside dialog
1992
- int pjw_call_send_request(long call_id, const char *method_name, const char *additional_headers, const char *body, const char *ct_type, const char *ct_subtype)
2359
+ //int pjw_call_send_request(long call_id, const char *method_name, const char *additional_headers, const char *body, const char *ct_type, const char *ct_subtype)
2360
+ int pjw_call_send_request(long call_id, const char *json)
1993
2361
  {
1994
2362
  PJW_LOCK();
1995
2363
  clear_error();
1996
2364
 
1997
- pj_str_t s_method_name;
2365
+ char *method = NULL;
2366
+ char *body = NULL;
2367
+ char *ct_type = NULL;
2368
+ char *ct_subtype = NULL;
2369
+
2370
+ pj_str_t s_method;
1998
2371
  pjsip_tx_data *tdata;
1999
2372
  pj_status_t status;
2000
- pjsip_method method;
2373
+ pjsip_method meth;
2001
2374
 
2002
2375
  pjsip_msg_body *msg_body;
2003
2376
 
@@ -2009,14 +2382,37 @@ int pjw_call_send_request(long call_id, const char *method_name, const char *add
2009
2382
 
2010
2383
  long val;
2011
2384
 
2385
+ char buffer[MAX_JSON_INPUT];
2386
+
2387
+ Document document;
2388
+
2389
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2390
+ goto out;
2391
+ }
2392
+
2012
2393
  if(!g_call_ids.get(call_id, val)){
2013
2394
  set_error("Invalid call_id");
2014
2395
  goto out;
2015
2396
  }
2016
-
2017
2397
  call = (Call*)val;
2018
2398
 
2019
- if(strcmp(method_name,"INVITE")==0 || strcmp(method_name,"UPDATE")==0 || strcmp(method_name,"PRACK")==0 || strcmp(method_name,"BYE")==0) {
2399
+ if(!json_get_string_param(document, "method", false, &method)) {
2400
+ goto out;
2401
+ }
2402
+
2403
+ if(!json_get_string_param(document, "body", true, &body)) {
2404
+ goto out;
2405
+ }
2406
+
2407
+ if(!json_get_string_param(document, "ct_type", true, &ct_type)) {
2408
+ goto out;
2409
+ }
2410
+
2411
+ if(!json_get_string_param(document, "ct_subtype", true, &ct_subtype)) {
2412
+ goto out;
2413
+ }
2414
+
2415
+ if(strcmp(method,"INVITE")==0 || strcmp(method,"UPDATE")==0 || strcmp(method,"PRACK")==0 || strcmp(method,"BYE")==0) {
2020
2416
  set_error("Invalid method");
2021
2417
  goto out;
2022
2418
  }
@@ -2028,17 +2424,17 @@ int pjw_call_send_request(long call_id, const char *method_name, const char *add
2028
2424
  }
2029
2425
  }
2030
2426
 
2031
- s_method_name = pj_str((char*)method_name);
2427
+ s_method = pj_str((char*)method);
2032
2428
 
2033
- pjsip_method_init_np(&method, &s_method_name);
2429
+ pjsip_method_init_np(&meth, &s_method);
2034
2430
 
2035
- status = pjsip_dlg_create_request(call->inv->dlg, &method, -1, &tdata);
2431
+ status = pjsip_dlg_create_request(call->inv->dlg, &meth, -1, &tdata);
2036
2432
  if (status != PJ_SUCCESS) {
2037
- set_error("pjsip_dlg_create_request failed");
2433
+ set_error("pjsip_dlg_create_request failed with status=%i", status);
2038
2434
  goto out;
2039
2435
  }
2040
2436
 
2041
- if(!add_additional_headers(call->inv->dlg->pool, tdata, additional_headers)) {
2437
+ if(!add_headers(call->inv->dlg->pool, tdata, document)) {
2042
2438
  goto out;
2043
2439
  }
2044
2440
 
@@ -2058,222 +2454,294 @@ int pjw_call_send_request(long call_id, const char *method_name, const char *add
2058
2454
 
2059
2455
  status = pjsip_dlg_send_request(call->inv->dlg, tdata, -1, NULL);
2060
2456
  if (status != PJ_SUCCESS) {
2061
- set_error("pjsip_dlg_send_request failed");
2457
+ set_error("pjsip_dlg_send_request failed with status=%i", status);
2062
2458
  goto out;
2063
2459
  }
2064
2460
 
2065
- PJW_UNLOCK();
2066
- return 0;
2067
-
2068
2461
  out:
2069
2462
  PJW_UNLOCK();
2070
-
2071
2463
  if(pjw_errorstring[0]) {
2072
2464
  return -1;
2073
2465
  }
2074
- return 0;
2075
2466
 
2467
+ return 0;
2076
2468
  }
2077
2469
 
2078
- int pjw_call_start_record_wav(long call_id, const char *file)
2470
+ //int pjw_call_start_record_wav(long call_id, const char *file)
2471
+ int pjw_call_start_record_wav(long call_id, const char *json)
2079
2472
  {
2080
2473
  PJW_LOCK();
2474
+ clear_error();
2081
2475
 
2082
2476
  long val;
2477
+ Call *call;
2478
+ pj_status_t status;
2479
+ pjmedia_port *stream_port;
2480
+
2481
+ char *file;
2482
+
2483
+ char buffer[MAX_JSON_INPUT];
2484
+
2485
+ Document document;
2083
2486
 
2084
2487
  if(!g_call_ids.get(call_id, val)){
2085
- PJW_UNLOCK();
2086
2488
  set_error("Invalid call_id");
2087
- return -1;
2489
+ goto out;
2088
2490
  }
2089
-
2090
- Call *call = (Call*)val;
2491
+ call = (Call*)val;
2091
2492
 
2092
2493
  if(!call->med_stream)
2093
2494
  {
2094
- PJW_UNLOCK();
2095
2495
  set_error("Media not ready");
2096
- return -1;
2496
+ goto out;
2097
2497
  }
2098
2498
 
2099
- pj_status_t status;
2499
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2500
+ goto out;
2501
+ }
2100
2502
 
2101
- pjmedia_port *stream_port;
2503
+ if(!json_get_string_param(document, "file", false, &file)) {
2504
+ goto out;
2505
+ }
2506
+
2507
+ if(!file[0]) {
2508
+ set_error("file cannot be blank string");
2509
+ goto out;
2510
+ }
2511
+
2102
2512
  status = pjmedia_stream_get_port(call->med_stream,
2103
2513
  &stream_port);
2104
2514
  if(status != PJ_SUCCESS)
2105
2515
  {
2106
- PJW_UNLOCK();
2107
- set_error("pjmedia_stream_get_port failed");
2108
- return -1;
2516
+ set_error("pjmedia_stream_get_port failed with status=%i", status);
2517
+ goto out;
2109
2518
  }
2110
2519
 
2111
2520
  if(!prepare_wav_writer(call, file)) {
2112
- PJW_UNLOCK();
2113
2521
  set_error("prepare_wav_writer failed");
2114
- return -1;
2522
+ goto out;
2115
2523
  }
2116
2524
 
2525
+ out:
2117
2526
  PJW_UNLOCK();
2527
+ if(pjw_errorstring[0]){
2528
+ return -1;
2529
+ }
2530
+
2118
2531
  return 0;
2119
2532
  }
2120
2533
 
2121
2534
 
2122
- int pjw_call_start_play_wav(long call_id, const char *file)
2535
+ //int pjw_call_start_play_wav(long call_id, const char *file)
2536
+ int pjw_call_start_play_wav(long call_id, const char *json)
2123
2537
  {
2124
2538
  PJW_LOCK();
2539
+ clear_error();
2125
2540
 
2126
2541
  long val;
2542
+ Call *call;
2543
+ pj_status_t status;
2544
+ pjmedia_port *stream_port;
2545
+
2546
+ char *file;
2547
+
2548
+ char buffer[MAX_JSON_INPUT];
2549
+
2550
+ Document document;
2127
2551
 
2128
2552
  if(!g_call_ids.get(call_id, val)){
2129
- PJW_UNLOCK();
2130
2553
  set_error("Invalid call_id");
2131
- return -1;
2554
+ goto out;
2132
2555
  }
2133
-
2134
- Call *call = (Call*)val;
2556
+ call = (Call*)val;
2135
2557
 
2136
2558
  if(!call->med_stream)
2137
2559
  {
2138
- PJW_UNLOCK();
2139
2560
  set_error("Media not ready");
2140
- return -1;
2561
+ goto out;
2141
2562
  }
2142
2563
 
2143
- pj_status_t status;
2564
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2565
+ goto out;
2566
+ }
2567
+
2568
+ if(!json_get_string_param(document, "file", false, &file)) {
2569
+ goto out;
2570
+ }
2571
+
2572
+ if(!file[0]) {
2573
+ set_error("file cannot be blank string");
2574
+ goto out;
2575
+ }
2144
2576
 
2145
- pjmedia_port *stream_port;
2146
2577
  status = pjmedia_stream_get_port(call->med_stream,
2147
2578
  &stream_port);
2148
2579
  if(status != PJ_SUCCESS)
2149
2580
  {
2150
- PJW_UNLOCK();
2151
- set_error("pjmedia_stream_get_port failed");
2152
- return -1;
2581
+ set_error("pjmedia_stream_get_port failed with status=%i", status);
2582
+ goto out;
2153
2583
  }
2154
2584
 
2155
2585
  if(!prepare_wav_player(call, file)){
2156
- PJW_UNLOCK();
2157
- set_error("pjmedia_wav_player_port_create failed");
2158
- return -1;
2159
- }
2586
+ set_error("prepare_wav_player failed");
2587
+ goto out;
2588
+ }
2160
2589
 
2590
+ out:
2161
2591
  PJW_UNLOCK();
2592
+ if(pjw_errorstring[0]){
2593
+ return -1;
2594
+ }
2595
+
2162
2596
  return 0;
2163
2597
  }
2164
2598
 
2165
2599
  int pjw_call_stop_play_wav(long call_id)
2166
2600
  {
2167
2601
  PJW_LOCK();
2602
+ clear_error();
2603
+
2604
+ Call *call;
2605
+
2606
+ pjmedia_port *stream_port;
2607
+ pj_status_t status;
2168
2608
 
2169
2609
  long val;
2170
2610
 
2171
2611
  if(!g_call_ids.get(call_id, val)){
2172
- PJW_UNLOCK();
2173
2612
  set_error("Invalid call_id");
2174
- return -1;
2613
+ goto out;
2175
2614
  }
2615
+ call = (Call*)val;
2176
2616
 
2177
- Call *call = (Call*)val;
2178
-
2179
- pjmedia_port *stream_port;
2180
- pj_status_t status;
2181
2617
  status = pjmedia_stream_get_port(call->med_stream,
2182
2618
  &stream_port);
2183
2619
  if(status != PJ_SUCCESS) {
2184
- PJW_UNLOCK();
2185
- set_error("pjmedia_stream_get_port failed.");
2186
- return -1;
2620
+ set_error("pjmedia_stream_get_port failed with status=%i", status);
2621
+ goto out;
2187
2622
  }
2188
2623
 
2189
2624
  if(!prepare_wire(call->inv->pool, &call->wav_player, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info))) {
2190
- PJW_UNLOCK();
2191
2625
  set_error("prepare_wire failed.");
2192
- return -1;
2626
+ goto out;
2193
2627
  }
2194
2628
 
2195
2629
  connect_media_ports(call);
2196
2630
 
2631
+ out:
2197
2632
  PJW_UNLOCK();
2633
+ if(pjw_errorstring[0]){
2634
+ return -1;
2635
+ }
2636
+
2198
2637
  return 0;
2199
2638
  }
2200
2639
 
2201
2640
  int pjw_call_stop_record_wav(long call_id)
2202
2641
  {
2203
2642
  PJW_LOCK();
2643
+ clear_error();
2204
2644
 
2205
2645
  long val;
2646
+ Call *call = (Call*)val;
2647
+ pjmedia_port *stream_port;
2648
+ pj_status_t status;
2206
2649
 
2207
2650
  if(!g_call_ids.get(call_id, val)){
2208
- PJW_UNLOCK();
2209
2651
  set_error("Invalid call_id");
2210
- return -1;
2652
+ goto out;
2211
2653
  }
2654
+ call = (Call*)val;
2212
2655
 
2213
- Call *call = (Call*)val;
2214
-
2215
- pjmedia_port *stream_port;
2216
- pj_status_t status;
2217
2656
  status = pjmedia_stream_get_port(call->med_stream,
2218
2657
  &stream_port);
2219
2658
  if(status != PJ_SUCCESS) {
2220
- PJW_UNLOCK();
2221
2659
  set_error("pjmedia_stream_get_port failed.");
2222
- return -1;
2660
+ goto out;
2223
2661
  }
2224
2662
 
2225
2663
  if(!prepare_wire(call->inv->pool, &call->wav_writer, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info))) {
2226
- PJW_UNLOCK();
2227
2664
  set_error("prepare_wire failed.");
2228
- return -1;
2665
+ goto out;
2229
2666
  }
2230
2667
 
2231
2668
  connect_media_ports(call);
2232
-
2669
+
2670
+ out:
2233
2671
  PJW_UNLOCK();
2672
+ if(pjw_errorstring[0]){
2673
+ return -1;
2674
+ }
2675
+
2234
2676
  return 0;
2235
2677
  }
2236
2678
 
2237
- int pjw_call_start_fax(long call_id, bool is_sender, const char *file)
2679
+ //int pjw_call_start_fax(long call_id, bool is_sender, const char *file)
2680
+ int pjw_call_start_fax(long call_id, const char *json)
2238
2681
  {
2239
2682
  PJW_LOCK();
2683
+ clear_error();
2240
2684
 
2241
2685
  long val;
2686
+ Call *call;
2687
+ pj_status_t status;
2688
+ pjmedia_port *stream_port;
2689
+
2690
+ bool is_sender;
2691
+ char *file;
2692
+
2693
+ char buffer[MAX_JSON_INPUT];
2694
+
2695
+ Document document;
2242
2696
 
2243
2697
  if(!g_call_ids.get(call_id, val)){
2244
- PJW_UNLOCK();
2245
2698
  set_error("Invalid call_id");
2246
- return -1;
2699
+ goto out;
2247
2700
  }
2248
-
2249
- Call *call = (Call*)val;
2701
+ call = (Call*)val;
2250
2702
 
2251
2703
  if(!call->med_stream)
2252
2704
  {
2253
- PJW_UNLOCK();
2254
2705
  set_error("Media not ready");
2255
- return -1;
2706
+ goto out;
2256
2707
  }
2257
2708
 
2258
- pj_status_t status;
2709
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
2710
+ goto out;
2711
+ }
2712
+
2713
+ if(!json_get_bool_param(document, "is_sender", false, &is_sender)) {
2714
+ goto out;
2715
+ }
2716
+
2717
+ if(!json_get_string_param(document, "file", false, &file)) {
2718
+ goto out;
2719
+ }
2720
+
2721
+ if(!file[0]) {
2722
+ set_error("file cannot be blank string");
2723
+ goto out;
2724
+ }
2259
2725
 
2260
- pjmedia_port *stream_port;
2261
2726
  status = pjmedia_stream_get_port(call->med_stream,
2262
2727
  &stream_port);
2263
2728
  if(status != PJ_SUCCESS)
2264
2729
  {
2265
- PJW_UNLOCK();
2266
- set_error("pjmedia_stream_get_port failed");
2267
- return -1;
2730
+ set_error("pjmedia_stream_get_port failed with status=%i", status);
2731
+ goto out;
2268
2732
  }
2269
2733
 
2270
2734
  if(!prepare_fax(call, is_sender, file)){
2271
- PJW_UNLOCK();
2272
- set_error("pjmedia_wav_player_port_create failed");
2273
- return -1;
2274
- }
2735
+ set_error("prepare_fax failed");
2736
+ goto out;
2737
+ }
2275
2738
 
2739
+ out:
2276
2740
  PJW_UNLOCK();
2741
+ if(pjw_errorstring[0]){
2742
+ return -1;
2743
+ }
2744
+
2277
2745
  return 0;
2278
2746
  }
2279
2747
 
@@ -2281,84 +2749,90 @@ int pjw_call_start_fax(long call_id, bool is_sender, const char *file)
2281
2749
  int pjw_call_stop_fax(long call_id)
2282
2750
  {
2283
2751
  PJW_LOCK();
2752
+ clear_error();
2284
2753
 
2285
2754
  long val;
2755
+ Call *call;
2756
+
2757
+ pjmedia_port *stream_port;
2758
+ pj_status_t status;
2286
2759
 
2287
2760
  if(!g_call_ids.get(call_id, val)){
2288
- PJW_UNLOCK();
2289
2761
  set_error("Invalid call_id");
2290
- return -1;
2762
+ goto out;
2291
2763
  }
2292
2764
 
2293
- Call *call = (Call*)val;
2765
+ call = (Call*)val;
2294
2766
 
2295
- pjmedia_port *stream_port;
2296
- pj_status_t status;
2297
2767
  status = pjmedia_stream_get_port(call->med_stream,
2298
2768
  &stream_port);
2299
2769
  if(status != PJ_SUCCESS) {
2300
- PJW_UNLOCK();
2301
2770
  set_error("pjmedia_stream_get_port failed.");
2302
- return -1;
2771
+ goto out;
2303
2772
  }
2304
2773
 
2305
2774
  if(!prepare_wire(call->inv->pool, &call->fax, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info))) {
2306
- PJW_UNLOCK();
2307
2775
  set_error("prepare_wire failed.");
2308
- return -1;
2776
+ goto out;
2309
2777
  }
2310
2778
 
2311
2779
  connect_media_ports(call);
2312
2780
 
2781
+ out:
2313
2782
  PJW_UNLOCK();
2783
+ if(pjw_errorstring[0]){
2784
+ return -1;
2785
+ }
2786
+
2314
2787
  return 0;
2315
2788
  }
2316
2789
 
2317
2790
 
2318
2791
  int pjw_call_get_stream_stat(long call_id, char *out_stats){
2319
2792
  PJW_LOCK();
2793
+ clear_error();
2320
2794
 
2321
2795
  long val;
2796
+ Call *call;
2797
+
2798
+ pj_status_t status;
2799
+ pjmedia_rtcp_stat stat;
2800
+ pjmedia_stream_info stream_info;
2801
+
2802
+ ostringstream oss;
2322
2803
 
2323
2804
  if(!g_call_ids.get(call_id, val)){
2324
- PJW_UNLOCK();
2325
2805
  set_error("Invalid call_id");
2326
- return -1;
2806
+ goto out;
2327
2807
  }
2328
-
2329
- Call *call = (Call*)val;
2808
+ call = (Call*)val;
2330
2809
 
2331
2810
  if(!call->med_stream){
2332
- PJW_UNLOCK();
2333
2811
  set_error("Could not get stream stats. No media session");
2334
- return -1;
2812
+ goto out;
2335
2813
  }
2336
2814
 
2337
- pj_status_t status;
2338
-
2339
- pjmedia_rtcp_stat stat;
2340
- pjmedia_stream_info stream_info;
2341
-
2342
2815
  status = pjmedia_stream_get_stat(call->med_stream, &stat);
2343
2816
  if(status != PJ_SUCCESS){
2344
- PJW_UNLOCK();
2345
- set_error("Could not get stream stats. Call to pjmedia_stream_get_stream_stat failed.");
2346
- return -1;
2817
+ set_error("Could not get stream stats. Call to pjmedia_stream_get_stream_stat failed with status=%i", status);
2818
+ goto out;
2347
2819
  }
2348
2820
 
2349
2821
  status = pjmedia_stream_get_info(call->med_stream, &stream_info);
2350
2822
  if(status != PJ_SUCCESS){
2351
- PJW_UNLOCK();
2352
- set_error("Could not get stream info. Call to pjmedia_stream_get_info failed.");
2353
- return -1;
2823
+ set_error("Could not get stream info. Call to pjmedia_stream_get_info failed with status=%i", status);
2824
+ goto out;
2354
2825
  }
2355
2826
 
2356
- ostringstream oss;
2357
2827
  build_stream_stat(oss, &stat, &stream_info);
2828
+ strcpy(out_stats, oss.str().c_str());
2358
2829
 
2830
+ out:
2359
2831
  PJW_UNLOCK();
2832
+ if(pjw_errorstring[0]){
2833
+ return -1;
2834
+ }
2360
2835
 
2361
- strcpy(out_stats, oss.str().c_str());
2362
2836
  return 0;
2363
2837
  }
2364
2838
 
@@ -2649,7 +3123,7 @@ static void on_state_changed( pjsip_inv_session *inv,
2649
3123
 
2650
3124
  char evt[2048];
2651
3125
  int sip_msg_len = 0;
2652
- char *sip_msg = "";
3126
+ char *sip_msg = (char*)"";
2653
3127
  if(e->type == PJSIP_EVENT_TSX_STATE) {
2654
3128
  sip_msg_len = e->body.rx_msg.rdata->msg_info.len;
2655
3129
  sip_msg = e->body.rx_msg.rdata->msg_info.msg_buf;
@@ -2766,7 +3240,7 @@ static void process_subscribe_request(pjsip_rx_data *rdata) {
2766
3240
 
2767
3241
  out:
2768
3242
  if(status != PJ_SUCCESS) {
2769
- pj_str_t s_reason = pj_str(pjw_errorstring);
3243
+ //pj_str_t s_reason = pj_str(pjw_errorstring);
2770
3244
  if(dlg) {
2771
3245
  status = pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
2772
3246
  if(status == PJ_SUCCESS) {
@@ -2843,7 +3317,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2843
3317
  build_basic_request_info(&oss, rdata, &transport);
2844
3318
  */
2845
3319
 
2846
- reason = pj_str("OK");
3320
+ reason = pj_str((char*)"OK");
2847
3321
 
2848
3322
  pjsip_hdr hdr_list;
2849
3323
  pj_list_init(&hdr_list);
@@ -2852,7 +3326,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2852
3326
  pjsip_hdr *hdr_from_request;
2853
3327
 
2854
3328
  //Add Contact header from Request, if present
2855
- pj_str_t STR_CONTACT = { "Contact" , 7 };
3329
+ pj_str_t STR_CONTACT = {(char*)"Contact" , 7 };
2856
3330
  hdr_from_request = (pjsip_hdr*)pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2857
3331
  &STR_CONTACT,
2858
3332
  NULL);
@@ -2862,7 +3336,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2862
3336
  }
2863
3337
 
2864
3338
  //Add Expires header from Request, if present
2865
- pj_str_t STR_EXPIRES = { "Expires" , 7 };
3339
+ pj_str_t STR_EXPIRES = {(char*)"Expires" , 7 };
2866
3340
  hdr_from_request = (pjsip_hdr*)pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2867
3341
  &STR_EXPIRES,
2868
3342
  NULL);
@@ -2883,13 +3357,13 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2883
3357
  unsigned options = 0;
2884
3358
  status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, g_sip_endpt, NULL);
2885
3359
  if(status != PJ_SUCCESS) {
2886
- reason = pj_str("Unable to handle this INVITE");
3360
+ reason = pj_str((char*)"Unable to handle this INVITE");
2887
3361
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2888
3362
  return PJ_TRUE;
2889
3363
  }
2890
3364
 
2891
3365
  char local_contact[1000];
2892
- build_local_contact(local_contact, rdata->tp_info.transport, "sip-tester");
3366
+ build_local_contact(local_contact, rdata->tp_info.transport, "sip-lab");
2893
3367
  pj_str_t url = pj_str(local_contact);
2894
3368
 
2895
3369
  status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(),
@@ -2898,7 +3372,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2898
3372
  &dlg);
2899
3373
 
2900
3374
  if(status != PJ_SUCCESS) {
2901
- reason = pj_str("Internal Server Error (pjsip_dlg_create_uas_and_inc_lock failed)");
3375
+ reason = pj_str((char*)"Internal Server Error (pjsip_dlg_create_uas_and_inc_lock failed)");
2902
3376
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2903
3377
  return PJ_TRUE;
2904
3378
  }
@@ -2909,7 +3383,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2909
3383
 
2910
3384
  if(!med_transport)
2911
3385
  {
2912
- reason = pj_str("Internal Server Error (could not create media transport)");
3386
+ reason = pj_str((char*)"Internal Server Error (could not create media transport)");
2913
3387
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2914
3388
  return PJ_TRUE;
2915
3389
  }
@@ -2924,7 +3398,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2924
3398
  &sdp);
2925
3399
  if(status != PJ_SUCCESS) {
2926
3400
  close_media_transport(med_transport);
2927
- reason = pj_str("Internal Server Error (pjmedia_endprt_create_sdp failed)");
3401
+ reason = pj_str((char*)"Internal Server Error (pjmedia_endprt_create_sdp failed)");
2928
3402
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2929
3403
  return PJ_TRUE;
2930
3404
  }
@@ -2933,14 +3407,14 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2933
3407
  status = pjsip_inv_create_uas(dlg, rdata, sdp, 0, &inv);
2934
3408
  if(status != PJ_SUCCESS) {
2935
3409
  close_media_transport(med_transport);
2936
- reason = pj_str("Internal Server Error (pjsip_inv_create_uas failed)");
3410
+ reason = pj_str((char*)"Internal Server Error (pjsip_inv_create_uas failed)");
2937
3411
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2938
3412
  return PJ_TRUE;
2939
3413
  }
2940
3414
 
2941
3415
  if(!dlg_set_transport(t, dlg)) {
2942
3416
  close_media_transport(med_transport);
2943
- reason = pj_str("Internal Server Error (set_transport failed)");
3417
+ reason = pj_str((char*)"Internal Server Error (set_transport failed)");
2944
3418
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2945
3419
  return PJ_TRUE;
2946
3420
  }
@@ -2956,7 +3430,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2956
3430
  NULL, NULL, &tdata);
2957
3431
  if(status != PJ_SUCCESS) {
2958
3432
  close_media_transport(med_transport);
2959
- reason = pj_str("Internal Server Error (pjsip_inv_initial_answer failed)");
3433
+ reason = pj_str((char*)"Internal Server Error (pjsip_inv_initial_answer failed)");
2960
3434
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2961
3435
  return PJ_TRUE;
2962
3436
  }
@@ -2965,7 +3439,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2965
3439
  status = pjsip_inv_send_msg(inv, tdata);
2966
3440
  if(status != PJ_SUCCESS) {
2967
3441
  close_media_transport(med_transport);
2968
- reason = pj_str("Internal Server Error (pjsip_inv_send_msg failed)");
3442
+ reason = pj_str((char*)"Internal Server Error (pjsip_inv_send_msg failed)");
2969
3443
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2970
3444
  return PJ_TRUE;
2971
3445
  }
@@ -2974,7 +3448,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2974
3448
 
2975
3449
  if(status != PJ_SUCCESS) {
2976
3450
  close_media_transport(med_transport);
2977
- reason = pj_str("Internal Server Error (pjsip_rx_data_clone failed)");
3451
+ reason = pj_str((char*)"Internal Server Error (pjsip_rx_data_clone failed)");
2978
3452
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2979
3453
  return PJ_TRUE;
2980
3454
  }
@@ -2987,7 +3461,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
2987
3461
 
2988
3462
  if(status != PJ_SUCCESS) {
2989
3463
  close_media_transport(med_transport);
2990
- reason = pj_str("Internal Server Error (pjsip_rx_data_clone failed)");
3464
+ reason = pj_str((char*)"Internal Server Error (pjsip_rx_data_clone failed)");
2991
3465
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
2992
3466
  return PJ_TRUE;
2993
3467
  }
@@ -3005,7 +3479,7 @@ static pj_bool_t on_rx_request( pjsip_rx_data *rdata ){
3005
3479
  status = pjsip_dlg_add_usage(dlg, &mod_tester, call);
3006
3480
  if(status != PJ_SUCCESS) {
3007
3481
  close_media_transport(med_transport);
3008
- reason = pj_str("Internal Server Error (pjsip_dlg_add_usage failed)");
3482
+ reason = pj_str((char*)"Internal Server Error (pjsip_dlg_add_usage failed)");
3009
3483
  pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
3010
3484
  return PJ_TRUE;
3011
3485
  }
@@ -3147,15 +3621,17 @@ static void on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer
3147
3621
  addon_log(LOG_LEVEL_DEBUG, "on_rx_offer offer=%x\n", offer);
3148
3622
  if(g_shutting_down) return;
3149
3623
 
3624
+ /*
3150
3625
  bool is_reinvite = false;
3151
3626
 
3152
3627
  if(inv->state == PJSIP_INV_STATE_CONFIRMED) {
3153
3628
  is_reinvite = true;
3154
3629
  }
3630
+ */
3155
3631
 
3156
3632
  char evt[2048];
3157
3633
 
3158
- char *type;
3634
+ //char *type;
3159
3635
 
3160
3636
  Call *call = (Call*)inv->dlg->mod_data[mod_tester.id];
3161
3637
 
@@ -3194,7 +3670,7 @@ static void on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer
3194
3670
  call->remote_hold = 0;
3195
3671
  }
3196
3672
 
3197
- char *mode = get_media_mode_str(remote_mode);
3673
+ //char *mode = get_media_mode_str(remote_mode);
3198
3674
 
3199
3675
  pjmedia_sdp_attr *attr;
3200
3676
 
@@ -3208,17 +3684,13 @@ static void on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer
3208
3684
  // Keep call on-hold by setting 'sendonly' attribute.
3209
3685
  // (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
3210
3686
  if(call->remote_hold) {
3211
- printf("p1\n");
3212
3687
  attr = pjmedia_sdp_attr_create(inv->pool, "inactive", NULL);
3213
3688
  } else {
3214
- printf("p2\n");
3215
3689
  attr = pjmedia_sdp_attr_create(inv->pool, "sendonly", NULL);
3216
3690
  }
3217
3691
  } else if(call->remote_hold) {
3218
- printf("p3\n");
3219
3692
  attr = pjmedia_sdp_attr_create(inv->pool, "recvonly", NULL);
3220
3693
  } else {
3221
- printf("p4\n");
3222
3694
  attr = pjmedia_sdp_attr_create(inv->pool, "sendrecv", NULL);
3223
3695
  }
3224
3696
  pjmedia_sdp_media_add_attr(answer->media[0], attr);
@@ -3362,7 +3834,7 @@ int pjw_get_codecs(char *out_codecs)
3362
3834
  goto out;
3363
3835
  }
3364
3836
 
3365
- for(int i=0; i<count; ++i) {
3837
+ for(unsigned i=0; i<count; ++i) {
3366
3838
  pjmedia_codec_info *info = &codec_info[i];
3367
3839
  if(i != 0) oss << " ";
3368
3840
  oss.write(info->encoding_name.ptr, info->encoding_name.slen);
@@ -3385,7 +3857,7 @@ out:
3385
3857
  int pjw_set_codecs(const char *in_codec_info) {
3386
3858
  clear_error();
3387
3859
 
3388
- char error[1000];
3860
+ //char error[1000];
3389
3861
  pjmedia_codec_mgr *codec_mgr;
3390
3862
  pj_status_t status;
3391
3863
  char codec_info[1000];
@@ -3400,7 +3872,7 @@ int pjw_set_codecs(const char *in_codec_info) {
3400
3872
  goto out;
3401
3873
  }
3402
3874
 
3403
- codec_id = pj_str("");
3875
+ codec_id = pj_str((char*)"");
3404
3876
  status = pjmedia_codec_mgr_set_codec_priority(codec_mgr, &codec_id, 0);
3405
3877
  if(status != PJ_SUCCESS) {
3406
3878
  set_error("pjmedia_codec_mgr_set_codec_priority(zero all) failed.");
@@ -3435,7 +3907,7 @@ out:
3435
3907
 
3436
3908
  if(pjw_errorstring[0]){
3437
3909
  //Try to put default priority to all codecs
3438
- codec_id = pj_str("");
3910
+ codec_id = pj_str((char*)"");
3439
3911
  status = pjmedia_codec_mgr_set_codec_priority(codec_mgr, &codec_id, 128);
3440
3912
  return -1;
3441
3913
  }
@@ -3576,7 +4048,13 @@ static void build_stream_stat(ostringstream &oss, pjmedia_rtcp_stat *stat, pjmed
3576
4048
  {
3577
4049
  char temp[200];
3578
4050
  char duration[80], last_update[80];
3579
- char bps[16], ipbps[16], packets[16], bytes[16], ipbytes[16];
4051
+
4052
+ //char bps[16];
4053
+ //char ipbps[16];
4054
+ char packets[16];
4055
+ //char bytes[16];
4056
+ //char ipbytes[16];
4057
+
3580
4058
  pj_time_val now;
3581
4059
 
3582
4060
  pj_gettimeofday(&now);
@@ -3593,7 +4071,7 @@ static void build_stream_stat(ostringstream &oss, pjmedia_rtcp_stat *stat, pjmed
3593
4071
  oss << duration;
3594
4072
 
3595
4073
  sprintf(temp, ", \"CodecInfo\": \"%.*s/%d/%d\"",
3596
- stream_info->fmt.encoding_name.slen,
4074
+ (int)stream_info->fmt.encoding_name.slen,
3597
4075
  stream_info->fmt.encoding_name.ptr,
3598
4076
  stream_info->fmt.clock_rate,
3599
4077
  stream_info->fmt.channel_cnt);
@@ -3922,7 +4400,7 @@ void on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code, pj_str
3922
4400
 
3923
4401
  static void on_client_refresh( pjsip_evsub *sub ) {
3924
4402
  Subscription *subscription;
3925
- pj_status_t status;
4403
+ //pj_status_t status;
3926
4404
 
3927
4405
  subscription = (Subscription*) pjsip_evsub_get_mod_data(sub, mod_tester.id);
3928
4406
 
@@ -3931,7 +4409,7 @@ static void on_client_refresh( pjsip_evsub *sub ) {
3931
4409
  goto out;
3932
4410
  }
3933
4411
 
3934
- if(!subscription_subscribe(subscription, -1, "")) {
4412
+ if(!subscription_subscribe_no_headers(subscription, -1)) {
3935
4413
  goto out;
3936
4414
  }
3937
4415
 
@@ -3962,7 +4440,7 @@ static void client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) {
3962
4440
  }
3963
4441
 
3964
4442
  pjsip_generic_string_hdr *refer_sub;
3965
- const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
4443
+ const pj_str_t REFER_SUB = { (char*)"Refer-Sub", 9 };
3966
4444
  ostringstream oss;
3967
4445
 
3968
4446
  // When subscription is accepted (got 200/OK)
@@ -4004,7 +4482,7 @@ static void client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) {
4004
4482
 
4005
4483
  rdata = event->body.tsx_state.src.rdata;
4006
4484
 
4007
- Transport *t;
4485
+ //Transport *t;
4008
4486
  //build_basic_request_info(&oss, rdata, &t);
4009
4487
 
4010
4488
  long subscription_id;
@@ -4041,8 +4519,8 @@ static void client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) {
4041
4519
  static void server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
4042
4520
  {
4043
4521
  Subscriber *s;
4044
- pj_status_t status;
4045
- pjsip_tx_data *tdata;
4522
+ //pj_status_t status;
4523
+ //pjsip_tx_data *tdata;
4046
4524
 
4047
4525
  //addon_log(LOG_LEVEL_DEBUG, "server_on_evsub_state\n");
4048
4526
  if(!sub) {
@@ -4084,7 +4562,7 @@ static void server_on_evsub_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, i
4084
4562
 
4085
4563
  ostringstream oss;
4086
4564
  Subscriber *s;
4087
- Transport *t;
4565
+ //Transport *t;
4088
4566
 
4089
4567
  if(g_shutting_down) return;
4090
4568
  addon_log(LOG_LEVEL_DEBUG, "server_on_evsub_rx_refresh\n");
@@ -4099,7 +4577,7 @@ static void server_on_evsub_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, i
4099
4577
  dispatch_event(evt);
4100
4578
 
4101
4579
  if( pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
4102
- pj_str_t reason = { "noresource", 10 };
4580
+ pj_str_t reason = { (char*)"noresource", 10 };
4103
4581
  status = pjsip_evsub_notify(sub,
4104
4582
  PJSIP_EVSUB_STATE_TERMINATED,
4105
4583
  NULL,
@@ -4140,17 +4618,17 @@ void process_in_dialog_refer(pjsip_dialog *dlg, pjsip_rx_data *rdata)
4140
4618
  char evt[2048];
4141
4619
 
4142
4620
  pj_status_t status;
4143
- pjsip_tx_data *tdata;
4144
- int new_call;
4145
- const pj_str_t str_refer_to = { "Refer-To", 8};
4146
- const pj_str_t str_refer_sub = { "Refer-Sub", 9 };
4147
- const pj_str_t str_ref_by = { "Referred-By", 11 };
4621
+ //pjsip_tx_data *tdata;
4622
+ //int new_call;
4623
+ const pj_str_t str_refer_to = { (char*)"Refer-To", 8};
4624
+ const pj_str_t str_refer_sub = { (char*)"Refer-Sub", 9 };
4625
+ //const pj_str_t str_ref_by = { (char*)"Referred-By", 11 };
4148
4626
  pjsip_generic_string_hdr *refer_to;
4149
4627
  pjsip_generic_string_hdr *refer_sub;
4150
- pjsip_hdr *ref_by_hdr;
4628
+ //pjsip_hdr *ref_by_hdr;
4151
4629
  pj_bool_t no_refer_sub = PJ_FALSE;
4152
- char *uri;
4153
- pj_str_t tmp;
4630
+ //char *uri;
4631
+ //pj_str_t tmp;
4154
4632
  pjsip_status_code code;
4155
4633
  pjsip_evsub *sub;
4156
4634
 
@@ -4177,13 +4655,14 @@ void process_in_dialog_refer(pjsip_dialog *dlg, pjsip_rx_data *rdata)
4177
4655
  /* Find optional Referred-By header (to be copied onto outgoing INVITE
4178
4656
  * request.
4179
4657
  */
4658
+ /*
4180
4659
  ref_by_hdr = (pjsip_hdr*)
4181
4660
  pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_ref_by,
4182
4661
  NULL);
4183
-
4184
- if(ref_by_hdr) {
4662
+ */
4663
+ /* if(ref_by_hdr) {
4185
4664
  pjsip_generic_string_hdr *referred_by = (pjsip_generic_string_hdr*)ref_by_hdr;
4186
- }
4665
+ } */
4187
4666
 
4188
4667
  /* Find optional Refer-Sub header */
4189
4668
  refer_sub = (pjsip_generic_string_hdr*)
@@ -4206,7 +4685,7 @@ void process_in_dialog_refer(pjsip_dialog *dlg, pjsip_rx_data *rdata)
4206
4685
  * Always answer with 2xx.
4207
4686
  */
4208
4687
  pjsip_tx_data *tdata;
4209
- const pj_str_t str_false = { "false", 5};
4688
+ const pj_str_t str_false = { (char*)"false", 5};
4210
4689
  pjsip_hdr *hdr;
4211
4690
 
4212
4691
  status = pjsip_dlg_create_response(dlg, rdata, code, NULL,
@@ -4260,7 +4739,7 @@ void process_in_dialog_refer(pjsip_dialog *dlg, pjsip_rx_data *rdata)
4260
4739
  * Refer-Sub in the response with value "true" too.
4261
4740
  */
4262
4741
  if (refer_sub) {
4263
- const pj_str_t str_true = { "true", 4 };
4742
+ const pj_str_t str_true = { (char*)"true", 4 };
4264
4743
  pjsip_hdr *hdr;
4265
4744
 
4266
4745
  hdr = (pjsip_hdr*)
@@ -4324,7 +4803,7 @@ static void on_tsx_state_changed(pjsip_inv_session *inv,
4324
4803
  }
4325
4804
 
4326
4805
  //ostringstream oss;
4327
- Transport *t;
4806
+ //Transport *t;
4328
4807
  if (tsx->role==PJSIP_ROLE_UAS &&
4329
4808
  tsx->state==PJSIP_TSX_STATE_TRYING) {
4330
4809
  if(pjsip_method_cmp(&tsx->method, pjsip_get_refer_method())==0) {
@@ -4342,15 +4821,16 @@ static void on_tsx_state_changed(pjsip_inv_session *inv,
4342
4821
  }
4343
4822
  }
4344
4823
 
4345
- int pjw_call_refer(long call_id, const char *dest_uri, const char *additional_headers, long *out_subscription_id)
4824
+ //int pjw_call_refer(long call_id, const char *dest_uri, const char *additional_headers, long *out_subscription_id)
4825
+ int pjw_call_refer(long call_id, const char *json, long *out_subscription_id)
4346
4826
  {
4347
4827
  PJW_LOCK();
4348
4828
  clear_error();
4349
4829
 
4350
- int n;
4830
+ char *dest_uri;
4831
+
4351
4832
  long val;
4352
4833
  Call *call;
4353
- Subscription *s;
4354
4834
  pj_str_t s_dest_uri;
4355
4835
 
4356
4836
  long subscription_id;
@@ -4359,17 +4839,23 @@ int pjw_call_refer(long call_id, const char *dest_uri, const char *additional_he
4359
4839
  pjsip_tx_data *tdata;
4360
4840
  pj_status_t status;
4361
4841
 
4842
+ char buffer[MAX_JSON_INPUT];
4843
+
4844
+ Document document;
4845
+
4362
4846
  if(!g_call_ids.get(call_id, val)){
4363
4847
  set_error("Invalid call_id");
4364
4848
  goto out;
4365
4849
  }
4366
-
4367
4850
  call = (Call*)val;
4368
4851
 
4369
- if(!check_uri(dest_uri)) {
4370
- set_error("Invalid dest_uri");
4371
- goto out;
4372
- }
4852
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
4853
+ goto out;
4854
+ }
4855
+
4856
+ if(!json_get_and_check_uri(document, "dest_uri", false, &dest_uri)) {
4857
+ goto out;
4858
+ }
4373
4859
 
4374
4860
  pj_bzero(&xfer_cb, sizeof(xfer_cb));
4375
4861
  xfer_cb.on_evsub_state = &client_on_evsub_state;
@@ -4377,30 +4863,30 @@ int pjw_call_refer(long call_id, const char *dest_uri, const char *additional_he
4377
4863
 
4378
4864
  status = pjsip_xfer_create_uac(call->inv->dlg, &xfer_cb, &sub);
4379
4865
  if(status != PJ_SUCCESS) {
4380
- set_error("pjsip_xfer_create_uac failed");
4866
+ set_error("pjsip_xfer_create_uac failed with status=%i", status);
4381
4867
  goto out;
4382
4868
  }
4383
4869
 
4384
4870
  s_dest_uri = pj_str((char*)dest_uri);
4385
4871
  status = pjsip_xfer_initiate(sub, &s_dest_uri, &tdata);
4386
4872
 
4387
- if(!add_additional_headers(call->inv->dlg->pool, tdata, additional_headers)) {
4873
+ if(!add_headers(call->inv->dlg->pool, tdata, document)) {
4388
4874
  goto out;
4389
4875
  }
4390
4876
 
4391
4877
  status = pjsip_xfer_send_request(sub, tdata);
4392
4878
  if(status != PJ_SUCCESS) {
4393
- set_error("pjsip_xfer_send_request failed");
4879
+ set_error("pjsip_xfer_send_request failed with status=%i", status);
4394
4880
  goto out;
4395
4881
  }
4396
4882
 
4883
+ *out_subscription_id = subscription_id;
4884
+
4397
4885
  out:
4398
4886
  PJW_UNLOCK();
4399
-
4400
4887
  if(pjw_errorstring[0]) {
4401
4888
  return -1;
4402
4889
  }
4403
- *out_subscription_id = subscription_id;
4404
4890
  return 0;
4405
4891
  }
4406
4892
 
@@ -4437,7 +4923,7 @@ int pjw_call_get_info(long call_id, const char *required_info, char *out_info)
4437
4923
  }
4438
4924
  pj_str_t str_addr = pj_str( inet_ntoa( (in_addr&)session_info.rem_addr.ipv4.sin_addr.s_addr ) );
4439
4925
  pj_uint16_t port = session_info.rem_addr.ipv4.sin_port;
4440
- sprintf(info, "%.*s:%u", str_addr.slen, str_addr.ptr, ntohs(port));
4926
+ sprintf(info, "%.*s:%u", (int)str_addr.slen, str_addr.ptr, ntohs(port));
4441
4927
  } else {
4442
4928
  PJW_UNLOCK();
4443
4929
  set_error("Unsupported info");
@@ -4449,9 +4935,9 @@ int pjw_call_get_info(long call_id, const char *required_info, char *out_info)
4449
4935
  return 0;
4450
4936
  }
4451
4937
 
4452
- bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int subscription_state, const char *reason, const char *additional_headers) {
4453
- pj_str_t s_content_type;
4454
- pj_str_t s_body;
4938
+ bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int subscription_state, const char *reason, Document &document) {
4939
+ //pj_str_t s_content_type;
4940
+ //pj_str_t s_body;
4455
4941
  pj_str_t s_reason;
4456
4942
 
4457
4943
  char *temp;
@@ -4464,9 +4950,9 @@ bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int
4464
4950
  char *content_type_buffer;
4465
4951
  pj_str_t s_content_type_type;
4466
4952
  pj_str_t s_content_type_subtype;
4467
- pj_str_t s_content_type_param;
4953
+ //pj_str_t s_content_type_param;
4468
4954
 
4469
- char *blank_string;
4955
+ //char *blank_string;
4470
4956
 
4471
4957
  pjsip_tx_data *tdata;
4472
4958
  pj_status_t status;
@@ -4503,7 +4989,9 @@ bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int
4503
4989
  }
4504
4990
  s_content_type_subtype = pj_str(tok);
4505
4991
 
4506
- add_additional_headers(tdata->pool, tdata, additional_headers);
4992
+ if(!add_headers(tdata->pool, tdata, document)) {
4993
+ return false;
4994
+ }
4507
4995
 
4508
4996
  msg_body->content_type.type = s_content_type_type;
4509
4997
  msg_body->content_type.subtype = s_content_type_subtype;
@@ -4524,22 +5012,29 @@ bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int
4524
5012
  return true;
4525
5013
  }
4526
5014
 
4527
- int pjw_notify(long subscriber_id, const char *content_type, const char *body, int subscription_state, const char *reason, const char *additional_headers)
5015
+ //int pjw_notify(long subscriber_id, const char *content_type, const char *body, int subscription_state, const char *reason, const char *additional_headers)
5016
+ int pjw_notify(long subscriber_id, const char *json)
4528
5017
  {
4529
5018
  PJW_LOCK();
4530
-
4531
5019
  clear_error();
4532
5020
 
4533
- int n;
5021
+ char *content_type = NULL;
5022
+ char *body = NULL;
5023
+ int subscription_state;
5024
+ char *reason = NULL;
5025
+
4534
5026
  long val;
4535
5027
 
4536
5028
  Subscriber *subscriber;
4537
5029
 
5030
+ char buffer[MAX_JSON_INPUT];
5031
+
5032
+ Document document;
5033
+
4538
5034
  if(!g_subscriber_ids.get(subscriber_id, val)){
4539
5035
  set_error("Invalid subscriber_id");
4540
5036
  goto out;
4541
5037
  }
4542
-
4543
5038
  subscriber = (Subscriber*)val;
4544
5039
 
4545
5040
  if(subscriber->created_by_refer) {
@@ -4547,40 +5042,63 @@ int pjw_notify(long subscriber_id, const char *content_type, const char *body, i
4547
5042
  goto out;
4548
5043
  }
4549
5044
 
4550
- if(!notify(subscriber->evsub, content_type, body, subscription_state, reason, additional_headers)){
5045
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
5046
+ goto out;
5047
+ }
5048
+
5049
+ if(!json_get_string_param(document, "content_type", false, &content_type)) {
5050
+ goto out;
5051
+ }
5052
+
5053
+ if(!json_get_string_param(document, "body", false, &body)) {
5054
+ goto out;
5055
+ }
5056
+
5057
+ if(!json_get_int_param(document, "subscription_state", false, &subscription_state)) {
5058
+ goto out;
5059
+ }
5060
+
5061
+ if(!json_get_string_param(document, "reason", true, &reason)) {
5062
+ goto out;
5063
+ }
5064
+
5065
+ if(!notify(subscriber->evsub, content_type, body, subscription_state, reason, document)){
4551
5066
  goto out;
4552
5067
  }
4553
5068
 
4554
5069
  out:
4555
5070
  PJW_UNLOCK();
4556
-
4557
5071
  if(pjw_errorstring[0]) {
4558
5072
  return -1;
4559
5073
  }
4560
-
4561
5074
  return 0;
4562
5075
  }
4563
5076
 
4564
5077
 
4565
- int pjw_notify_xfer(long subscriber_id, int subscription_state, int xfer_status_code, const char *xfer_status_text) {
5078
+ //int pjw_notify_xfer(long subscriber_id, int subscription_state, int xfer_status_code, const char *xfer_status_text) {
5079
+ int pjw_notify_xfer(long subscriber_id, const char *json) {
4566
5080
  PJW_LOCK();
4567
-
4568
5081
  clear_error();
4569
5082
 
4570
- int n;
4571
5083
  pjsip_tx_data *tdata;
4572
5084
  pj_status_t status;
4573
5085
 
5086
+ int subscription_state;
5087
+ int code;
5088
+ char *reason;
5089
+
4574
5090
  long val;
4575
5091
 
4576
5092
  Subscriber *subscriber;
4577
- pj_str_t s_xfer_status_text;
5093
+ pj_str_t r;
5094
+
5095
+ char buffer[MAX_JSON_INPUT];
4578
5096
 
5097
+ Document document;
4579
5098
  if(!g_subscriber_ids.get(subscriber_id, val)){
4580
5099
  set_error("Invalid subscriber_id");
4581
5100
  goto out;
4582
5101
  }
4583
-
4584
5102
  subscriber = (Subscriber*)val;
4585
5103
 
4586
5104
  if(!subscriber->created_by_refer) {
@@ -4588,23 +5106,39 @@ int pjw_notify_xfer(long subscriber_id, int subscription_state, int xfer_status_
4588
5106
  goto out;
4589
5107
  }
4590
5108
 
4591
- s_xfer_status_text = pj_str((char*)xfer_status_text);
5109
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
5110
+ goto out;
5111
+ }
4592
5112
 
4593
- status = pjsip_xfer_notify( subscriber->evsub,
4594
- (pjsip_evsub_state)subscription_state,
4595
- xfer_status_code,
4596
- &s_xfer_status_text,
4597
- &tdata);
4598
- if (status != PJ_SUCCESS) {
4599
- set_error( "Unable to create NOTIFY for 'Event: refer'");
4600
- goto out;
4601
- }
5113
+ if(!json_get_int_param(document, "subscription_state", false, &subscription_state)) {
5114
+ goto out;
5115
+ }
4602
5116
 
4603
- status = pjsip_xfer_send_request( subscriber->evsub, tdata);
4604
- if (status != PJ_SUCCESS) {
4605
- set_error("Unable to send NOTIFY for 'Event: refer'");
4606
- goto out;
4607
- }
5117
+ if(!json_get_int_param(document, "code", false, &code)) {
5118
+ goto out;
5119
+ }
5120
+
5121
+ if(!json_get_string_param(document, "reason", false, &reason)) {
5122
+ goto out;
5123
+ }
5124
+
5125
+ r = pj_str((char*)reason);
5126
+
5127
+ status = pjsip_xfer_notify( subscriber->evsub,
5128
+ (pjsip_evsub_state)subscription_state,
5129
+ code,
5130
+ &r,
5131
+ &tdata);
5132
+ if (status != PJ_SUCCESS) {
5133
+ set_error( "pjsip_xfer_notify failed with status=%i", status);
5134
+ goto out;
5135
+ }
5136
+
5137
+ status = pjsip_xfer_send_request( subscriber->evsub, tdata);
5138
+ if (status != PJ_SUCCESS) {
5139
+ set_error("pjsip_xfer_send_request failed with status=%i", status);
5140
+ goto out;
5141
+ }
4608
5142
 
4609
5143
  out:
4610
5144
  PJW_UNLOCK();
@@ -4616,6 +5150,7 @@ out:
4616
5150
  return 0;
4617
5151
  }
4618
5152
 
5153
+ /*
4619
5154
  pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers) {
4620
5155
 
4621
5156
  if(additional_headers && additional_headers[0]){
@@ -4652,94 +5187,133 @@ pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const ch
4652
5187
  }
4653
5188
  return PJ_TRUE;
4654
5189
  }
5190
+ */
4655
5191
 
4656
- pj_bool_t add_additional_headers_for_account(pjsip_regc *regc, const char *additional_headers) {
4657
5192
 
4658
- if(additional_headers && additional_headers[0]){
4659
- pjsip_hdr hdr_list;
4660
- pj_list_init(&hdr_list);
5193
+ pj_bool_t add_headers(pj_pool_t *pool, pjsip_tx_data *tdata, Document &document) {
5194
+ if(!document.HasMember("headers")) {
5195
+ return PJ_TRUE;
5196
+ }
4661
5197
 
4662
- char pool_buf[4096];
4663
- pj_pool_t *pool;
4664
- pool = pj_pool_create_on_buf(NULL, pool_buf, sizeof(pool_buf));
5198
+ if(!document["headers"].IsObject()) {
5199
+ set_error("Parameter headers must be an object");
5200
+ return PJ_FALSE;
5201
+ }
4665
5202
 
4666
- char buf[2048];
4667
- strcpy(buf,additional_headers);
4668
- char *saved;
4669
- char *token = strtok_r(buf, "\n", &saved);
4670
- while(token){
4671
- char *name = strtok(token, ":");
4672
- char *value = strtok(NULL, "\n");
4673
- //addon_log(LOG_LEVEL_DEBUG, "Adding %s:%s\n", name, value);
5203
+ Value headers = document["headers"].GetObject();
4674
5204
 
4675
- if(!name || !value) {
4676
- set_error("Invalid additional_header");
4677
- return PJ_FALSE;
4678
- }
5205
+ for (Value::ConstMemberIterator itr = headers.MemberBegin(); itr != headers.MemberEnd(); ++itr) {
5206
+ printf("%s => '%s'\n", itr->name.GetString(), itr->value.GetString());
4679
5207
 
4680
- pj_str_t hname = pj_str(name);
4681
- pjsip_hdr *hdr = (pjsip_hdr*)pjsip_parse_hdr(pool,
4682
- &hname,
4683
- value,
4684
- strlen(value),
4685
- NULL);
5208
+ const char *name = itr->name.GetString();
5209
+ if(!itr->value.IsString()) {
5210
+ set_error("Parameter headers key '%s' found with non-string value", name);
5211
+ return PJ_FALSE;
5212
+ }
4686
5213
 
4687
- if(!hdr) {
4688
- set_error("Failed to parse additional header to INVITE");
4689
- return PJ_FALSE;
4690
- }
4691
-
4692
- pj_list_push_back(&hdr_list, hdr);
4693
- token = strtok_r(NULL, "\n", &saved);
4694
- }
4695
- pjsip_regc_add_headers(regc, &hdr_list);
4696
- }
5214
+ const char *value = itr->value.GetString();
5215
+
5216
+ pj_str_t hname = pj_str((char*)name);
5217
+ pjsip_hdr *hdr = (pjsip_hdr*)pjsip_parse_hdr(pool,
5218
+ &hname,
5219
+ (char*)value,
5220
+ strlen(value),
5221
+ NULL);
5222
+
5223
+ if(!hdr) {
5224
+ set_error("Failed to parse header '%s' => '%s'", name, value);
5225
+ return PJ_FALSE;
5226
+ }
5227
+ pjsip_hdr *clone_hdr = (pjsip_hdr*) pjsip_hdr_clone(pool, hdr);
5228
+ pjsip_msg_add_hdr(tdata->msg, clone_hdr);
5229
+ }
4697
5230
  return PJ_TRUE;
4698
5231
  }
4699
5232
 
4700
- pj_bool_t get_content_type_and_subtype_from_additional_headers(const char *additional_headers, char *type, char *subtype) {
5233
+ pj_bool_t add_headers_for_account(pjsip_regc *regc, Document &document) {
5234
+ pjsip_hdr hdr_list;
5235
+ pj_list_init(&hdr_list);
4701
5236
 
4702
- if(!additional_headers || !additional_headers[0]){
4703
- set_error("Header Content-Type not supplied");
4704
- return PJ_FALSE;
4705
- }
5237
+ char pool_buf[4096];
5238
+ pj_pool_t *pool;
5239
+ pool = pj_pool_create_on_buf(NULL, pool_buf, sizeof(pool_buf));
4706
5240
 
4707
- char buf[1000];
4708
- strcpy(buf,additional_headers);
4709
- char *saved;
4710
- char *token = strtok_r(buf, "\n", &saved);
4711
- while(token){
4712
- char *name = strtok(token, ":");
4713
- char *value = strtok(NULL, " ");
4714
- addon_log(LOG_LEVEL_DEBUG, "Checking %s: %s\n", name, value);
4715
-
4716
- if(!name || !value) {
4717
- set_error("Invalid additional_header");
4718
- return PJ_FALSE;
4719
- }
5241
+ if(!document.HasMember("headers")) {
5242
+ return PJ_TRUE;
5243
+ }
4720
5244
 
4721
- if(strcmp(name, "Content-Type")==0) {
4722
- char *token_type = strtok(value, "/");
4723
- if(!token_type) {
4724
- set_error("No type specified in header Content-Type");
4725
- return PJ_FALSE;
4726
- }
4727
-
4728
- char *token_subtype = strtok(NULL, "\n");
4729
- if(!token_subtype) {
4730
- set_error("No subtype specified in header Content-Type");
4731
- return PJ_FALSE;
4732
- }
5245
+ if(!document["headers"].IsObject()) {
5246
+ set_error("Parameter headers must be an object");
5247
+ return PJ_FALSE;
5248
+ }
4733
5249
 
4734
- strcpy(type, token_type);
4735
- strcpy(subtype, token_subtype);
4736
- addon_log(LOG_LEVEL_DEBUG, "Checking parsing of Content-Type. type=%s: subtype=%s\n", type, subtype);
4737
- return PJ_TRUE;
4738
- }
4739
- token = strtok_r(NULL, "\n", &saved);
5250
+ Value headers = document["headers"].GetObject();
5251
+
5252
+ for (Value::ConstMemberIterator itr = headers.MemberBegin(); itr != headers.MemberEnd(); ++itr) {
5253
+ printf("%s => '%s'\n", itr->name.GetString(), itr->value.GetString());
5254
+
5255
+ const char *name = itr->name.GetString();
5256
+ if(!itr->value.IsString()) {
5257
+ set_error("Parameter headers key '%s' found with non-string value", name);
5258
+ return PJ_FALSE;
5259
+ }
5260
+
5261
+ const char *value = itr->value.GetString();
5262
+
5263
+ pj_str_t hname = pj_str((char*)name);
5264
+ pjsip_hdr *hdr = (pjsip_hdr*)pjsip_parse_hdr(pool,
5265
+ &hname,
5266
+ (char*)value,
5267
+ strlen(value),
5268
+ NULL);
5269
+
5270
+ if(!hdr) {
5271
+ set_error("Failed to parse header %s", name);
5272
+ return PJ_FALSE;
5273
+ }
5274
+
5275
+ pj_list_push_back(&hdr_list, hdr);
4740
5276
  }
4741
- set_error("Header Content-Type not supplied");
4742
- return PJ_FALSE;
5277
+
5278
+ pjsip_regc_add_headers(regc, &hdr_list);
5279
+ return PJ_TRUE;
5280
+ }
5281
+
5282
+ pj_bool_t get_content_type_and_subtype_from_headers(Document &document, char *type, char *subtype) {
5283
+ if(!document.HasMember("headers")) {
5284
+ set_error("Parameter headers absent");
5285
+ return PJ_FALSE;
5286
+ }
5287
+
5288
+ if(!document["headers"].IsObject()) {
5289
+ set_error("Parameter headers must be an object");
5290
+ return PJ_FALSE;
5291
+ }
5292
+
5293
+ Value headers = document["headers"].GetObject();
5294
+
5295
+ if(!headers.HasMember("Content-Type")) {
5296
+ set_error("Parameter headers doesn't contain key Content-Type");
5297
+ return PJ_FALSE;
5298
+ }
5299
+
5300
+ const char *content_type = headers["Content-Type"].GetString();
5301
+
5302
+ const char *slash;
5303
+ int index;
5304
+
5305
+ slash = strchr(content_type, '/');
5306
+ if(!slash) {
5307
+ set_error("Invalid header Content-Type");
5308
+ return PJ_FALSE;
5309
+ }
5310
+
5311
+ index = (int)(slash - content_type);
5312
+
5313
+ strncpy(type, content_type, index-1);
5314
+ strcpy(subtype, content_type+index);
5315
+ addon_log(LOG_LEVEL_DEBUG, "Checking parsing of Content-Type. type=%s: subtype=%s\n", type, subtype);
5316
+ return PJ_TRUE;
4743
5317
  }
4744
5318
 
4745
5319
 
@@ -4765,7 +5339,7 @@ int pjw_register_pkg(const char *event, const char *accept) {
4765
5339
 
4766
5340
  clear_error();
4767
5341
 
4768
- int n;
5342
+ //int n;
4769
5343
 
4770
5344
  if(!register_pkg(event, accept)) {
4771
5345
  goto out;
@@ -4780,12 +5354,23 @@ out:
4780
5354
  return 0;
4781
5355
  }
4782
5356
 
4783
- int pjw_subscription_create(long transport_id, const char *event, const char *accept, const char *from_uri, const char *to_uri, const char *request_uri, const char *proxy_uri, const char *realm, const char *username, const char *password, long *out_subscription_id) {
5357
+ //int pjw_subscription_create(long transport_id, const char *event, const char *accept, const char *from_uri, const char *to_uri, const char *request_uri, const char *proxy_uri, const char *realm, const char *username, const char *password, long *out_subscription_id) {
5358
+ int pjw_subscription_create(long transport_id, const char *json, long *out_subscription_id) {
4784
5359
  PJW_LOCK();
4785
-
4786
5360
  clear_error();
4787
5361
 
4788
- int n;
5362
+ char *event = NULL;
5363
+ char *accept = NULL;
5364
+
5365
+ char *from_uri = NULL;
5366
+ char *to_uri = NULL;
5367
+ char *request_uri = NULL;
5368
+ char *proxy_uri = NULL;
5369
+
5370
+ char *realm = NULL;
5371
+ char *username = NULL;
5372
+ char *password = NULL;
5373
+
4789
5374
  long subscription_id;
4790
5375
  Subscription *subscription;
4791
5376
  Transport *t;
@@ -4793,7 +5378,7 @@ int pjw_subscription_create(long transport_id, const char *event, const char *ac
4793
5378
  const char *contact_username = "sip";
4794
5379
 
4795
5380
  char local_contact[400];
4796
- char *start;
5381
+ //char *start;
4797
5382
 
4798
5383
  pjsip_dialog *dlg = NULL;
4799
5384
  pjsip_evsub *evsub = NULL;
@@ -4803,38 +5388,80 @@ int pjw_subscription_create(long transport_id, const char *event, const char *ac
4803
5388
 
4804
5389
  pj_status_t status;
4805
5390
 
5391
+ char buffer[MAX_JSON_INPUT];
5392
+
5393
+ Document document;
5394
+
4806
5395
  if(!g_transport_ids.get(transport_id, val)){
4807
5396
  set_error("Invalid transport_id");
4808
5397
  goto out;
4809
5398
  }
4810
5399
  t = (Transport*)val;
4811
5400
 
4812
- if(!check_uri(from_uri)) {
4813
- set_error("Invalid from_uri");
4814
- goto out;
4815
- }
5401
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
5402
+ goto out;
5403
+ }
4816
5404
 
4817
- if(!check_uri(to_uri)) {
4818
- set_error("Invalid to_uri");
4819
- goto out;
4820
- }
5405
+ if(!json_get_string_param(document, "event", false, &event)) {
5406
+ goto out;
5407
+ }
5408
+
5409
+ if(!json_get_string_param(document, "accept", false, &accept)) {
5410
+ goto out;
5411
+ }
5412
+
5413
+ if(!json_get_and_check_uri(document, "from_uri", false, &from_uri)) {
5414
+ goto out;
5415
+ }
5416
+
5417
+ if(!json_get_and_check_uri(document, "to_uri", false, &to_uri)) {
5418
+ goto out;
5419
+ }
4821
5420
 
4822
- if(request_uri){
4823
- if(!check_uri(request_uri)) {
4824
- set_error("Invalid request_uri");
5421
+ request_uri = to_uri;
5422
+ if(!json_get_and_check_uri(document, "request_uri", true, &request_uri)) {
5423
+ goto out;
5424
+ }
5425
+
5426
+ if(!json_get_and_check_uri(document, "proxy_uri", true, &proxy_uri)) {
5427
+ goto out;
5428
+ }
5429
+
5430
+ if(document.HasMember("auth")) {
5431
+ if(!document["auth"].IsObject()) {
5432
+ set_error("Parameter auth must be an object");
5433
+ goto out;
5434
+ } else {
5435
+ const Value& auth = document["auth"];
5436
+
5437
+ for (Value::ConstMemberIterator itr = auth.MemberBegin(); itr != auth.MemberEnd(); ++itr) {
5438
+ const char *name = itr->name.GetString();
5439
+ if(strcmp(name, "realm") == 0) {
5440
+ if(!itr->value.IsString()) {
5441
+ set_error("%s must be a string", itr->name.GetString());
4825
5442
  goto out;
5443
+ }
5444
+ realm = (char*)itr->value.GetString();
5445
+ } else if(strcmp(name, "username") == 0) {
5446
+ if(!itr->value.IsString()) {
5447
+ set_error("%s must be a string", itr->name.GetString());
5448
+ goto out;
5449
+ }
5450
+ username = (char*)itr->value.GetString();
5451
+ contact_username = username;
5452
+ } else if(strcmp(name, "password") == 0) {
5453
+ if(!itr->value.IsString()) {
5454
+ set_error("%s must be a string", itr->name.GetString());
5455
+ goto out;
5456
+ }
5457
+ password = (char*)itr->value.GetString();
5458
+ } else {
5459
+ set_error("Unknown auth paramter %s", itr->name.GetString());
5460
+ goto out;
4826
5461
  }
4827
- }else{
4828
- request_uri = to_uri;
5462
+ }
4829
5463
  }
4830
-
4831
- if(realm) {
4832
- if(!username || !password) {
4833
- set_error("Not all authentication data was provided");
4834
- goto out;
4835
- }
4836
- contact_username = username;
4837
- }
5464
+ }
4838
5465
 
4839
5466
  build_local_contact(local_contact, t->sip_transport, contact_username);
4840
5467
 
@@ -4859,7 +5486,7 @@ int pjw_subscription_create(long transport_id, const char *event, const char *ac
4859
5486
  PJSIP_EVSUB_NO_EVENT_ID,
4860
5487
  &evsub);
4861
5488
  if(status != PJ_SUCCESS) {
4862
- set_error("pjsip_evsub_create_uac failed");
5489
+ set_error("pjsip_evsub_create_uac failed with status=%i", status);
4863
5490
  goto out;
4864
5491
  }
4865
5492
 
@@ -4885,17 +5512,46 @@ int pjw_subscription_create(long transport_id, const char *event, const char *ac
4885
5512
  strcpy(subscription->accept, accept);
4886
5513
  pjsip_evsub_set_mod_data(evsub, mod_tester.id, subscription);
4887
5514
 
5515
+ *out_subscription_id = subscription_id;
4888
5516
  out:
4889
5517
  PJW_UNLOCK();
4890
5518
  if(pjw_errorstring[0]){
4891
5519
  return -1;
4892
5520
  }
4893
-
4894
- *out_subscription_id = subscription_id;
4895
5521
  return 0;
4896
5522
  }
4897
5523
 
4898
- bool subscription_subscribe(Subscription *s, int expires, const char *additional_headers) {
5524
+ bool subscription_subscribe_no_headers(Subscription *s, int expires) {
5525
+ pj_status_t status;
5526
+ pjsip_tx_data *tdata;
5527
+
5528
+ status = pjsip_evsub_initiate(s->evsub,
5529
+ NULL,
5530
+ expires,
5531
+ &tdata);
5532
+ if(status != PJ_SUCCESS) {
5533
+ set_error("pjsip_evsub_initiate failed");
5534
+ return false;
5535
+ }
5536
+
5537
+ status = pjsip_evsub_send_request(s->evsub, tdata);
5538
+ if(status != PJ_SUCCESS) {
5539
+ set_error("pjsip_inv_send_msg failed");
5540
+ return false;
5541
+ }
5542
+
5543
+ //Without this, on_rx_response will not be called
5544
+ status = pjsip_dlg_add_usage(s->dlg, &mod_tester, s);
5545
+ if(status != PJ_SUCCESS) {
5546
+ set_error("pjsip_dlg_add_usage failed");
5547
+ return false;
5548
+ }
5549
+
5550
+ return true;
5551
+ }
5552
+
5553
+
5554
+ bool subscription_subscribe(Subscription *s, int expires, Document &document) {
4899
5555
  pj_status_t status;
4900
5556
  pjsip_tx_data *tdata;
4901
5557
 
@@ -4908,7 +5564,7 @@ bool subscription_subscribe(Subscription *s, int expires, const char *additional
4908
5564
  return false;
4909
5565
  }
4910
5566
 
4911
- if(!add_additional_headers(s->dlg->pool, tdata, additional_headers)) {
5567
+ if(!add_headers(s->dlg->pool, tdata, document)) {
4912
5568
  return false;
4913
5569
  }
4914
5570
 
@@ -4928,29 +5584,41 @@ bool subscription_subscribe(Subscription *s, int expires, const char *additional
4928
5584
  return true;
4929
5585
  }
4930
5586
 
4931
- int pjw_subscription_subscribe(long subscription_id, int expires, const char *additional_headers) {
5587
+ //int pjw_subscription_subscribe(long subscription_id, int expires, const char *additional_headers) {
5588
+ int pjw_subscription_subscribe(long subscription_id, const char *json) {
4932
5589
  PJW_LOCK();
4933
-
4934
5590
  clear_error();
4935
5591
 
5592
+ int expires;
5593
+
4936
5594
  Subscription *subscription;
4937
5595
 
4938
5596
  long val;
4939
5597
 
5598
+ char buffer[MAX_JSON_INPUT];
5599
+
5600
+ Document document;
5601
+
4940
5602
  if(!g_subscription_ids.get(subscription_id, val)){
4941
5603
  set_error("Invalid subscription_id");
4942
5604
  goto out;
4943
5605
  }
4944
-
4945
5606
  subscription = (Subscription*)val;
4946
5607
 
4947
- if(!subscription_subscribe(subscription, expires, additional_headers)) {
5608
+ if(!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
5609
+ goto out;
5610
+ }
5611
+
5612
+ if(!json_get_int_param(document, "expires", true, &expires)) {
5613
+ goto out;
5614
+ }
5615
+
5616
+ if(!subscription_subscribe(subscription, expires, document)) {
4948
5617
  goto out;
4949
5618
  }
4950
5619
 
4951
5620
  out:
4952
5621
  PJW_UNLOCK();
4953
-
4954
5622
  if(pjw_errorstring[0]) {
4955
5623
  return -1;
4956
5624
  }
@@ -4961,7 +5629,7 @@ void process_in_dialog_subscribe(pjsip_dialog *dlg, pjsip_rx_data *rdata) {
4961
5629
  char evt[2048];
4962
5630
 
4963
5631
  Subscriber *s;
4964
- Transport *t;
5632
+ //Transport *t;
4965
5633
 
4966
5634
  s = (Subscriber*)dlg->mod_data[mod_tester.id];
4967
5635
  if(!s) {
@@ -4979,11 +5647,11 @@ int pjw_call_gen_string_replaces(long call_id, char *out_replaces) {
4979
5647
 
4980
5648
  clear_error();
4981
5649
 
4982
- int n;
5650
+ //int n;
4983
5651
  long val;
4984
5652
  Call *call;
4985
5653
  pjsip_dialog *dlg;
4986
- int len;
5654
+ //int len;
4987
5655
  char *p;
4988
5656
  char buf[2000];
4989
5657
  pjsip_uri* uri;