Your IP : 3.15.141.201
var WebRTCPlugin = function ()
{
/**
*
* @type {Window.BXCordovaPlugin}
*/
this.plugin = this.UI.plugin = new BXCordovaPlugin("MobileWebRTC");
this.CallBackExecute = function(){
this.plugin.CallBackExecute.apply(this.plugin, arguments);
}
};
WebRTCPlugin.prototype =
{
UI: {
state: {
"OUTGOING_CALL": "outgoing_call",
"INCOMING_CALL": "incoming_call",
"CONVERSATION": "conversation",
"FAIL_CALL": "fail_call"
},
exec: function (func, params)
{
console.log(this);
this.plugin.exec(func, params);
},
show: function (state, options)
{
var params = options || {};
params.state = state;
return this.exec("showUi", params);
},
close: function (params)
{
return this.plugin.exec("closeUi", params);
},
showLocalVideo: function (params)
{
return this.plugin.exec("showLocalVideo", params);
}
},
createPeerConnection: function (params)
{
return this.plugin.exec("createPeerConnection", params);
},
createOffer: function (params)
{
return this.plugin.exec("createOffer", params);
},
createAnswer: function (params)
{
return this.plugin.exec("createAnswer", params);
},
addIceCandidates:function (params)
{
return this.plugin.exec("addIceCandidates", params);
},
setRemoteDescription:function (params)
{
return this.plugin.exec("setRemoteDescription", params);
},
getUserMedia:function (params)
{
return this.plugin.exec("getUserMedia", params);
},
onReconnect:function (params)
{
return this.plugin.exec("onReconnect", params);
},
setEventListeners:function (params)
{
return this.plugin.exec("setEventListeners", params);
}
};
window.webrtc = webrtc = new WebRTCPlugin();
MobileWebrtc = function ()
{
this.siteDir = (typeof mobileSiteDir == "undefined" ? "/" : mobileSiteDir);
this.signalingLink = this.siteDir + 'mobile/ajax.php?mobile_action=calls&';
this.initiator = false;
this.callUserId = 0;
this.debug = false;
this.eventTimeRange = 30;
this.incomingCallTimeOut = 2;
this.delayedIncomingCall = {};
this.incomingCallTimeOutId = null;
this.callBackUserId = 0;
this.callChatId = 0;
this.callToGroup = false;
this.waitTimeout = false;
this.callGroupUsers = [];
this.callInit = false;
this.callActive = false;
this.ready = false;
this.pcStart = {};
this.connected = {};
this.sessionDescription = {};
this.remoteSessionDescription = {};
this.iceCandidates = [];
this.iceCandidatesToSend = [];
this.iceCandidateTimeout = 0;
this.peerConnectionInited = false;
this.utcOffest = BX.localStorage.get("bxUTCOffset");
if (this.utcOffest == null)
{
this.utcOffest = 0;
BX.ajax({
url: this.siteDir + "mobile/?mobile_action=service&service_id=server_utc",
method: 'GET',
dataType: 'json',
timeout: 30,
async: true,
onsuccess: BX.proxy(function (json)
{
if (json)
{
var localUtcTimeStamp = Math.round((new Date).getTime() / 1000);
this.utcOffest = json.server_utc_time - localUtcTimeStamp;
BX.localStorage.set("bxUTCOffset", this.utcOffest, 43200);
}
}, this),
onfailure: BX.proxy(function ()
{
}, this)
});
}
webrtc.setEventListeners(
{
//UI callbacks
"onAnswer": BX.proxy(this.onAnswer, this),
"onDecline": BX.proxy(this.onDecline, this),
"onCallback": BX.proxy(this.onCallback, this),
"onClose": BX.proxy(this.onClose, this),
//WebRTC callbacks
"onUserMediaSuccess": BX.proxy(this.onUserMediaSuccess, this),
"onDisconnect": BX.proxy(this.onDisconnect, this),
"onPeerConnectionCreated": BX.proxy(this.onPeerConnectionCreated, this),
"onIceCandidateDiscovered": BX.proxy(this.onIceCandidateDiscovered, this),
"onLocalSessionDescriptionCreated": BX.proxy(this.onLocalSessionDescriptionCreated, this),
"onIceConnectionStateChanged": BX.proxy(this.onIceConnectionStateChanged, this),
"onIceGatheringStateChanged": BX.proxy(this.onIceGatheringStateChanged, this),
"onSignalingStateChanged": BX.proxy(this.onSignalingStateChanged, this),
"onError": BX.proxy(this.onError, this)
}
);
};
MobileWebrtc.prototype.attachListeners = function ()
{
webrtc.setEventListeners(
{
//UI callbacks
"onAnswer": BX.proxy(this.onAnswer, this),
"onDecline": BX.proxy(this.onDecline, this),
"onCallback": BX.proxy(this.onCallback, this),
"onClose": BX.proxy(this.onClose, this),
//WebRTC callbacks
"onUserMediaSuccess": BX.proxy(this.onUserMediaSuccess, this),
"onDisconnect": BX.proxy(this.onDisconnect, this),
"onPeerConnectionCreated": BX.proxy(this.onPeerConnectionCreated, this),
"onIceCandidateDiscovered": BX.proxy(this.onIceCandidateDiscovered, this),
"onLocalSessionDescriptionCreated": BX.proxy(this.onLocalSessionDescriptionCreated, this),
"onIceConnectionStateChanged": BX.proxy(this.onIceConnectionStateChanged, this),
"onIceGatheringStateChanged": BX.proxy(this.onIceGatheringStateChanged, this),
"onSignalingStateChanged": BX.proxy(this.onSignalingStateChanged, this),
"onError": BX.proxy(this.onError, this)
}
);
};
/**
* Returns identifier of the current user
*/
MobileWebrtc.prototype.getUserId = function ()
{
return BX.message('USER_ID');
};
/**
* Invites user
* @param userId
* @param video
* @param repeat
*/
MobileWebrtc.prototype.callInvite = function (userId, video, repeat)
{
if (userId == this.getUserId() || this.callInit)
return;
if (this.delayedIncomingCall.chatId && this.delayedIncomingCall.senderId == userId)
{
this.clearDelayedCallData();
}
var callVideo = !(typeof video != "undefined" && video === false);
var isRepeatCall = (repeat === true);
this.callInit = true;
this.video = callVideo;
this.initiator = true;
this.isConversationUIReady = false;
this.ajaxCall("CALL_INVITE", {
'COMMAND': 'invite',
'CHAT_ID': userId,
'CHAT': 'N',
'VIDEO': (callVideo ? "Y" : "N")
},
BX.delegate(function (params)
{
if (params.ERROR)
{
if (isRepeatCall)
{
this.resetState();
this.callInit = false;
this.finishDialog();
}
else if (params.ERROR == "SESSION_ERROR")
{
BX.message.bitrix_sessid = params.BITRIX_SESSID;
this.callInit = false;
this.callInvite(userId, video, true);
}
else if (params.ERROR == 'AUTHORIZE_ERROR')
{
app.BasicAuth({
success: BX.delegate(function ()
{
this.callInit = false;
this.callInvite(userId, video, true);
}, this)
});
}
return;
}
this.isConversationUIReady = true;
this.initiator = true;
this.callChatId = params.CHAT_ID;
this.callToGroup = params.CALL_TO_GROUP;
this.callUserId = userId;
this.attachListeners();
webrtc.UI.show(
webrtc.UI.state.OUTGOING_CALL,
{
"data": params,
"video": callVideo,
"recipient": {
"avatar": params["HR_PHOTO"][this.callUserId],
"name": params["USERS"][this.callUserId]["name"]
},
"caller": {
"avatar": params["HR_PHOTO"][this.getUserId()],
"name": params["USERS"][this.getUserId()]["name"]
}
}
);
BX.onCustomEvent("onMobileRTCReadyToConversation");
}, this),
BX.delegate(function (params)
{
//TODO error handling
this.resetState();
this.callInit = false;
this.finishDialog();
}, this)
);
};
/**
* Shows incoming call screen
* @param params
*/
MobileWebrtc.prototype.showIncomingCall = function (params)
{
this.callChatId = params.chatId;
this.callToGroup = false;
this.callUserId = params.senderId;
this.initiator = false;
this.callInit = true;
this.callCommand(this.callChatId, 'wait');
this.attachListeners();
webrtc.UI.show(
webrtc.UI.state.INCOMING_CALL,
{
"data": params,
"video": params.video,
"caller": {
"name": params["users"][params.senderId]["name"],
"avatar": params["hrphoto"][params.senderId]
}
}
);
};
/**
* Clears data for delayed incoming call
*/
MobileWebrtc.prototype.clearDelayedCallData = function ()
{
clearTimeout(this.incomingCallTimeOutId);
this.incomingCallTimeOutId = null;
this.delayedIncomingCall = {};
};
/**
* Resets all variables, connection data and states
*/
MobileWebrtc.prototype.resetState = function ()
{
this.connected = {};
this.initiator = false;
this.callInit = false;
this.video = false;
this.callActive = false;
this.callChatId = 0;
this.callUserId = 0;
this.isMobile = false;
this.peerConnectionInited = false;
this.iceCandidates = [];
this.iceCandidatesToSend = [];
this.isConversationUIReady = false;
};
/**
* Signaling
* Sends signals to user with passed commands and params
* @param userID
* @param params
*/
MobileWebrtc.prototype.callSignaling = function (userID, params)
{
this.ajaxCall("CALL_SIGNALING", {
'COMMAND': 'signaling',
'CHAT_ID': this.callChatId,
'RECIPIENT_ID': userID,
'PEER': JSON.stringify(params)
});
};
/**
* Send command to chat with chatId
*
* Available commands and them meaning:
* <pre>
* busy - you are already have the conversation with someone and can't pick up the phone
* busy_self - informs the partner that you already have the conversation with him
* ready - informs the partner you have front camera and microphone, local video stream is created and you are ready for the peerdata exchange
* wait - informs the partner to keep waiting for the answer for the 30 seconds
* decline - informs the partner that you've declined his incoming call or hung up while the call was active
* </pre>
* @param chatId
* @param command
* @param params
* @param async
*/
MobileWebrtc.prototype.callCommand = function (chatId, command, params, async)
{
chatId = parseInt(chatId);
params = typeof(params) == 'object' ? params : {};
if (chatId > 0)
{
this.ajaxCall(
"CALL_SHARED",
{'COMMAND': command, 'CHAT_ID': chatId, 'RECIPIENT_ID': this.callUserId, 'PARAMS': JSON.stringify(params)}
);
}
};
/**
* Finishes the conversation with closing UI
*/
MobileWebrtc.prototype.finishDialog = function ()
{
webrtc.UI.close();
};
/**
* Handles peer data signals
*
* @param userId
* @param peerData
*/
MobileWebrtc.prototype.signalingPeerData = function (userId, peerData)
{
var signal = JSON.parse(peerData);
if (signal.type === 'offer')
{
this.remoteSessionDescription = signal["sdp"];
webrtc.createPeerConnection();
}
else if (signal.type === 'answer')
{
webrtc.setRemoteDescription(signal);
}
else if (signal.type === 'candidate')
{
if (this.peerConnectionInited)
{
webrtc.addIceCandidates(signal.candidates);
}
else {
for (var i = 0; i < signal.candidates.length; i++)
this.iceCandidates.push(signal.candidates[i]);
}
}
};
/**
* @param reqParam - request param for the ajax request
* @param reqData - post data
* @param onfailure - failure callback function
* @param onsuccess - success callback function
*/
MobileWebrtc.prototype.ajaxCall = function (reqParam, reqData, onsuccess, onfailure)
{
var data = reqData;
data["MOBILE"] = "Y";
data["IS_MOBILE"] = "Y";
data["IM_CALL"] = "Y";
data["IM_AJAX_CALL"] = "Y";
data["sessid"] = BX.bitrix_sessid();
BX.ajax({
url: this.signalingLink + reqParam,
method: 'POST',
dataType: 'json',
timeout: 30,
async: true,
data: data,
onsuccess: onsuccess,
onfailure: onfailure
});
};
/**
* Returns absolute diff between incoming date (in UTC) and local date
* @returns {number}
*/
MobileWebrtc.prototype.getUTCOffset = function ()
{
return this.utcOffest * 1000;
};
MobileWebrtc.prototype.getTimeDiff = function (utcDate)
{
var localTimestamp = (new Date).getTime() + this.getUTCOffset();
var incomingTimestamp = Date.parse(utcDate);
return Math.abs((localTimestamp - incomingTimestamp) / 1000);
};
MobileWebrtc.prototype.timesUp = function (utcDate)
{
return ((Math.abs((new Date).getTime() + this.getUTCOffset() - utcDate) / 1000) >= this.eventTimeRange);
};
MobileWebrtc.prototype.onDecline = function (params)
{
this.callCommand(this.callChatId, 'decline', {
"ACTIVE": (this.callActive) ? "Y" : "N",
"INITIATOR": (this.initiator) ? "Y" : "N"
});
this.resetState();
};
MobileWebrtc.prototype.onAnswer = function (params)
{
webrtc.UI.show(
webrtc.UI.state.CONVERSATION
);
webrtc.getUserMedia({video: params.video});
this.waitTimeout = false;
this.callToGroup = false;
this.callChatId = params.chatId;
this.callUserId = params.senderId;
this.callActive = true;
this.initiator = false;
this.ajaxCall(
"CALL_ANSWER",
{
'COMMAND': 'answer',
'CHAT_ID': this.callChatId,
'CALL_TO_GROUP': this.callToGroup ? 'Y' : 'N',
'RECIPIENT_ID': this.callUserId
}
);
};
MobileWebrtc.prototype.onCallback = function ()
{
if (this.callBackUserId > 0)
this.callInvite(this.callBackUserId);
};
MobileWebrtc.prototype.onClose = function ()
{
this.callBackUserId = 0;
this.resetState();
};
MobileWebrtc.prototype.onDisconnect = function ()
{
this.peerConnectionInited = false;
//send reconnect
};
MobileWebrtc.prototype.onIceCandidateDiscovered = function (params)
{
this.iceCandidatesToSend.push({
type: 'candidate',
label: params.candidate.sdpMLineIndex,
id: params.candidate.sdpMid,
candidate: params.candidate.candidate
});
clearTimeout(this.iceCandidateTimeout);
this.iceCandidateTimeout = setTimeout(BX.delegate(function ()
{
if (this.iceCandidatesToSend.length === 0)
return false;
this.onIceCandidate(this.callUserId, {'type': 'candidate', 'candidates': this.iceCandidatesToSend});
this.iceCandidatesToSend = [];
}, this), 250);
};
MobileWebrtc.prototype.onPeerConnectionCreated = function ()
{
this.peerConnectionInited = true;
if (this.initiator)
{
webrtc.createOffer();
}
else {
webrtc.createAnswer({
"sdp": this.remoteSessionDescription
});
}
};
MobileWebrtc.prototype.onIceCandidate = function (userID, candidates)
{
this.callSignaling(userID, candidates);
};
MobileWebrtc.prototype.onIceConnectionStateChanged = function (params)
{
//TODO to do something
};
MobileWebrtc.prototype.onIceGatheringStateChanged = function (params)
{
//TODO to do something
};
MobileWebrtc.prototype.onSignalingStateChanged = function (params)
{
//TODO to do something
};
MobileWebrtc.prototype.onLocalSessionDescriptionCreated = function (params)
{
this.sessionDescription = params;
if (this.iceCandidates.length > 0)
{
webrtc.addIceCandidates(this.iceCandidates);
this.iceCandidates = [];
}
this.callSignaling(this.callUserId, this.sessionDescription);
};
MobileWebrtc.prototype.onUserMediaSuccess = function (params)
{
webrtc.UI.showLocalVideo();
this.connected[this.getUserId()] = true;
this.callCommand(this.callChatId, "ready");
if (this.connected[this.callUserId] && this.initiator)
{
webrtc.createPeerConnection();
}
};
MobileWebrtc.prototype.onError = function (errorData)
{
//TODO handle error
this.resetState();
};
window.mwebrtc = new MobileWebrtc();
BX.addCustomEvent("onPullEvent-im", BX.proxy(function (command, params)
{
/**
* If the call ringing was started 30 sec ago
* it too late to pick up the phone
* @type {boolean}
*/
var isTooLate = this.getTimeDiff(params.SERVER_TIME) >= this.eventTimeRange;
if (command == 'call')
{
if (params.command == 'ready')
{
this.connected[params.senderId] = true;
if (this.connected[this.getUserId()] && this.initiator == true)
{
webrtc.createPeerConnection();
}
}
else if (params.command == 'decline' || params.command == 'end_call')
{
if (this.callInit)
{
if (this.callChatId == params.chatId)
{
if (this.initiator && !this.connected[this.callUserId])
{
this.callBackUserId = this.callUserId;
webrtc.UI.show(
webrtc.UI.state.FAIL_CALL,
{
'message': BX.message("MOBILEAPP_CALL_DECLINE")
}
);
}
else {
webrtc.UI.close();
}
this.resetState()
}
}
else if (this.delayedIncomingCall.chatId == params.chatId)
{
this.clearDelayedCallData();
}
}
else if (params.command == 'end_call')
{
if ((this.delayedIncomingCall.chatId && this.delayedIncomingCall.chatId == params.chatId))
{
if (this.delayedIncomingCall.chatId == params.chatId)
{
clearTimeout(this.incomingCallTimeOutId);
this.incomingCallTimeOutId = null;
this.delayedIncomingCall = {};
}
}
}
else if (params.command == 'waitTimeout')
{
if (this.callChatId == params.chatId)
{
this.resetState();
this.finishDialog();
}
}
else if (!isTooLate && (params.command == 'invite' || params.command == 'invite_join'))
{
if(params.callToGroup)
{
console.log("Call to group");
return;
}
if (!this.callInit)
{
if (this.incomingCallTimeOutId == null)
{
this.delayedIncomingCall = params;
this.incomingCallTimeOutId = setTimeout(BX.proxy(function ()
{
this.showIncomingCall(this.delayedIncomingCall);
this.delayedIncomingCall = {};
this.incomingCallTimeOutId = null;
}, this), this.incomingCallTimeOut * 1000);
}
}
else if (params.command == 'invite')
{
if (this.callChatId == params.chatId)
{
this.callCommand(params.chatId, 'busy_self');
}
else {
this.ajaxCall("CALL_BUSY", {
'COMMAND': 'busy',
'CHAT_ID': params.chatId,
'RECIPIENT_ID': params.senderId,
'VIDEO': params.video ? 'Y' : 'N'
});
}
}
else if (this.initiator && this.callChatId == params.chatId && !this.callActive)
{
this.onAnswer(params);
}
}
else if (params.command == 'answer' && this.initiator == true)
{
if (!this.isConversationUIReady)
{
var handler = function ()
{
BX.onCustomEvent("onPullEvent-im", [command, params]);
BX.removeCustomEvent("onMobileRTCReadyToConversation", handler);
};
BX.addCustomEvent("onMobileRTCReadyToConversation", handler);
return;
}
if (this.callInit)
{
this.initiator = true;
this.callActive = true;
webrtc.UI.show(
webrtc.UI.state.CONVERSATION
);
if (typeof params.video == "undefined")
{
params.video = this.video;
}
webrtc.getUserMedia({video: params.video});
}
}
else if (params.command == 'decline_self' && this.callChatId == params.chatId || params.command == 'answer_self' && !this.callActive)
{
if (this.delayedIncomingCall.chatId == params.chatId)
{
this.clearDelayedCallData();
}
this.resetState();
this.finishDialog();
}
else if (this.callInit && this.callChatId == params.chatId)
{
if (params.command == 'signaling' && this.connected[this.getUserId()])
{
if (this.callInit && this.callChatId == params.chatId)
this.signalingPeerData(params.senderId, params.peer);
}
else if (params.command == 'busy')
{
if (this.callInit && this.callChatId == params.chatId)
{
this.callBackUserId = this.callUserId;
webrtc.UI.show(
webrtc.UI.state.FAIL_CALL,
{
'message': BX.message("MOBILEAPP_CALL_BUSY")
}
);
this.resetState();
}
}
else if (params.command == 'errorAccess')
{
if (this.callInit && this.callChatId == params.chatId)
{
this.callBackUserId = this.callUserId;
webrtc.UI.show(
webrtc.UI.state.FAIL_CALL,
{
'message': BX.message('MOBILEAPP_CALL_NO_ACCESS')
}
);
this.callInit = false;
}
}
else if (params.command == 'reconnect')
{
this.initiator = false;
webrtc.onReconnect();
}
}
}
}, mwebrtc));