message_events.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <?php
  2. /*
  3. description - message_events service
  4. - subcribes to get notified for each SIP Message
  5. - sends messages to external numbers to the message_queue
  6. - message tests
  7. handled messages_events service
  8. from 1008 to 1001 (partial loop, no message queue)
  9. from 1001 to 1008 (partial loop, no message queue)
  10. from 1008 to 2089068227 (runs through entire loop, sends to message queue)
  11. handled by message/index
  12. from 2089068227 to 1008
  13. */
  14. //only allow command line
  15. if (defined('STDIN')) {
  16. //set the include path
  17. $conf = glob("{/usr/local/etc,/etc}/fusionpbx/config.conf", GLOB_BRACE);
  18. set_include_path(parse_ini_file($conf[0])['document.root']);
  19. }
  20. else {
  21. exit;
  22. }
  23. //increase limits
  24. set_time_limit(0);
  25. ini_set('max_execution_time', 0);
  26. ini_set('memory_limit', '512M');
  27. //save the arguments to variables
  28. $script_name = $argv[0];
  29. if (!empty($argv[1])) {
  30. parse_str($argv[1], $_GET);
  31. }
  32. //set the variables
  33. if (isset($_GET['hostname'])) {
  34. $hostname = urldecode($_GET['hostname']);
  35. }
  36. if (isset($_GET['debug'])) {
  37. $debug = $_GET['debug'];
  38. }
  39. //set the hostname if it wasn't provided
  40. if (!isset($hostname) || (isset($hostname) && strlen($hostname) == 0)) {
  41. $hostname = gethostname();
  42. }
  43. //includes
  44. require_once "resources/require.php";
  45. include "resources/classes/permissions.php";
  46. //define the process id file
  47. $pid_file = "/var/run/fusionpbx/".basename( $argv[0], ".php") .".pid";
  48. //echo "pid_file: ".$pid_file."\n";
  49. //function to check if the process exists
  50. function process_exists($file = false) {
  51. //set the default exists to false
  52. $exists = false;
  53. //check to see if the process is running
  54. if (file_exists($file)) {
  55. $pid = file_get_contents($file);
  56. if (posix_getsid($pid) === false) {
  57. //process is not running
  58. $exists = false;
  59. }
  60. else {
  61. //process is running
  62. $exists = true;
  63. }
  64. }
  65. //return the result
  66. return $exists;
  67. }
  68. //check to see if the process exists
  69. $pid_exists = process_exists($pid_file);
  70. //prevent the process running more than once
  71. if ($pid_exists) {
  72. echo "Cannot lock pid file {$pid_file}\n";
  73. exit;
  74. }
  75. //create the process id file if the process doesn't exist
  76. if (!$pid_exists) {
  77. //remove the old pid file
  78. if (file_exists($file)) {
  79. unlink($pid_file);
  80. }
  81. //show the details to the user
  82. //echo "The process id is ".getmypid()."\n";
  83. //save the pid file
  84. file_put_contents($pid_file, getmypid());
  85. }
  86. //connect to event socket
  87. $socket = new event_socket;
  88. if (!$socket->connect($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password'])) {
  89. echo "Unable to connect to event socket\n";
  90. }
  91. //connect to event socket
  92. $fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']);
  93. //create the database connection
  94. $database = new database;
  95. //add the permission
  96. $p = permissions::new();
  97. $p->add('message_queue_add', 'temp');
  98. //example command
  99. //$cmd = "api help";
  100. //$result = $esl->request($cmd);
  101. //echo "help: ".$result."\n";
  102. //loop through the switch events
  103. //read the events
  104. //$cmd = "event plain ALL";
  105. //$cmd = "event xml ALL";
  106. $cmd = "event json MESSAGE";
  107. //$cmd = "event json CUSTOM";
  108. $result = $socket->request($cmd);
  109. while ($socket) {
  110. //read events from socket
  111. $response = $socket->read_event();
  112. //decode the event into an array
  113. $array = json_decode($response['$'], true);
  114. //initialize variable(s)
  115. $user_uuid = '';
  116. $message_type = 'sms';
  117. //set variables from the event array
  118. $event_name = $array['Event-Name'];
  119. $event_type = $array['event_type'];
  120. $event_subclass = $array['Event-Subclass'];
  121. $from = $array['from'];
  122. $from_array = explode("@", $from);
  123. $from_user = $array['from_user'];
  124. $from_host = $array['from_host'];
  125. $to_user = $array['to_user'];
  126. $to_host = $array['to_host'];
  127. $from_sip_ip = $array['from_sip_ip'];
  128. $message_content = $array['_body'];
  129. $to = $array['to_user'];
  130. //if the message is from an external number don't relay the message
  131. $from_command = "user_exists id ".$from_user." ".$from_host;
  132. $from_response = event_socket_request($fp, "api ".$from_command);
  133. $to_command = "user_exists id ".$to_user." ".$to_host;
  134. $to_response = event_socket_request($fp, "api ".$to_command);
  135. if ($debug) {
  136. echo "from command: ".$from_command."\n";
  137. echo "from response: ".$from_response."\n\n";
  138. echo "to command: ".$to_command."\n";
  139. echo "to response: ".$to_response."\n\n";
  140. }
  141. //from and to are both local then don't send to the message queue
  142. if ($from_response == 'true' && $to_response == 'true') {
  143. usleep(10000);
  144. continue;
  145. }
  146. //get the from user's external number
  147. $command = "user_data ".$from_user."@".$from_host." var outbound_caller_id_number";
  148. //echo $command."\n";
  149. $source_number = event_socket_request($fp, "api ".$command);
  150. /*
  151. [from] => [email protected]
  152. [from_user] => 1005
  153. [from_host] => voip.fusionpbx.com
  154. [to_user] => 12088058985
  155. [to_host] => voip.fusionpbx.com
  156. [from_sip_ip] => 96.18.173.64
  157. [from_sip_port] => 14395
  158. [to] => [email protected]
  159. [subject] => SIMPLE MESSAGE
  160. [context] => public
  161. [type] => text/plain
  162. [from_full] => <sip:[email protected]>;tag=6952509
  163. [sip_profile] => internal
  164. [dest_proto] => sip
  165. [max_forwards] => 70
  166. [DP_MATCH] => [email protected]
  167. [Nonblocking-Delivery] => true
  168. [Content-Length] => 4
  169. [_body] => nova
  170. */
  171. //reconnect to the database
  172. if (!$database) {
  173. $database = new database;
  174. }
  175. //get the provider uuid - needed for sending the message
  176. $sql = "SELECT * FROM v_destinations \n";
  177. $sql .= "WHERE ( \n";
  178. $sql .= " destination_prefix || destination_area_code || destination_number = :source_number \n";
  179. $sql .= " OR destination_trunk_prefix || destination_area_code || destination_number = :source_number \n";
  180. $sql .= " OR destination_prefix || destination_number = :source_number \n";
  181. $sql .= " OR '+' || destination_prefix || destination_number = :source_number \n";
  182. $sql .= " OR '+' || destination_prefix || destination_area_code || destination_number = :source_number \n";
  183. $sql .= " OR destination_area_code || destination_number = :source_number \n";
  184. $sql .= " OR destination_number = :source_number \n";
  185. $sql .= ") \n";
  186. $parameters['source_number'] = $source_number;
  187. $row = $database->select($sql, $parameters, 'row');
  188. //view_array($row, false);
  189. if (empty($row)) { continue; }
  190. $domain_uuid = $row["domain_uuid"];
  191. $provider_uuid = $row["provider_uuid"];
  192. $destination_prefix = $row["destination_prefix"];
  193. $destination_number = $row["destination_number"];
  194. unset($parameters, $row);
  195. //get the provider settings
  196. $sql = "select provider_setting_category, provider_setting_subcategory, ";
  197. $sql .= "provider_setting_name, provider_setting_value, provider_setting_order \n";
  198. $sql .= "from v_provider_settings \n";
  199. $sql .= "where provider_uuid = :provider_uuid \n";
  200. $sql .= "and provider_setting_category = 'outbound' \n";
  201. $sql .= "and provider_setting_subcategory = 'format' \n";
  202. $sql .= "and provider_setting_enabled = 'true'; \n";
  203. $parameters['provider_uuid'] = $provider_uuid;
  204. $database = new database;
  205. $provider_settings = $database->select($sql, $parameters, 'all');
  206. unset($parameters);
  207. if (isset($_GET['debug'])) {
  208. echo $sql;
  209. print_r($parameters);
  210. print_r($provider_settings);
  211. echo "\n";
  212. }
  213. //process the provider settings array
  214. foreach ($provider_settings as $row) {
  215. //format the phone numbers
  216. if ($row['provider_setting_name'] == 'message_from') {
  217. $from = format_string($row['provider_setting_value'], $destination_number);
  218. }
  219. if ($row['provider_setting_name'] == 'message_to') {
  220. $to = format_string($row['provider_setting_value'], $to);
  221. }
  222. }
  223. //if any of these are empty then skip the rest of the current loop
  224. if (empty($from) || empty($to) || empty($message_content)) {
  225. usleep(10000);
  226. continue;
  227. }
  228. //get the user_uuid - needed for sending the message
  229. $sql = "select user_uuid from v_extension_users \n";
  230. $sql .= "where extension_uuid in ( \n";
  231. $sql .= " select extension_uuid \n";
  232. $sql .= " from v_extensions \n";
  233. $sql .= " where extension = :extension \n";
  234. $sql .= " and domain_uuid = :domain_uuid\n";
  235. $sql .= ");\n";
  236. $parameters['extension'] = $from_user;
  237. $parameters['domain_uuid'] = $domain_uuid;
  238. $row = $database->select($sql, $parameters, 'row');
  239. //view_array($row, false);
  240. if (!empty($row)) {
  241. $user_uuid = $row["user_uuid"];
  242. }
  243. unset($parameters);
  244. //send the message using the message queue
  245. $array['message_queue'][0]['domain_uuid'] = $domain_uuid;
  246. $array['message_queue'][0]['message_queue_uuid'] = uuid();
  247. $array['message_queue'][0]['user_uuid'] = $user_uuid;
  248. //$array['message_queue'][0]['contact_uuid'] = $contact_uuid;
  249. $array['message_queue'][0]['provider_uuid'] = $provider_uuid;
  250. $array['message_queue'][0]['hostname'] = system('hostname');
  251. $array['message_queue'][0]['message_status'] = 'waiting';
  252. $array['message_queue'][0]['message_type'] = $message_type;
  253. $array['message_queue'][0]['message_direction'] = 'outbound';
  254. $array['message_queue'][0]['message_date'] = 'now()';
  255. $array['message_queue'][0]['message_from'] = $from;
  256. $array['message_queue'][0]['message_to'] = $to;
  257. $array['message_queue'][0]['message_text'] = $message_content;
  258. //view_array($array);
  259. //build message media array (if necessary)
  260. //$p = permissions::new();
  261. //if (is_array($message_media) && @sizeof($message_media) != 0) {
  262. // foreach($message_media as $index => $media) {
  263. // $array['message_media'][$index]['message_media_uuid'] = $media['uuid'];
  264. // $array['message_media'][$index]['message_uuid'] = $message_uuid;
  265. // $array['message_media'][$index]['domain_uuid'] = $_SESSION["domain_uuid"];
  266. // $array['message_media'][$index]['user_uuid'] = $_SESSION["user_uuid"];
  267. // $array['message_media'][$index]['message_media_type'] = strtolower(pathinfo($media['name'], PATHINFO_EXTENSION));
  268. // $array['message_media'][$index]['message_media_url'] = $media['name'];
  269. // $array['message_media'][$index]['message_media_content'] = base64_encode(file_get_contents($media['tmp_name']));
  270. // }
  271. // $p->add('message_media_add', 'temp');
  272. // $message_media_exists = true;
  273. //}
  274. //save to the data
  275. $database->app_name = 'messages';
  276. $database->app_uuid = '4a20815d-042c-47c8-85df-085333e79b87';
  277. $message = $database->save($array, false);
  278. if ($debug) {
  279. print_r($message);
  280. }
  281. unset($array);
  282. // current memory
  283. //$memory_usage = memory_get_usage();
  284. // peak memory
  285. //$memory_peak = memory_get_peak_usage();
  286. //echo 'Current memory: ' . round($memory_usage / 1024) . " KB\n";
  287. //echo 'Peak memory: ' . round($memory_peak / 1024) . " KB\n\n";
  288. //slow down the loop to reduce cpu usage
  289. usleep(10000);
  290. }
  291. //remove the permission
  292. $p->delete('message_queue_add', 'temp');
  293. //remove the old pid file
  294. if (file_exists($file)) {
  295. unlink($pid_file);
  296. }
  297. //save output to
  298. //$fp = fopen(sys_get_temp_dir()."/mailer-app.log", "a");
  299. //prepare the output buffers
  300. //ob_end_clean();
  301. //ob_start();
  302. //message divider for log file
  303. //echo "\n\n=========================================================================\n\n";
  304. //get and save the output from the buffer
  305. //$content = ob_get_contents(); //get the output from the buffer
  306. //$content = str_replace("<br />", "", $content);
  307. //ob_end_clean(); //clean the buffer
  308. //fwrite($fp, $content);
  309. //fclose($fp);
  310. //to do list
  311. // destination_number -> digits length the provider requires
  312. // local extension to extension messages
  313. // cross tenant messages on same server
  314. // cross server messages off the local server
  315. // test multiple registrations for the same extension
  316. // maybe merge into one server rather than multiple
  317. // use a queue for inbound messages don't send unless the SIP user is registered
  318. // group messages to multiple users
  319. // limit number of messages to the provider per second per source number
  320. // add media support for sending photos
  321. //how to use this feature
  322. // cd /var/www/fusionpbx && /usr/bin/php /var/www/fusionpbx/app/messages/resources/service/message_events.php >> /dev/null 2>&1 &
  323. ?>