//////////////////////////////////////////////////////////////////
//
// SoftPBX.cxx
//
// This work is published under the GNU Public License (GPL)
// see file COPYING for details.
// We also explicitely grant the right to link this code
// with the OpenH323 library.
//
// initial author: Jan Willamowius
//
//////////////////////////////////////////////////////////////////
#if defined(_WIN32) && (_MSC_VER <= 1200)
#pragma warning(disable:4786) // warning about too long debug symbol off
#pragma warning(disable:4284)
#endif
#include <ptlib.h>
#include <h323pdu.h>
#include "gk_const.h"
#include "Toolkit.h"
#include "GkStatus.h"
#include "RasSrv.h"
#include "ProxyChannel.h"
#include "SoftPBX.h"
int SoftPBX::TimeToLive = -1;
PTime SoftPBX::StartUp;
void SoftPBX::PrintEndpoint(const PString & EpStr, USocket *client, bool verbose)
{
H225_ArrayOf_AliasAddress EpAlias;
EpAlias.SetSize(1);
H323SetAliasAddress(EpStr, EpAlias[0]);
// Apply rewriting rules
Toolkit::Instance()->RewriteE164(EpAlias[0]);
endptr ep = RegistrationTable::Instance()->FindEndpoint(EpAlias, false, true);
if (!ep) {
H225_EndpointIdentifier id;
id = EpStr;
ep = RegistrationTable::Instance()->FindByEndpointId(id);
}
if (!ep) {
H225_TransportAddress callSignalAddress;
GetTransportAddress(EpStr, (WORD)GkConfig()->GetInteger("EndpointSignalPort", GK_DEF_ENDPOINT_SIGNAL_PORT), callSignalAddress);
ep = RegistrationTable::Instance()->FindBySignalAdr(callSignalAddress);
}
PString msg;
if (ep)
msg = "RCF|" + ep->PrintOn(verbose) + ";\r\n";
else
msg = "SoftPBX: endpoint " + EpStr + " not found!\r\n";
client->TransmitData(msg);
}
void SoftPBX::PrintAllRegistrations(USocket *client, bool verbose)
{
PTRACE(3, "GK\tSoftPBX: PrintAllRegistrations");
RegistrationTable::Instance()->PrintAllRegistrations(client, verbose);
}
void SoftPBX::PrintAllCached(USocket *client, bool verbose)
{
PTRACE(3, "GK\tSoftPBX: PrintAllCached");
RegistrationTable::Instance()->PrintAllCached(client, verbose);
}
void SoftPBX::PrintRemoved(USocket *client, bool verbose)
{
PTRACE(3, "GK\tSoftPBX: PrintRemoved");
RegistrationTable::Instance()->PrintRemoved(client, verbose);
}
void SoftPBX::PrintCurrentCalls(USocket *client, bool verbose)
{
PTRACE(3, "GK\tSoftPBX: PrintCurrentCalls");
CallTable::Instance()->PrintCurrentCalls(client, verbose);
}
void SoftPBX::PrintStatistics(USocket *client, bool)
{
PTRACE(3, "GK\tSoftPBX: PrintStatistics");
PString msg = RegistrationTable::Instance()->PrintStatistics()
+ CallTable::Instance()->PrintStatistics()
+ SoftPBX::Uptime() + "\r\n;\r\n";
client->TransmitData(msg);
}
// send URQ to all endpoints
void SoftPBX::UnregisterAllEndpoints()
{
CallTable::Instance()->ClearTable();
RegistrationTable::Instance()->ClearTable();
}
void SoftPBX::UnregisterAlias(PString Alias)
{
H225_ArrayOf_AliasAddress EpAlias;
EpAlias.SetSize(1);
H323SetAliasAddress(Alias, EpAlias[0]);
PTRACE(3, "GK\tSoftPBX: UnregisterAlias " << Alias);
const endptr ep = RegistrationTable::Instance()->FindByAliases(EpAlias);
if (!ep) {
PString msg("SoftPBX: alias " + Alias + " not found!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
DisconnectEndpoint(ep);
ep->Unregister();
// remove the endpoint (even if we don't get a UCF - the endoint might be dead)
RegistrationTable::Instance()->RemoveByEndptr(ep);
PString msg("SoftPBX: Endpoint " + Alias + " unregistered!");
PTRACE(2, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
}
void SoftPBX::UnregisterIp(PString Ip)
{
H225_TransportAddress callSignalAddress;
GetTransportAddress(Ip, (WORD)GkConfig()->GetInteger("EndpointSignalPort", GK_DEF_ENDPOINT_SIGNAL_PORT), callSignalAddress);
PTRACE(3, "GK\tSoftPBX: UnregisterIp " << AsDotString(callSignalAddress));
const endptr ep = RegistrationTable::Instance()->FindBySignalAdr(callSignalAddress);
if (!ep) {
PString msg("SoftPBX: ip " + AsDotString(callSignalAddress) + " not found!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
DisconnectEndpoint(ep);
ep->Unregister();
// remove the endpoint (even if we don't get a UCF - the endoint might be dead)
RegistrationTable::Instance()->RemoveByEndptr(ep);
PString msg("SoftPBX: Endpoint " + AsDotString(callSignalAddress) + " unregistered!");
PTRACE(2, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
}
void SoftPBX::DisconnectAll()
{
CallTable::Instance()->ClearTable();
}
// send a DRQ to caller of this call number, causing it to close the H.225 channel
// this causes the gatekeeper to close the H.225 channel to the called party when
// it recognises the caller has gone away
void SoftPBX::DisconnectCall(unsigned CallNumber)
{
PTRACE(3, "GK\tSoftPBX: DisconnectCall " << CallNumber);
callptr Call = CallTable::Instance()->FindCallRec(CallNumber);
if (!Call) {
PString msg(PString::Printf, "Can't find call number %u", CallNumber);
PTRACE(2, "GK\tSoftPBX: " << msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
Call->Disconnect();
// remove the call directly so we don't have to handle DCF
CallTable::Instance()->RemoveCall(Call);
PString msg(PString::Printf, "Call number %d disconnected.", CallNumber);
PTRACE(2, "GK\tSoftPBX: " << msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
}
// send a DRQ to this endpoint
void SoftPBX::DisconnectIp(PString Ip)
{
H225_TransportAddress callSignalAddress;
GetTransportAddress(Ip, (WORD)GkConfig()->GetInteger("EndpointSignalPort", GK_DEF_ENDPOINT_SIGNAL_PORT), callSignalAddress);
PTRACE(3, "GK\tSoftPBX: DisconnectIp " << AsDotString(callSignalAddress));
DisconnectEndpoint(RegistrationTable::Instance()->FindBySignalAdr(callSignalAddress));
}
// send a DRQ to this endpoint
void SoftPBX::DisconnectAlias(PString Alias)
{
H225_ArrayOf_AliasAddress EpAlias;
EpAlias.SetSize(1);
H323SetAliasAddress(Alias, EpAlias[0]);
PTRACE(3, "GK\tSoftPBX: DisconnectAlias " << Alias);
DisconnectEndpoint(RegistrationTable::Instance()->FindByAliases(EpAlias));
}
// send a DRQ to this endpoint
void SoftPBX::DisconnectEndpoint(PString Id)
{
H225_EndpointIdentifier EpId; // id of endpoint to be disconnected
EpId = Id;
PTRACE(3, "GK\tSoftPBX: DisconnectEndpoint " << EpId);
DisconnectEndpoint(RegistrationTable::Instance()->FindByEndpointId(EpId));
}
void SoftPBX::DisconnectEndpoint(const endptr &ep)
{
if (!ep) {
PString msg("SoftPBX: no endpoint to disconnect!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
callptr Call;
// remove all calls of ep
while (Call = CallTable::Instance()->FindCallRec(ep)) {
Call->Disconnect();
CallTable::Instance()->RemoveCall(Call);
}
}
void SoftPBX::TransferCall(PString SourceAlias, PString DestinationAlias)
{
PTRACE(1, "GK\tSoftPBX: TransferCall " << SourceAlias << " -> " << DestinationAlias);
endptr lDestForward;
endptr lSrcForward;
callptr lCall;
PString lForwarder = SourceAlias + ":forward";
PString lAltDestInfo = DestinationAlias;
CallSignalSocket *lForwardedSocket = 0;
PStringList lBufferAliasArrayString;
H225_ArrayOf_AliasAddress lBufferAliasArray;
//Search for the call in CallTable
lBufferAliasArrayString.AppendString(SourceAlias);
H323SetAliasAddresses(lBufferAliasArrayString, lBufferAliasArray);
lSrcForward = RegistrationTable::Instance()->FindEndpoint(lBufferAliasArray, true, true);
lBufferAliasArrayString.RemoveAll();
lBufferAliasArray.RemoveAll();
if (!lSrcForward) {
PString msg("SoftPBX: no endpoint to transfer!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
lCall = CallTable::Instance()->FindCallRec(lSrcForward);
//Search for the Forwarded CallSignalSocket in lCall ( calling or caller socket ? )
if (lCall) {
endptr lCalling, lCalled;
lCalling = lCall->GetCallingParty();
lCalled = lCall->GetCalledParty();
H225_ArrayOf_AliasAddress aliases = lSrcForward->GetAliases();
if (lCalling && lCalling->CompareAlias(&aliases)) {
lForwardedSocket = lCall->GetCallSignalSocketCalling();
} else if (lCalled && lCalled->CompareAlias(&aliases)) {
lForwardedSocket = lCall->GetCallSignalSocketCalled();
}
if (!lForwardedSocket) {
PString msg("SoftPBX: can't transfer call in direct mode!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
} else {
PString msg("SoftPBX: no call to transfer!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
//Search destination of call forwarding : lDestForward
lBufferAliasArrayString.AppendString(DestinationAlias);
H323SetAliasAddresses(lBufferAliasArrayString, lBufferAliasArray);
lDestForward = RegistrationTable::Instance()->FindEndpoint(lBufferAliasArray, true, true);
lBufferAliasArrayString.RemoveAll();
lBufferAliasArray.RemoveAll();
if (!lDestForward) {
PString msg("SoftPBX: transferred destination not found!");
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
return;
}
Q931 q931;
PBYTEArray lBuffer;
lForwardedSocket->BuildFacilityPDU(q931, H225_FacilityReason::e_callForwarded, &DestinationAlias);
q931.Encode(lBuffer);
lForwardedSocket->TransmitData(lBuffer);
PString msg = PString("SoftPBX: call ") + PString(lCall->GetCallNumber()) + " transferred from" + SourceAlias + " to " + DestinationAlias;
PTRACE(1, "GK\t" + msg);
GkStatus::Instance()->SignalStatus(msg + "\r\n");
}
void SoftPBX::MakeCall(PString SourceAlias, PString DestinationAlias)
{
PTRACE(1, "GK\tSoftPBX: MakeCall " << SourceAlias << " -> " << DestinationAlias);
PTRACE(1, "GK\tSoftPBX: MakeCall not implemented, yet");
}
PString SoftPBX::Uptime()
{
long total = (PTime() - SoftPBX::StartUp).GetSeconds();
int days = total / (24*60*60);
int hour = (total % (24*60*60)) / (60*60);
int min = (total % (60*60)) / 60;
int sec = total % 60;
return PString(PString::Printf,
"Startup: %s Running: %d days %02d:%02d:%02d",
(const char *)SoftPBX::StartUp.AsString(),
days, hour, min, sec);
}
syntax highlighted by Code2HTML, v. 0.9.1