415 lines
12 KiB
C#
415 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.IO.Pipes;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
|
|
using Microsoft.Win32;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using C4IT.Logging;
|
|
using C4IT.F4SD.TAPI;
|
|
using static C4IT.Logging.cLogManager;
|
|
|
|
using FasdDesktopUi.Basics;
|
|
|
|
namespace F4SD_PhoneMonitor
|
|
{
|
|
static class Program
|
|
{
|
|
public static string sendPipeName = null;
|
|
public static string listenPipeName = null;
|
|
public static string tapiLine = null;
|
|
public static bool SignalOutgoingCall = false;
|
|
public static string ExternalCallPrefix = "";
|
|
public static bool IsSimulation = false;
|
|
|
|
public static int SendError = 0;
|
|
|
|
public static cCLMgrEvents lmg = null;
|
|
|
|
public static System.Timers.Timer timerPolling = new System.Timers.Timer(100);
|
|
|
|
public static cF4sdPipeServer pipeServer = null;
|
|
|
|
public static bool StopImmediate = false;
|
|
|
|
[STAThread]
|
|
static int Main(string[] args)
|
|
{
|
|
try
|
|
{
|
|
cLogManagerFile.CreateInstance(false, SubFolder: "Logs");
|
|
cLogManager.DefaultLogger.LogAssemblyInfo();
|
|
}
|
|
catch
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
if (args.Length < 3 || args.Length > 6)
|
|
{
|
|
LogEntry("No valid pipe names at command line. Terminating...", LogLevels.Fatal);
|
|
return -1;
|
|
}
|
|
|
|
sendPipeName = args[0];
|
|
listenPipeName = args[1];
|
|
tapiLine = args[2];
|
|
|
|
if (args.Length >= 4)
|
|
ExternalCallPrefix = args[3];
|
|
|
|
if (args.Length >= 5)
|
|
{
|
|
if (args[4] == "1")
|
|
SignalOutgoingCall = true;
|
|
}
|
|
|
|
if (args.Length >= 6)
|
|
{
|
|
if (args[5] == "simulation")
|
|
IsSimulation = true;
|
|
}
|
|
|
|
if (tapiLine.ToLowerInvariant() == "swyxitnative")
|
|
{
|
|
if (!ConnectSwyxit())
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
if (!ConnectTapi(tapiLine))
|
|
{
|
|
System.Environment.Exit(-1);
|
|
}
|
|
}
|
|
|
|
timerPolling.Elapsed += TimerPolling_Elapsed;
|
|
timerPolling.Start();
|
|
|
|
var SessionId = 0;
|
|
try
|
|
{
|
|
SessionId = Process.GetCurrentProcess().SessionId;
|
|
}
|
|
catch { }
|
|
|
|
pipeServer = new cF4sdPipeServer();
|
|
pipeServer.PipeMessage += PipeServer_PipeMessage;
|
|
pipeServer.Listen(listenPipeName, MaxSize: 255, LowerIntegrity: true);
|
|
LogEntry($"Start listening on named pipe '{listenPipeName}'...", LogLevels.Debug);
|
|
|
|
|
|
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
|
|
|
|
Application.EnableVisualStyles();
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
Application.ApplicationExit += OnApplicationExit;
|
|
Application.Run();
|
|
|
|
return 0;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static bool ConnectSwyxit()
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
var regObj = Registry.GetValue("HKEY_CLASSES_ROOT\\CLSID\\{F8E552F8-4C00-11D3-80BC-00105A653379}\\VersionIndependentProgID", null, null);
|
|
if (!(regObj is string strObj) || strObj.ToLowerInvariant() != "clmgr.clientlinemgr")
|
|
{
|
|
LogEntry("SwyxIt client seems not to be installed. Terminating...", LogLevels.Fatal);
|
|
return false;
|
|
}
|
|
|
|
lmg = new cCLMgrEvents();
|
|
if (!lmg.Initialize())
|
|
return false;
|
|
|
|
lmg.ActiveCallHandler += ActiveCallMessage;
|
|
|
|
return true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
static bool ConnectTapi(string Line)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
C4TapiHelper.Instance = new C4TapiHelper();
|
|
C4TapiHelper.Instance.Initialize(TapiMessageHandler);
|
|
C4TapiHelper.Instance.GetLines();
|
|
if (C4TapiHelper.Instance.ConnectLine(Line))
|
|
return true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
|
|
{
|
|
LogEntry("User logout detected. Terminating...", LogLevels.Debug);
|
|
Application.Exit();
|
|
}
|
|
|
|
private static void TimerPolling_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
timerPolling.Stop();
|
|
if (StopImmediate)
|
|
{
|
|
Application.Exit();
|
|
return;
|
|
}
|
|
|
|
timerPolling.Interval = 10000;
|
|
bool res = false;
|
|
lock (sendPipeName)
|
|
{
|
|
res = Send("Hello", sendPipeName);
|
|
};
|
|
|
|
if (res)
|
|
SendError = 0;
|
|
else
|
|
{
|
|
SendError++;
|
|
if (SendError == 2)
|
|
Application.Exit();
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
timerPolling.Start();
|
|
}
|
|
|
|
static private void OnApplicationExit(object sender, EventArgs e)
|
|
{
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
timerPolling.Stop();
|
|
|
|
try
|
|
{
|
|
if (lmg != null)
|
|
{
|
|
lmg.ActiveCallHandler -= ActiveCallMessage;
|
|
lmg.Disconnect();
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
try
|
|
{
|
|
if (C4TapiHelper.Instance != null)
|
|
{
|
|
C4TapiHelper.Instance.Dispose();
|
|
C4TapiHelper.Instance = null;
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
if (pipeServer != null)
|
|
{
|
|
LogEntry("stopping pipe server...", LogLevels.Debug);
|
|
pipeServer.Stop();
|
|
pipeServer.Dispose();
|
|
pipeServer = null;
|
|
LogEntry("...finished.", LogLevels.Debug);
|
|
}
|
|
|
|
//Application.ApplicationExit -= OnApplicationExit;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
|
|
static void ActiveCallMessage(string phone, string name, bool isOutgoing)
|
|
{
|
|
if (isOutgoing && !SignalOutgoingCall)
|
|
{
|
|
LogEntry("An outgoing call is signaled but signaling outgoing calls is not enabled.");
|
|
return;
|
|
}
|
|
|
|
if (sendPipeName == null)
|
|
return;
|
|
|
|
if (string.IsNullOrWhiteSpace(phone))
|
|
return;
|
|
|
|
|
|
if (name == null)
|
|
name = "";
|
|
|
|
var phone2 = phone.Trim();
|
|
if (!string.IsNullOrEmpty(ExternalCallPrefix) && phone2.StartsWith(ExternalCallPrefix))
|
|
phone2 = phone2.Remove(0,ExternalCallPrefix.Length);
|
|
|
|
if (phone2.StartsWith("+"))
|
|
{
|
|
var _r = Math.Min(phone2.Length, 3);
|
|
phone2 = phone2.Remove(0, _r);
|
|
}
|
|
else if (phone2.StartsWith("00"))
|
|
{
|
|
var _r = Math.Min(phone2.Length, 4);
|
|
phone2 = phone2.Remove(0, _r);
|
|
}
|
|
if (phone2.StartsWith("0"))
|
|
phone2 = phone2.Remove(0, 1);
|
|
|
|
var phone3 = "";
|
|
foreach (var C in phone2)
|
|
if ((C >= '0') && (C <= '9'))
|
|
phone3 += C;
|
|
|
|
var name2 = name.Trim();
|
|
var _strDir = isOutgoing ? "outgoing" : "incoming";
|
|
LogEntry($"Signaling {_strDir} call: phone={phone2}, name={name2}", LogLevels.Debug);
|
|
|
|
var Info = JsonConvert.SerializeObject(new cPhoneSearchParameters() { phone = phone3, name = name2 });
|
|
lock (sendPipeName)
|
|
{
|
|
Send($"phonesearch: {Info}", sendPipeName);
|
|
}
|
|
}
|
|
|
|
static public bool Send(string SendStr, string PipeName, int TimeOut = 1000)
|
|
{
|
|
try
|
|
{
|
|
if (IsSimulation)
|
|
{
|
|
LogEntry($"simulatied pipe send: {SendStr}");
|
|
return true;
|
|
}
|
|
NamedPipeClientStream pipeStream = new NamedPipeClientStream
|
|
(".", PipeName, PipeDirection.Out, PipeOptions.WriteThrough);
|
|
|
|
// The connect function will indefinitely wait for the pipe to become available
|
|
// If that is not acceptable specify a maximum waiting time (in ms)
|
|
pipeStream.Connect(TimeOut);
|
|
|
|
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
|
|
pipeStream.Write(_buffer, 0, _buffer.Length);
|
|
pipeStream.Flush();
|
|
pipeStream.Close();
|
|
pipeStream.Dispose();
|
|
|
|
return true;
|
|
}
|
|
catch (TimeoutException oEX)
|
|
{
|
|
if (DefaultLogger.IsDebug)
|
|
cLogManager.DefaultLogger.LogException(oEX);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static private void PipeServer_PipeMessage(string Reply)
|
|
{
|
|
if (Reply.ToLowerInvariant() == "stop")
|
|
{
|
|
timerPolling.Stop();
|
|
StopImmediate = true;
|
|
timerPolling.Interval = 100;
|
|
timerPolling.Start();
|
|
|
|
}
|
|
}
|
|
|
|
private static void TapiMessageHandler(C4TapiHelper.C4TapiLineInfo lineInfo)
|
|
{
|
|
if (lineInfo.eventType == C4TapiHelper.eTapiEventType.connected)
|
|
{
|
|
|
|
var CM = MethodBase.GetCurrentMethod();
|
|
LogMethodBegin(CM);
|
|
try
|
|
{
|
|
ActiveCallMessage(lineInfo.participantPhoneNumber, lineInfo.participantName, lineInfo.IsOutbound);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
LogMethodEnd(CM);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class cPhoneSearchParameters
|
|
{
|
|
public string phone { get; set; }
|
|
public string name { get; set; } = null;
|
|
}
|
|
}
|
|
|
|
}
|