#!/usr/bin/php debug("Socket cannot be created due to errno [$errno] - $errstr"); exit(0); } echo "Connecting to asterisk server @ " . date("Y-m-d H:i:s") . "\n"; $log->debug("Connecting to asterisk server @ " . date("Y-m-d H:i:s")); echo "Connected successfully\n\n"; $asterisk = new Asterisk($sock, $data['server'], $data['port']); # authorize user first authorizeUser($data['username'], $data['password'], $asterisk); // Keep looping to poll the asterisk events while(true) { // Give some break to avoid server hanging sleep(1); try { $incoming = asterisk_handleEvents($asterisk, $adb, $data['version']); asterisk_IncomingEventCleanup($adb); } catch(Exception $ex) { echo "EXCEPTION: " . $ex->getMessage() . "\n"; } } fclose($sock); unset($sock); } /* * Delete the stale incoming events information recorded to avoid * overgrowth of the database. */ function asterisk_IncomingEventCleanup($adb) { $HOURRANGE = 60 * 60; $TIMELIMIT = $HOURRANGE * 12; // Delete events older than 'n' hours $adb->pquery("DELETE FROM vtiger_asteriskincomingevents WHERE timer < ? ", array(time() - $TIMELIMIT) ); } /** * Grab the events from server, parse it and process it. */ function asterisk_handleEvents($asterisk, $adb, $version="1.4") { $fnEntryTime = time(); //values of flag for asteriskincomingevents(-1 for stray calls, 0 for incoming calls, 1 for outgoing call) do { $mainresponse = $asterisk->getAsteriskResponse(); if(!empty($mainresponse)) { $state = ($version == "1.6")? "ChannelStateDesc" : "State"; if(asterisk_handleResponse1($mainresponse, $state, $adb)) { echo "iff1"; if(asterisk_handleResponse2($mainresponse, $adb, $asterisk, $state)) { echo "iff2"; if(asterisk_handleResponse3($mainresponse, $adb, $asterisk)){ echo "iff3"; // Proceed if previous event could not be handled. } } } } else { // No more response to consume break; } } while(true); return false; } function asterisk_handleResponse1($mainresponse, $state, $adb) { if( (($mainresponse['Event'] == 'Newstate' || $mainresponse['Event'] == 'Newchannel') && ($mainresponse[$state] == 'Ring') || ($mainresponse['Event'] == 'Newstate' && $mainresponse[$state] == 'Ringing')) ) { $uniqueid = $mainresponse['Uniqueid']; /* fix1 if(!empty($mainresponse['CallerID'])) { $callerNumber = $mainresponse['CallerID']; }elseif(!empty($mainresponse['CallerIDNum'])) { $callerNumber = $mainresponse['CallerIDNum']; } */ if(!empty($mainresponse['CallerIDName'])) { $callerName = $mainresponse['CallerIDName']; } $channel = $mainresponse['Channel']; // fix by alang $callerNumber = $mainresponse['CallerIDNum']; $sql = "INSERT INTO vtiger_asteriskincomingevents (uid, channel, from_number, from_name, timer, flag) VALUES(?,?,?,?,?,?)"; $adb->pquery($sql, array($uniqueid, $channel, $callerNumber, $callerName, time(), -1)); return false; } return true; } function asterisk_handleResponse2($mainresponse, $adb, $asterisk, $state) { $appdata = $mainresponse['AppData']; $uniqueid = $channel = $callerType = $extension = null; $parseSuccess = false; if( // fix3 $mainresponse['Event'] == 'Newexten' && (strstr($appdata, "__DIALED_NUMBER") || strstr($appdata, "EXTTOCALL")) ($mainresponse['Event'] == 'Newexten') && ($mainresponse['Application'] == 'Dial') ) { $uniqueid = $mainresponse['Uniqueid']; $channel = $mainresponse['Channel']; $splits = explode('/', $channel); $callerType = $splits[0]; //possible fix4 $callerType = ''; θλ?SIP /* $splits = explode('=', $appdata); $extension = $splits[1]; $extension = $mainresponse['Extension']; */ // fix by alang $splits = preg_split("/[\/,]/",$appdata); $extension = $splits[1]; $parseSuccess = true; } else if($mainresponse['Event'] == 'OriginateResponse'){ //if the event is OriginateResponse then its an outgoing call and set the flag to 1, so that AsteriskClient does not pick up as incoming call $uniqueid = $mainresponse['Uniqueid']; $adb->pquery("UPDATE vtiger_asteriskincomingevents set flag = 1 WHERE uid = ?", array($uniqueid)); } if($parseSuccess) { if(checkExtension($extension, $adb)) { $sql = "UPDATE vtiger_asteriskincomingevents SET to_number=?, callertype=?, timer=?, flag=? WHERE uid=?"; $adb->pquery($sql, array($extension, $callerType, time(), 0, $uniqueid)); $callerinfo = $adb->pquery("SELECT from_number,from_name FROM vtiger_asteriskincomingevents WHERE uid = ?",array($uniqueid)); if($adb->num_rows($callerinfo) > 0){ $callerNumber = $adb->query_result($callerinfo, 0, "from_number"); $callerName = $adb->query_result($callerinfo, 0, "from_name"); if(empty($callerNumber) || $callerNumber == '0') { // We don't have the information who is calling, could happen in Asterisk 1.4 (when call is made to Queue) // Let us defer the popup show for next Event: Link $sql = "UPDATE vtiger_asteriskincomingevents SET flag=? WHERE uid=?"; $adb->pquery($sql, array(-1, $uniqueid)); } else { $query = "INSERT INTO vtiger_asteriskincomingcalls (refuid, from_number, from_name, to_number, callertype, flag, timer) VALUES(?,?,?,?,?,?,?)"; $adb->pquery($query,array($uniqueid, $callerNumber, $callerName, $extension, $callerType, 0, time())); } } } return false; } return true; } function asterisk_handleResponse3($mainresponse, $adb, $asterisk){ $uid = false; $receiver_callerinfo = false; // Asterisk 1.4 (Event: Link), Asterisk 1.6 (Event: Bride, Bridgestate: Link) if($mainresponse['Event'] == 'Link' || ($mainresponse['Event'] == 'Bridge' && $mainresponse['Bridgestate'] == 'Link')){ $uid = $mainresponse['Uniqueid1']; $uid2 = $mainresponse['Uniqueid2']; $callerNumber = $mainresponse['CallerID1']; $extensionCalled = $mainresponse['CallerID2']; // Ignore the case wheren CallerIDs are same! if($callerNumber == $extensionCalled) { // case handled but we ignored. return false; } $callerType = ''; $status = "received"; $sourceChannel = $mainresponse['Channel1']; // Check if Popup has already been shown to user? // Due to (asterisk 1.4 bug: https://issues.asterisk.org/view.php?id=11757) // Popup display for Call made to queue is defered and will be handled below // So we need to pick up events with (flag = 0, asterisk 1.6) or (flag = -1, asterisk 1.4) // asterisk 1.4 - from_number is NULL, // TODO check the state of from_number in asterisk 1.6 $checkres = $adb->pquery("SELECT * FROM vtiger_asteriskincomingevents WHERE uid=? and (flag = 0 or flag = -1) and (from_number is NULL or from_number = 0)", array($uid)); if($adb->num_rows($checkres) > 0) { if(empty($checkresrow['from_name'])) $checkresrow['from_name'] = "Unknown"; $checkresrow = $adb->fetch_array($checkres); $sql = "UPDATE vtiger_asteriskincomingevents SET from_number=?, to_number=?, timer=?, flag=? WHERE uid=?"; $adb->pquery($sql, array($callerNumber, $extensionCalled, time(), 0, $uid)); // Check if the user has checked Incoming Calls in My Preferences if(checkExtension($extensionCalled, $adb)) { $query = "INSERT INTO vtiger_asteriskincomingcalls (refuid, from_number, from_name, to_number, callertype, flag, timer) VALUES(?,?,?,?,?,?,?)"; $adb->pquery($query,array($uid, $callerNumber, $checkresrow['from_name'], $extensionCalled, '', 0, time())); } } // END } else if($mainresponse['Event']== 'Newexten' && $mainresponse['AppData'] == "DIALSTATUS=CONGESTION" || $mainresponse['Event'] == 'Hangup'){ $status = "missed"; $uid = $mainresponse['Uniqueid']; $extensionCalled = false; } // TODO Need to detect the caller number using the Event Information $callerNumberInfo = $adb->pquery("SELECT from_number, callertype FROM vtiger_asteriskincomingevents WHERE uid=? AND from_number is not NULL LIMIT 1", array($uid)); if($callerNumberInfo && $adb->num_rows($callerNumberInfo)) { $callerNumber = $adb->query_result($callerNumberInfo, 0, 'from_number'); $receiver_callerinfo = getCallerInfo($callerNumber); } if($uid !== false) { // Create Record if not yet done and link to the event for further use $eventResult = $adb->pquery("SELECT * FROM vtiger_asteriskincomingevents WHERE uid = ? and pbxrecordid is NULL AND flag =0", array($uid)); if($adb->num_rows($eventResult)){ $eventResultRow = $adb->fetch_array($eventResult); $callerNumber = $eventResultRow['from_number']; if($extensionCalled === false) { $extensionCalled = $eventResultRow['to_number']; } // If we are not knowing the caller informatio (Asterisk 1.4, Event: Link not yet called) if($callerNumber != 'Unknown' && $callerNumber != '0') { $pbxrecordid = addToCallHistory($extensionCalled, $callerNumber, $extensionCalled , "incoming-$status", $adb, $receiver_callerinfo); $adb->pquery("UPDATE vtiger_asteriskincomingevents SET pbxrecordid = ? WHERE uid = ?", array($pbxrecordid, $uid)); if(!empty($receiver_callerinfo['id'])) { $adb->pquery("UPDATE vtiger_asteriskincomingevents SET relcrmid = ? WHERE uid = ?", array($receiver_callerinfo['id'], $uid)); } } return false; } } return true; } /** * Check if extension is configured to user in vtiger */ function checkExtension($ext, $adb){ $sql = "select 1 from vtiger_asteriskextensions where asterisk_extension=?"; $result = $adb->pquery($sql, array($ext)); if($adb->num_rows($result)>0){ return true; }else{ return false; } }