/*-----------------------------------------------------------------------------------------------*/ /* signaling.h */ /* copyright (c) innovaphone 2020 */ /* */ /*-----------------------------------------------------------------------------------------------*/ #ifndef SIGNALING_H #define SIGNALING_H #define SIG_CALL_STATE_SETUP 1 #define SIG_CALL_STATE_SETUP_ACK 2 #define SIG_CALL_STATE_CALL_PROC 3 #define SIG_CALL_STATE_ALERT 4 #define SIG_CALL_STATE_CONN 5 #define SIG_CALL_STATE_DISC_SENT 6 #define SIG_CALL_STATE_DISC_RCVD 7 #define SIG_CALL_STATE_PARKED 8 #define SIG_CALL_STATE_OUTG 0x80 #define SIG_CALL_STATE_HOLD 0x100 #define SIG_CALL_STATE_HELD 0x200 #define SIG_CALL_STATE_CALL_WAITING 0x400 #define MEDIA_CMD_NONE 0 #define MEDIA_CMD_SELECT 1 #define MEDIA_CMD_PROPOSAL 2 #define MEDIA_CMD_REQUEST 3 #define MEDIA_CMD_CLOSE 4 #define MEDIA_CMD_INFO 5 #define FTY_REMOTE_CONTROL_REC_ON 8 #define FTY_REMOTE_CONTROL_REC_OFF 9 #define FTY_REMOTE_CONTROL_3PTY_ON 10 #define FTY_REMOTE_CONTROL_MIC_ON 14 #define FTY_REMOTE_CONTROL_MIC_OFF 15 #define FTY_REMOTE_CONTROL_ADD_VIDEO 42 #define FTY_REMOTE_CONTROL_REM_VIDEO 43 #define FTY_REMOTE_CONTROL_START_CAMERA 44 #define FTY_REMOTE_CONTROL_STOP_CAMERA 45 #define FTY_REMOTE_CONTROL_ADD_APPSHARING 46 #define FTY_REMOTE_CONTROL_REM_APPSHARING 47 #define FTY_REMOTE_CONTROL_ALLOW_VIDEO 48 #define Q931_CAUSE_NormalCallClearing 16 #define Q931_CAUSE_UserBusy 17 #define Q931_CAUSE_NonSelectedUserClearing 26 #define Q931_CAUSE_NetworkOutOfOrder 38 #define AUTOHANGUP_OFF 1 #define AUTOHANGUP_ALLCALLS 2 #define AUTOHANGUP_CONNECTEDCALLS 3 #define HOOK_DEVICE_WAITING 1 #define HOOK_DEVICE_ACQUIRE 2 #define HOOK_DEVICE_DENIED 3 #define HOOK_DEVICE_NOT_FOUND 4 /*-----------------------------------------------------------------------------------------------*/ class JsonIo { json_io * j; public: JsonIo(char * buffer) { j = new json_io(buffer); } ~JsonIo() { delete j; } operator json_io &() { return *j; } word add(byte type, byte flags, word base, const char* name, const char* info, dword len = 0xffffffff) { return j->add(type, flags, base, name, info, len); } word add_object(word base, const char * name) { return j->add_object(base, name); } word add_array(word base, const char * name) { return j->add_array(base, name); } void add_string(word base, const char * name, const char * value, dword len=0xffffffff) { j->add_string(base, name, value, len); } void add_string(word base, const char * name, const word * value, dword len, char * & tmp) { j->add_string(base, name, value, len, tmp); } void add_string(word base, const char * name, const word * value, char * & tmp) { j->add_string(base, name, value, 0xffffffff, tmp); } void add_replace_string(word base, const char * name, const char * value, dword len=0xffffffff) { j->add_replace_string(base, name, value, len); } void add_json(word base, const char * name, const char * value, dword len=0xffffffff) { j->add_json(base, name, value, len); } void add_int(word base, const char * name, int c, char * & tmp) { j->add_int(base, name, c, tmp); } void add_unsigned(word base, const char * name, dword c, char * & tmp) { j->add_unsigned(base, name, c, tmp); } void add_long64(word base, const char * name, long64 c, char * & tmp) { j->add_long64(base, name, c, tmp); } void add_ulong64(word base, const char * name, ulong64 c, char * & tmp) { j->add_ulong64(base, name, c, tmp); } void add_printf(word base, const char * name, char * & tmp, const char * format, ...) { va_list ap; va_start(ap,format); j->add_printfv(base, name, tmp, format, ap); va_end(ap); } void add_printfv(word base, const char * name, char * & tmp, const char * format, va_list ap) { j->add_printfv(base, name, tmp, format, ap); } void add_hexstring(word base, const char * name, const byte * hex, word hex_len, char * & tmp) { j->add_hexstring(base, name, hex, hex_len, tmp); } void add_bool(word base, const char * name, bool value) { j->add_bool(base, name, value); } void add_null(word base, const char * name) { j->add_null(base, name); } }; /*-----------------------------------------------------------------------------------------------*/ class SignalingService : public AppService, public ISignalingService { void AppServiceApps(istd::list * appList) override; void IAppStart(AppInstanceArgs * args) override; class ISignaling * ICreateInstance(class USignaling * user, AppInstanceArgs * args) override; public: SignalingService(class IIoMux * const iomux, class ISocketProvider * localSocketProvider, class ISocketProvider * tcpSocketProvider, class ISocketProvider * tlsSocketProvider, IWebserverPluginProvider * const webserverPluginProvider, class IAppWebsocketClientProvider * appWebsocketClientProvider, IMediaProvider * mediaProvider, SignalingMediaConfig * mediaConfig, IAudioIo * audioIo, IRingerIo * ringerIo, IVideoIo * videoIo, IRemoteServices * remoteServices, AppServiceArgs * args); ~SignalingService(); class AppInstance * CreateInstance(AppInstanceArgs * args) override; class ISignaling* GetISignalingInstance() override { return this->signaling; }; class IIoMux * iomux; class ISocketProvider * localSocketProvider; class ISocketProvider * tcpSocketProvider; class ISocketProvider * tlsSocketProvider; class IWebserverPluginProvider * webserverPluginProvider; IAppWebsocketClientProvider * appWebsocketClientProvider; IMediaProvider * mediaProvider; SignalingMediaConfig * mediaConfig; IAudioIo * audioIo; IRingerIo * ringerIo; IVideoIo * videoIo; IRemoteServices * remoteServices; class ISignaling * signaling; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingRcc :public UJsonApiContext { class JsonApi * CreateJsonApi(class IJsonApiConnection * connection, class json_io & msg, word base) override; class JsonApi * JsonApiRequested(class IJsonApiConnection * connection) override; const char * Name() { return "RCC"; }; public: SignalingRcc(class JsonApiContext * context); virtual class SignalingRegistration * GetRegistration() = 0; virtual void AddRegistrationMonitor(class SignalingRegistrationMonitor * monitor) = 0; virtual void RemoveRegistrationMonitor(class SignalingRegistrationMonitor * monitor) = 0; virtual void MonitorSync(class SignalingRegistrationMonitor * monitor) = 0; virtual class IAudioIo * GetAudioIo() = 0; virtual class IRingerIo * GetRingerIo() = 0; virtual class IVideoIo * GetVideoIo() = 0; virtual class IMediaProvider * GetMediaProvider() = 0; virtual void RccSessionOpened() = 0; virtual void RccSessionClosed() = 0; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingDialingLocation { public: SignalingDialingLocation() { zeroize(); } ~SignalingDialingLocation() { cleanup(); } void zeroize(); void cleanup(); void read(class json_io & msg, word base); void write(class SignalingRCCMessage * msg); char * prefixIntl, *prefixNtl, *prefixSubs, *country, *area, *subscriber; unsigned maxIntern; unsigned tones; }; /*-----------------------------------------------------------------------------------------------*/ class Signaling : public ISignaling, public USelectDeviceIo, public UWebserverPlugin, public AppUpdates, public JsonApiContext, public SignalingRcc, public UHookDevice { class IRTPTP * SetRTPTP4(class URTPTP * user, const char * sip, unsigned timeout); class IRTPTP * SetRTPTP6(class URTPTP * user, const char * sip, unsigned timeout); void WebserverPluginWebsocketListenResult(IWebserverPlugin * plugin, const char * path, const char * registeredPathForRequest, const char * host) override; void WebserverPluginClose(IWebserverPlugin * plugin, wsp_close_reason_t reason, bool lastUser); void Stop() override; void AppInstanceShutdownTimeout() override; bool stopping; public: Signaling(IIoMux * const iomux, class USignaling * user, SignalingService * service, AppInstanceArgs * args); ~Signaling(); void AddClientMonitor(class SignalingClientMonitor * monitor); void RemoveClientMonitor(class SignalingClientMonitor * monitor); void ClientState(bool up, bool localInit); class SignalingRegistration * GetRegistration() override { return registration; }; void AddRegistrationMonitor(class SignalingRegistrationMonitor * monitor); void RemoveRegistrationMonitor(class SignalingRegistrationMonitor * monitor); void MonitorSync(class SignalingRegistrationMonitor * monitor); class IAudioIo * GetAudioIo() override; class IRingerIo * GetRingerIo() override; class IVideoIo * GetVideoIo() override; class IMediaProvider * GetMediaProvider() override; const char * AppendSipDomain(const char * sip, char * buffer, unsigned length); void RccSessionOpened(); void RccSessionClosed(); void RegisterToAltPbx(); void RegisterToRedirectUrl(const char* url); void RegistrationState(bool up); void CallAdded(class SignalingCall * call, class SignalingRegistrationMonitor * exclude); void UnknownCallMessage(const char * type, class json_io & msg, word base); void RTPTPState(class IRTPTP * rtptp, bool up); void SetClient(const char* url, const char* sec, const char* phys, const char* app, const char* usr, const char* pwd, const char * domain, const char * appdomain, unsigned timeout, bool localInit) override; void CloseClient() override; void SetRegistration(const char* hw, const char* phys, unsigned timeout) override; void RegistrationCheck() override; int NumActiveCalls() override; void LookupInfo(const char * src, class json_io& msg, word base) override; void StartRinging(const char* uuid) override; void AddSignalingSession(class SignalingSession * session); void RemoveSignalingSession(class SignalingSession* session); void PhoneStartCallAction(const char * uuid, const char * number, const char * name, bool video, bool sendingComplete) override; void PhoneAnswerCallAction(const char * uuid) override; void PhoneEndCallAction(const char * uuid, int callError) override; void PhoneDialNumber(const char *number, const char *name, StartCallVideoMode videoMode, bool sendingComplete) override; void PhoneHoldCallAction(const char * uuid) override; void PhoneRetrieveCallAction(const char * uuid) override; void PhoneSetMutedCallAction(const char * uuid, bool muted) override; void PhoneAudioRouteChanged(const char * uuid, const char * deviceId) override; void PhonePlayDtmfCallAction(const char * uuid, const char * digits) override; void PhoneStartRinging(const char * uuid) override; void PhoneCheckIncomingCall(const char * uuid) override; class SignalingCall * FindCallByConfId(const char * uuid); class SignalingCall * FindCallByRemoteNum(const char* num); void SelectAudioDevice(class IAudioIo * audioIo, const char * app, const char * deviceId, int type) override; void SelectVideoDevice(const char* app, const char* deviceId) override; void SelectRingerDevice(class IRingerIo* ringerIo, const char* app, const char* deviceId) override; void AudioDeviceList() override; void VideoDeviceList() override; void RingerDeviceList() override; void RingtoneList() override; void ChangeVideoDevice(const char* app, const char* deviceId) override; void ChangeAudioDevice(class IAudioIo* audioIo, const char* app, const char* deviceId, int type) override; void StartHookDevice(const char* deviceId, byte key, byte callId, const char* number, const char* name) override; void SendHookKey(const char* deviceId, byte key, byte callId, const char* number, const char* name); void SaveCredentials(const char* url, const char* sec, const char* phys, const char* app, const char* usr, const char* pwd, const char * domain, const char * appdomain, unsigned timeout); void SaveRegistration(const char* hw, const char* phys, unsigned timeout); void RegistrationDeleted(class SignalingRegistration * registration) { if (registration == this->registration) this->registration = NULL; }; class IIoMux * GetIoMux() { return AppUpdates::GetIoMux(); }; class ISocketProvider * GetTcpSocketProvider() { return this->service->tcpSocketProvider; }; class ISocketProvider * GetTlsSocketProvider() { return this->service->tlsSocketProvider; }; const char * GetWorkingPath() { return this->workingPath; }; void SetWorkingPath(const char * path) override { this->workingPath = _strdup(path); }; const char * GetRingerDevice() { return this->ringerDeviceId; }; const char * GetAudioDevice() { return this->changedAudioDeviceId ? this->changedAudioDeviceId : this->defaultAudioDeviceId; }; void SetNoVpnAddresses(bool noVpnAddresses) override; void SetRecordingParameters(const char* url, bool pbx, bool forceUrl, bool isRecordingByDefaultOn, bool forceDefaultOn, bool recordExternalOnly, bool forceExternalOnly) override; void SetSignalingUser(class USignaling* user) override; // UHookDevice void HookDeviceMsg(IAudioIo* audioIo, const char* deviceId, const char* msg) override; void HookKeyReceived(IAudioIo* audioIo, const char* deviceId, byte key) override; void IncomingCall(); class IInstanceLog * log; class USignaling * user; char* url; char* sec; char* phys; char* app; char* usr; char* userPwd; char* domain; char* appdomain; unsigned timeout; bool localInit; char * pwd; class SignalingService * service; class IWebserverPlugin * webserverPlugin; class AppUpdatesFilters filters; class SignalingClient * client; class SignalingRegistration * registration; class SignalingRTPTP * rtptp4; class SignalingRTPTP * rtptp6; class istd::list sessions; class istd::list clientMonitors; class istd::list registrationMonitors; char * defaultAudioDeviceId; char * changedAudioDeviceId; char * ringerDeviceId; char * ringtoneId; char * videoDeviceId; char * testAudioDeviceId; char * testRingerDeviceId; char * testVideoDeviceId; char * localIpAddr; int hookDeviceState; bool videoLicense; bool recordingLicense; bool startVideo; bool callWaiting; bool onhookTransfer; bool clir; int uiRunning; int autoHangup; bool recordingUrlSet; class VoipEndpoint * lastStartCallDest; char * workingPath; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingSession : public AppUpdatesSession { void ResponseSent(); void AppWebsocketClosed(); char * AppWebsocketPassword() { return signaling->pwd; }; bool AppWebsocketConnectComplete(class json_io & msg, word info); void AppWebsocketMessage(class json_io & msg, word base, const char * mt, const char * src); class Signaling * signaling; char * currentSrc; public: SignalingSession(class Signaling * signaling); }; class SignalingSessionHelper :public istd::listElement { public: SignalingSessionHelper(class SignalingSession* session) { this->session = session; } ~SignalingSessionHelper() {}; class SignalingSession* session; }; enum SignalingUpdateType { SignalingClientInfo, SignalingRegistrationInfo, SignalingRTPTP4Info, SignalingRTPTP6Info }; /*-----------------------------------------------------------------------------------------------*/ class SignalingUpdate : public AppUpdate { public: SignalingUpdate(enum SignalingUpdateType type, const char * mt, const char * info, class AppUpdatesFilters & filters, const char * sip = 0); ~SignalingUpdate(); enum SignalingUpdateType type; const char * mt; char * info; }; class SignalingUpdatesFilter : public AppUpdatesFilter { bool Test(SignalingUpdate * update) override; void Send(SignalingUpdate * update) override; public: SignalingUpdatesFilter(enum SignalingUpdateType type, AppUpdatesFilters & filters, class AppUpdatesSession * session, const char * src, const char * sip); ~SignalingUpdatesFilter(); enum SignalingUpdateType type; char * src; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingClient : public UAppWebsocketClient, public UTimer { void AppWebsocketClientConnectComplete(class IAppWebsocketClient * appWebsocketClient); void AppWebsocketClientMessage(class IAppWebsocketClient * appWebsocketClient, class json_io & msg, word base, const char * mt, const char * src); void AppWebsocketClientSendResult(class IAppWebsocketClient * appWebsocketClient); void AppWebsocketClientClosed(class IAppWebsocketClient * appWebsocketClient); void TimerOnTimeout(ITimer * timer) override; void DeleteCalls(); class Signaling * signaling; bool usePrimaryUrl; bool updateCredentials; char * url; char * sec; char * redirectUrl; char * curPbx; char * phys; char * app; char * usr; char * pwd; char * appdomain; unsigned clientTimeout; unsigned timeout; bool localInit; bool up; class ITimer retry; class ITimer tryAltPbx; bool clearRegistration; bool fastConnect; public: SignalingClient(class Signaling * signaling); virtual ~SignalingClient(); void Update(const char * url, const char * sec, const char * phys, const char * app, const char * usr, const char * pwd, const char * domain, const char * appdomain, unsigned timeout, bool localInit); void Sync(class json_io & msg, word base); void RegisterToAltPbx(); void RegisterToRedirectUrl(const char* url); void RegistrationState(bool up); IAppWebsocketClient * websocket; char * domain; void Close(); bool IsClientUp() { return this->up; }; void ClearRegistration() { this->clearRegistration = true; }; void RegistrationCheck(); }; class SignalingClientMonitor : public istd::listElement { public: SignalingClientMonitor(class Signaling * signaling, const char * src); void MessageSend(class json_io & msg, word base, char * buffer); virtual void ClientState(bool up) = 0; virtual void ClientMessage(class json_io & msg, word base, const char * mt, const char * src) = 0; class Signaling * signaling; char * src; }; class SignalingMessage : public JsonIo { public: SignalingMessage(const char * mt, const char * src, void * sb, void * tmp); void Send(class SignalingSession * session); char * sb; char * tmp; word base; }; class SignalingInboundVideoCall : public istd::listElement { public: SignalingInboundVideoCall(int id, const char * mode) { this->id = id; this->mode = _strdup(mode); } ~SignalingInboundVideoCall() { free((char *)this->mode); } int id; const char * mode; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingRegistration : public SignalingClientMonitor, public UTimer { void ClientState(bool up) override; void ClientMessage(class json_io & msg, word base, const char * mt, const char * src) override; void ControlCall(class json_io& msg, word base, const char* mt, const char* src); void Register(); void TimerOnTimeout(ITimer * timer) override; char * hw; char* phys; unsigned hwTimeout; unsigned timeout; class ITimer retry; istd::list inboundVideoCalls; public: SignalingRegistration(class Signaling * signaling); ~SignalingRegistration(); void Update(const char * hw, const char* phys, unsigned timeout); void Sync(class json_io & msg, word base); void UnRegister(); const char * GetHwId() { return this->hw; }; class SignalingCall * FindCallByState(word state); void StateChanged(SignalingCall* call); const char * AddExternalLinePrefix(const char * number, char * buffer, unsigned length); unsigned ExternalLinePrefixOffset(const char * number); bool IsExternalCall(const char * number); bool clientUp; bool registered; class SignalingDialingLocation dialingLocation; char* err; class btree * calls; class SignalingCall * activePhoneCall; class SignalingRccSession * diversionSession; bool presenceCall; bool dnd; }; enum CallType { CallTypeVoice, CallTypeData }; class SignalingRegistrationMonitor : public istd::listElement { public: SignalingRegistrationMonitor(enum CallType callType); virtual void RegistrationState(bool up) = 0; virtual class SignalingCallMonitor * CallAdded(class SignalingCall * call) { return NULL; }; virtual void UnknownCallMessage(const char * type, class json_io & msg, word base) {}; enum CallType callType; }; class SignalingRegMessage : public JsonIo { public: SignalingRegMessage(const char * mt, const char * src, void * sb); void Send(class SignalingRegistration * registration); char * sb; word base; }; class VoipEndpoint { public: VoipEndpoint(const char * num, const char * sip, const char * dn); ~VoipEndpoint() { Clear(); } void SetNum(const char * num); void AddtoNum(const char * num); void SetSip(const char * sip); void SetDn(const char * dn); void SetRestricted(bool restricted) { this->restricted = restricted; } void Clear(); char * num; char * sip; char * dn; bool restricted; }; class ConferenceInfo { void zeroize(); public: ConferenceInfo() { zeroize(); } ~ConferenceInfo() { cleanup(); } void cleanup(); void read(class json_io& msg, word base); void write(class json_io& msg, word base, char*& tmp); char* reason; struct { unsigned id; char* name, * inRoomState, * activeSpeaker, * muted, * mutedByMod, * mutedByUser, * videoOffByMod, * videoOffByUser, * appSharing, * hand; struct { char* flags; char* num; char* sip; } remote; struct { unsigned id; unsigned bitrate; } videoChannels[10]; } participant; }; class ChatMessage { void zeroize(); public: ChatMessage() { zeroize(); } ~ChatMessage() { cleanup(); } void cleanup(); void read(class json_io& msg, word base); void write(class json_io& msg, word base, char*& tmp); char* type, * sender, * sender_dn, * data, * guid, * mime; unsigned time; }; typedef struct { int loss; int jitter; int roundTrip; } stats; class SignalingCallMonitor; class SignalingCall : public btree, public UMedia, public UMediaIoChannel, public UTimer { friend class SignalingRegistration; int btree_compare(void * key) { return (int)(intp)key - call; }; int btree_compare(class btree * b) { return ((class SignalingCall *)b)->call - call; }; void MediaInitializeComplete(IMedia * const media, class MediaConfig *localMediaConfig) override; void MediaConnectResult(IMedia * const media, const char * error) override; void MediaRtpSendResult(IMedia * const media) override {}; void MediaSctpSendResult(IMedia * const media) override {}; void MediaIoSendFIR() override; void MediaRtpRecvResult(IMedia * const media, void * buf, size_t len, dword timestamp, short sequenceNumberDiff, bool marker); void MediaSctpRecvResult(IMedia * const media, void * buf, size_t len) override {}; void MediaSctpRecvAck(IMedia * const media, unsigned num) override {}; void MediaCloseComplete(IMedia * const media) override; void MediaEventReceived(IMedia * const media, enum MediaEndpointEvent event, void * ctx) override; void MediaRtpRecv(IMedia * const media, const char * src_addr, word src_port, dword ssrc, word pt) override; void MediaRtpDtmfNearStart(char digit) override; void MediaRtpDtmfNear(char digit) override; enum AudioCoder AvailableAudioCoder(unsigned coderNumber) override; unsigned AvailableAudioCoderCount() override; enum VideoCoder AvailableVideoCoder(unsigned coderNumber) override; unsigned AvailableVideoCoderCount() override; void RecordingStopped(const char * error) override; void RecordingStarted() override; void MediaIoRtpSend(const void * buf, size_t len, dword timestamp, enum MediaType mediaType, bool isConference) override; void MediaIoRtpForward(const void * buf, size_t len, dword timestamp, short sequenceNumberDiff, bool marker, enum MediaType mediaType) override; void MediaIoRtcpSend(const void * buf, size_t len, enum MediaType mediaType) override; void MediaIoSctpSend(const void * buf, size_t len, unsigned num) override; void MediaIoCloseComplete(class IMediaIoChannel * const mediaIoChannel) override; void TimerOnTimeout(ITimer * timer) override; void SendSetup(); void SendInfo(const char * num, const char * sip); void SendAlert(); void SendConn(); void SendChannels(); void SendRel(); int SelectCoder(class MediaConfig * remoteMediaConfig, class MediaConfig * localMediaConfig); void SendLocalMedia(class json_io & json, word base, char * & tmp); void RecvRemoteMedia(class json_io & json, word base); void GenerateIceCredentials(class IceCandidates* ice); char* GenerateRandomString(int len); void MediaInitialized(); void MediaInitialize(enum MediaType mediaType); void DTMF(const char* dtmf, bool feedback = false); class SignalingRegistration * registration; class IMedia* media, * media2; class MediaConfig * localAudioConfig, * localVideoConfig; class MediaConfig * remoteAudioConfig, * remoteVideoConfig; unsigned remoteMediaCmd; byte localDTMF; byte remoteDTMF; bool callWaiting; byte initializing; bool isMediaInitialized; byte connecting; bool noAudioIceCandidates; bool noVideoIceCandidates; class IAudioIoChannel * audioIoChannel; class IVideoIoChannel * videoIoChannel; class IMedia * mediaClosing; class IMedia * media2Closing; class IVideoIoChannel * videoIoChannelClosing; class IAudioIo * audioIo; class IVideoIo * videoIo; class IRingerIo * ringerIo; class IMediaProvider * mediaProvider; char * audioDeviceId; char * videoDeviceId; char * ringerDeviceId; char * ringertoneIdent; class URTPTP * rtptp; class SignalingRegistrationMonitor * exclude; bool deleting; byte hookState; bool audioMediaConnected; unsigned allocatedTones; struct AudioIoDualTone* tones; stats tx; stats rx; class SignalingCall * ctIdentify; class SignalingCall * ctInitiate; bool FindFty(class json_io& msg, word base, const char* type); public: SignalingCall(class SignalingRegistration * registration, enum CallType callType, int call, const char * num, const char * sip, const char * dn, bool sendingComplete); ~SignalingCall(); void StartCall(class IAudioIo * audioIo, class IVideoIo * videoIo, class URTPTP * rtptp, class SignalingRegistrationMonitor * exclude); void ClearCall(word cause = 0); void DoStartCall(); void ConnectCall(class IAudioIo * audioIo, class IVideoIo * videoIo); void AbortTone(); void Rc(unsigned rc); void Info(const char * num, const char * sip); void SendDTMF(const char * dtmf, bool feedback = false); void UUI(unsigned pd, const char * uui); void StartTransfer(SignalingCall * to); void StartRedirect(const char * num, const char * sip); void StartReroute(const char * num, const char * sip); void Hold(); void Retrieve(); void Park(const char * parked_to_num, const char * parked_to_sip); void Mute(); void AudioRouteChanged(); void RccSessionOpened(); void RccSessionClosed(); void StartRinging(); void StopRinging(); void HookDeviceAcquired(); void HookDeviceDenied(); void HookDeviceNotFound(); void Delete(); void Message(const char * type, class json_io & msg, word base); void MonitorXmit(const char * type, class json_io & msg, word base); void MonitorRecv(const char * type, class json_io & msg, word base); void SetAudioIoChannel(IAudioIoChannel * channel){audioIoChannel = channel;} void ChangeAudioDevice(const char* deviceId); void ChangeVideoDevice(const char* deviceId); void ChangeState(word state); void RegistrationState(bool up); void RequestStartCall(); void ResetRegistration(class SignalingRegistration * registration) { this->registration = registration; }; bool IsCameraOn() { return this->videoDeviceId != NULL; }; const char * getAudioDeviceId() { return audioDeviceId; } void LookupInfo(class json_io& msg, word base); const char* GetConfId(); int call; OS_GUID conf; char * confId; word state; word cause; bool cameraAllowed; bool videoDisabled; bool sendVideoProposal; bool alertPostponedOnHookDevice; bool connPostponed; bool connPostponedOnHookDevice; bool connReceived; bool selectByConn; bool updateHookDevice; enum CallType callType; char* videoDeviceIdBeforeHold; int audioCoder, videoCoder, videoCoderBeforeHold; class VoipEndpoint remote, diverting, originalCalled, transfering; istd::list dtmfs; char * conferenceGuid; const char * conferenceType; // "3pty" or "central" bool multiVideoSupport; bool remoteVideoPriority; bool announce; bool muted; class ConferenceInfo conferenceInfo; class ChatMessage chatMessage; istd::list monitors; ITimer toneEndTimer, autoConnectTimer, mediaInfoInterval, queuedDTMFTimer; unsigned ct_setup_id; int numVideoPackets, numAudioPackets; int lastNumVideoPackets, lastNumAudioPackets; bool videoDataOff; bool audioDataOff; time_t duration; bool clearCall; bool sendingComplete; struct { unsigned id; char* num; char* sip; char* dn; void cleanup() { free(num); free(sip); free(dn); zerioze(); } void zerioze() { id = 0; num = 0; sip = 0; dn = 0; } } fty_ct_initiate; struct { bool isExternal; bool isTrunkRecording; bool isRecordingByDefaultOn; char* recordingError; void cleanup() { free(recordingError); initialize(); } void initialize() { isExternal = false; isTrunkRecording = false; isRecordingByDefaultOn = false; recordingError = 0; } } recordingInfo; }; class QueuedDTMF : public istd::listElement { public: QueuedDTMF(const char * dtmf, bool feedback = false) { this->dtmf = _strdup(dtmf); this->feedback = feedback; } ~QueuedDTMF() { if (this->dtmf) free(this->dtmf); } char * dtmf; bool feedback; }; class SignalingCallMonitor : public istd::listElement { public: SignalingCallMonitor(class SignalingCall * call); virtual ~SignalingCallMonitor(); virtual void MonitorXmit(const char * type, class json_io & msg, word base) = 0; virtual void MonitorRecv(const char * type, class json_io & msg, word base) = 0; virtual void MonitorSync() = 0; class SignalingCall * call; }; class SignalingSigMessage : public JsonIo { public: SignalingSigMessage(int call, const char * type, void * sb, void * tmp); void Send(class SignalingRegistration * registration); char * sb; char * tmp; word base; word sig; }; /*-----------------------------------------------------------------------------------------------*/ #define RCC_TYPE_USER 1 #define RCC_TYPE_CALL 2 #define RCC_TYPE_CALL_INFO 3 class SignalingRccVideoConfCall : public istd::listElement { public: SignalingRccVideoConfCall(const char* confId, int id) { this->confId = _strdup(confId); this->id = id; } ~SignalingRccVideoConfCall() { if (this->confId) free(this->confId); } char* confId; int id; }; class SignalingRccSessionHttpClient : public UHTTPClient, public UTask, public STaskContext { class Signaling * signaling; class SignalingRccSession * rccSession; class IHTTPClient * httpClient; char * url; byte * recvBuffer; class TaskFileWrite * fWrite; bool closing; bool httpOk; bool fileOk; bool firstFProgressReceived; void HTTPClientConnectComplete(IHTTPClient * const httpClient) override; void HTTPClientShutdown(IHTTPClient * const httpClient, http_shutdown_reason_t reason) override; void HTTPClientSendResult(IHTTPClient * const httpClient) override; void HTTPClientRecvResult(IHTTPClient * const httpClient, byte * buffer, size_t len, bool transferComplete) override; void HTTPClientRecvCanceled(IHTTPClient * const httpClient, byte * buffer) override; void HTTPClientRequestComplete(IHTTPClient * const httpClient) override; void TaskComplete(class ITask * const task) override; void TaskFailed(class ITask * const task) override; void TaskProgress(class ITask * const task, dword progress = 0) override; void TryClose(); public: SignalingRccSessionHttpClient(class Signaling * signaling, class SignalingRccSession * rccSession, const char * url); ~SignalingRccSessionHttpClient(); bool Success(); void Close(); }; class SignalingRccSession : public JsonApi, public SignalingRegistrationMonitor { friend class SignalingRCCMessage; const char * Name() { return "RCC"; }; void JsonApiStart(); void Message(class json_io & msg, word base, const char * mt, const char * src); void JsonApiConnectionClosed(); void Version(class json_io & json, word base, const char * src); void DiversionInterrogate(class json_io & json, word base, const char * src); void DiversionActivateDeactivate(class json_io & json, word base, const char * src); void UserInitialize(class json_io & json, word base, const char * src); void UserCall(class json_io & json, word base, const char * src); void UserClear(class json_io & json, word base, const char * src); void UserConnect(class json_io & json, word base, const char * src); void UserRc(class json_io & json, word base, const char * src); void UserInfo(class json_io & json, word base, const char * src); void UserDTMF(class json_io & json, word base, const char * src); void UserUUI(class json_io & json, word base, const char * src); void UserTransfer(class json_io & json, word base, const char * src); void UserRedirect(class json_io & json, word base, const char * src); void UserReroute(class json_io & json, word base, const char * src); void UserHold(class json_io & json, word base, const char * src); void UserRetrieve(class json_io & json, word base, const char * src); void UserPark(class json_io& json, word base, const char* src); void UserOptions(class json_io& json, word base, const char* src); void PbxSignal(class json_io& json, word base, const char* src); void PlaySound(class json_io& json, word base, const char* src); class IJsonApiConnection * connection; char * src; char * userInitializeSrc; bool userInitializeRx; class SignalingRccUser * user; void UserInitializeResult(); void RegistrationState(bool up) override; istd::list videoConfCalls; class SignalingRccSessionHttpClient * httpClient; char webaccessTone[4096]; //PATH_MAX = 4096 bool stopping; public: SignalingRccSession(class SignalingRcc * rcc, class IJsonApiConnection * connection); ~SignalingRccSession(); class SignalingRccUser * FindUser(word handle); class SignalingRccCall * FindCall(word handle); class SignalingRcc * rcc; word lastSessionHandle; class btree * handles; istd::list users; void JsonApiMessage(class json_io& msg, char* buffer) { connection->JsonApiMessage(msg, buffer); } void SignalingRccSessionHttpClientClosed(class SignalingRccSessionHttpClient * httpClient); }; class SignalingRccHandle : public btree { int btree_compare(void * key); int btree_compare(class btree * b); public: SignalingRccHandle(class SignalingRccSession * session, word type); virtual ~SignalingRccHandle(); class SignalingRccSession * session; word type; word handle; }; class SignalingRCCMessage : public JsonIo { public: SignalingRCCMessage(const char * mt, const char * src, class SignalingRccSession * session, void * sb, void * tmp); void Send(); class SignalingRccSession * session; char * sb; char * tmp; word base; word sig; }; class SignalingRccUser : public SignalingRccHandle, public SignalingRegistrationMonitor, public istd::listElement { void RegistrationState(bool up) override; class SignalingCallMonitor * CallAdded(class SignalingCall * call) override; void UnknownCallMessage(const char * type, class json_io & msg, word base) override; public: SignalingRccUser(class SignalingRccSession * session, const char * src); ~SignalingRccUser(); char * src; istd::list calls; }; /*-----------------------------------------------------------------------------------------------*/ class SignalingRccCall : public SignalingRccHandle, public SignalingCallMonitor, public istd::listElement { void MonitorXmit(const char * type, class json_io & msg, word base); void MonitorRecv(const char * type, class json_io & msg, word base); void MonitorSync(); void SendCallInfo(class json_io & msg, word base, char * & tmp); class SignalingRccSession * session; class SignalingRccUser * user; public: SignalingRccCall(SignalingRccSession * session, SignalingRccUser * user, class SignalingCall * call); ~SignalingRccCall(); }; /*-----------------------------------------------------------------------------------------------*/ /* SignalingRTPTP */ /*-----------------------------------------------------------------------------------------------*/ class SignalingRTPTP : public SignalingRegistrationMonitor, public UTimer, public IRTPTP { void RegistrationState(bool up) override; class SignalingCallMonitor * CallAdded(class SignalingCall * call) override { return 0; }; void TimerOnTimeout(ITimer * timer) override; void Send(void * buf, size_t len) override; char * sip; unsigned timeout; class ITimer retry; public: SignalingRTPTP(class Signaling * signaling); ~SignalingRTPTP(); class SignalingRTPTP * Update(class URTPTP * user, const char * sip, unsigned timeout); void Sync(class json_io & msg, word base); void State(bool up); class Signaling * signaling; class URTPTP * user; bool up; class SignalingRTPTPCall * call; }; class SignalingRTPTPCall : public SignalingCallMonitor { class SignalingRTPTP * rtptp; void MonitorXmit(const char * type, class json_io & msg, word base) override; void MonitorRecv(const char * type, class json_io & msg, word base) override; void MonitorSync() override; public: SignalingRTPTPCall(class SignalingRTPTP * rtptp, class SignalingCall * call); ~SignalingRTPTPCall(); }; #endif