2018-11-24 21:39:18 +00:00
|
|
|
/*-
|
2021-01-12 21:50:54 +00:00
|
|
|
* Copyright (c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
|
2018-11-24 21:39:18 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "message.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "win.h"
|
|
|
|
|
2021-01-12 21:53:12 +00:00
|
|
|
#define EVT_HOTKEY 1L
|
|
|
|
|
2018-11-24 21:39:18 +00:00
|
|
|
static void ProcessMsg(void);
|
2021-01-12 21:53:12 +00:00
|
|
|
static void InitBroker(void);
|
|
|
|
static void CleanupBroker(void);
|
2018-11-24 21:39:18 +00:00
|
|
|
|
|
|
|
static struct NewBroker newBroker = {
|
|
|
|
NB_VERSION,
|
|
|
|
(STRPTR)APP_SHORT_NAME,
|
|
|
|
(STRPTR)APP_TITLE_VERSION,
|
|
|
|
(STRPTR) "Synchronize Clock With Internet Servers",
|
|
|
|
NBU_UNIQUE | NBU_NOTIFY,
|
|
|
|
COF_SHOW_HIDE,
|
|
|
|
0, 0, 0};
|
|
|
|
|
|
|
|
void StartBroker(void)
|
|
|
|
{
|
|
|
|
LONG error;
|
|
|
|
struct Message *msg;
|
2021-01-12 21:53:12 +00:00
|
|
|
CxObj *filter, *sender, *translate;
|
|
|
|
|
|
|
|
InitBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
|
|
|
|
Globals->Broker->BrokerPort = CreateMsgPort();
|
|
|
|
if (Globals->Broker->BrokerPort == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker port");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Globals->Broker->UserPort = CreateMsgPort();
|
|
|
|
if (Globals->Broker->UserPort == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker user port");
|
2021-01-12 21:53:12 +00:00
|
|
|
CleanupBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Globals->Broker->ReplyPort = CreateMsgPort();
|
|
|
|
if (Globals->Broker->ReplyPort == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker reply port");
|
2021-01-12 21:53:12 +00:00
|
|
|
CleanupBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Globals->Broker->ShutdownSigBit = AllocSignal(-1);
|
|
|
|
if (Globals->Broker->ShutdownSigBit == -1)
|
|
|
|
{
|
|
|
|
SendErrorMessage("Could not allocate signal for broker");
|
2021-01-12 21:53:12 +00:00
|
|
|
CleanupBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
newBroker.nb_Port = Globals->Broker->BrokerPort;
|
|
|
|
newBroker.nb_Pri = Globals->Settings->Priority;
|
|
|
|
|
|
|
|
Globals->Broker->Object = CxBroker(&newBroker, &error);
|
|
|
|
if (!Globals->Broker->Object)
|
|
|
|
{
|
|
|
|
switch (error)
|
|
|
|
{
|
|
|
|
case CBERR_SYSERR:
|
|
|
|
LogError("System problems (CBERR_SYSERR). Could not allocate broker object");
|
|
|
|
break;
|
|
|
|
case CBERR_DUP:
|
2021-01-12 21:53:12 +00:00
|
|
|
LogWarning(APP_SHORT_NAME " is already running");
|
2018-11-24 21:39:18 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LogError("Could not allocate broker object (error code: %ld)", error);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-01-12 21:53:12 +00:00
|
|
|
CleanupBroker();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
filter = CxFilter(Globals->Settings->PopKey);
|
|
|
|
if (filter == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker filter object");
|
|
|
|
CleanupBroker();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttachCxObj(Globals->Broker->Object, filter);
|
|
|
|
|
|
|
|
sender = CxSender(Globals->Broker->BrokerPort, EVT_HOTKEY);
|
|
|
|
if (sender == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker sender object");
|
|
|
|
CleanupBroker();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttachCxObj(filter, sender);
|
|
|
|
|
|
|
|
translate = CxTranslate(NULL);
|
|
|
|
if (translate == NULL)
|
|
|
|
{
|
|
|
|
LogError("Could not allocate broker translate object");
|
|
|
|
CleanupBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-12 21:53:12 +00:00
|
|
|
AttachCxObj(filter, translate);
|
|
|
|
|
|
|
|
error = CxObjError(filter);
|
|
|
|
if (error != 0)
|
|
|
|
{
|
|
|
|
switch (error)
|
|
|
|
{
|
|
|
|
case CBERR_SYSERR:
|
|
|
|
LogWarning("Commodity filter problems (CBERR_SYSERR)");
|
|
|
|
break;
|
|
|
|
case COERR_BADFILTER:
|
|
|
|
LogWarning("Commodity HOTKEY error");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LogWarning("Commodity filter error (error code: %ld)", error);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-24 21:39:18 +00:00
|
|
|
Globals->Broker->Task = FindTask(NULL);
|
|
|
|
|
|
|
|
StartCom();
|
|
|
|
ProcessMsg();
|
|
|
|
|
|
|
|
while ((msg = GetMsg(Globals->Broker->BrokerPort)))
|
|
|
|
ReplyMsg(msg);
|
|
|
|
|
|
|
|
while ((msg = GetMsg(Globals->Broker->UserPort)))
|
|
|
|
ReplyMsg(msg);
|
|
|
|
|
|
|
|
while ((msg = GetMsg(Globals->Broker->ReplyPort)))
|
|
|
|
ReplyMsg(msg);
|
|
|
|
|
2021-01-12 21:53:12 +00:00
|
|
|
CleanupBroker();
|
2018-11-24 21:39:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShutdownBroker(void)
|
|
|
|
{
|
|
|
|
Signal((struct Task *)Globals->Broker->Task,
|
|
|
|
(1 << Globals->Broker->ShutdownSigBit));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetBrokerPriority(int priority)
|
|
|
|
{
|
|
|
|
SetCxObjPri(Globals->Broker->Object, priority);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Activate(void)
|
|
|
|
{
|
|
|
|
LogWarning("ACTIVE changed: 1 -> 0");
|
|
|
|
ActivateCxObj(Globals->Broker->Object, 0);
|
|
|
|
Globals->Active = false;
|
|
|
|
StopComAsync();
|
|
|
|
while (!CheckComClosed())
|
|
|
|
Delay(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Deactivate(void)
|
|
|
|
{
|
|
|
|
LogWarning("ACTIVE changed: 0 -> 1");
|
|
|
|
ActivateCxObj(Globals->Broker->Object, 1);
|
|
|
|
Globals->Active = true;
|
|
|
|
StartCom();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void StopSubProcesses(void)
|
|
|
|
{
|
|
|
|
Forbid();
|
|
|
|
Globals->ShuttingDown = true;
|
|
|
|
Permit();
|
|
|
|
|
|
|
|
HideSettingWindow();
|
|
|
|
while (!CheckSettingWindowClosed())
|
|
|
|
Delay(10);
|
|
|
|
|
|
|
|
StopComAsync();
|
|
|
|
while (!CheckComClosed())
|
|
|
|
Delay(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ProcessMsg(void)
|
|
|
|
{
|
|
|
|
bool run = true;
|
|
|
|
ULONG sigmask = SIGBREAKF_CTRL_C |
|
|
|
|
(1 << Globals->Broker->ShutdownSigBit) |
|
|
|
|
(1 << Globals->Broker->BrokerPort->mp_SigBit) |
|
|
|
|
(1 << Globals->Broker->UserPort->mp_SigBit) |
|
|
|
|
(1 << Globals->Broker->ReplyPort->mp_SigBit);
|
|
|
|
|
|
|
|
ActivateCxObj(Globals->Broker->Object, 1);
|
|
|
|
Globals->Active = true;
|
|
|
|
|
2021-01-12 21:53:12 +00:00
|
|
|
if (Globals->Settings->Popup)
|
|
|
|
{
|
|
|
|
ShowSettingWindow();
|
|
|
|
}
|
|
|
|
|
2018-11-24 21:39:18 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
ULONG sigrcvd = Wait(sigmask);
|
|
|
|
|
|
|
|
if (sigrcvd & (1 << Globals->Broker->BrokerPort->mp_SigBit))
|
|
|
|
{
|
|
|
|
CxMsg *msg;
|
|
|
|
while ((msg = (CxMsg *)GetMsg(Globals->Broker->BrokerPort)))
|
|
|
|
{
|
|
|
|
LONG msgid = CxMsgID(msg);
|
|
|
|
ULONG msgtype = CxMsgType(msg);
|
|
|
|
ReplyMsg((struct Message *)msg);
|
|
|
|
|
|
|
|
switch (msgtype)
|
|
|
|
{
|
|
|
|
case CXM_IEVENT:
|
2021-01-12 21:53:12 +00:00
|
|
|
switch (msgid)
|
|
|
|
{
|
|
|
|
case EVT_HOTKEY:
|
|
|
|
LogTrace("Show window");
|
|
|
|
ShowSettingWindow();
|
|
|
|
break;
|
|
|
|
}
|
2018-11-24 21:39:18 +00:00
|
|
|
break;
|
|
|
|
case CXM_COMMAND:
|
|
|
|
switch (msgid)
|
|
|
|
{
|
|
|
|
case CXCMD_DISABLE:
|
|
|
|
Activate();
|
|
|
|
break;
|
|
|
|
case CXCMD_ENABLE:
|
|
|
|
Deactivate();
|
|
|
|
break;
|
|
|
|
case CXCMD_KILL:
|
|
|
|
LogInfo("Received shut down from commodity");
|
|
|
|
StopSubProcesses();
|
|
|
|
run = false;
|
|
|
|
break;
|
|
|
|
case CXCMD_UNIQUE:
|
|
|
|
LogWarning("Commodity duplicate detected");
|
|
|
|
LogTrace("Show window");
|
|
|
|
ShowSettingWindow();
|
|
|
|
break;
|
|
|
|
case CXCMD_APPEAR:
|
|
|
|
LogTrace("Show window");
|
|
|
|
ShowSettingWindow();
|
|
|
|
break;
|
|
|
|
case CXCMD_DISAPPEAR:
|
|
|
|
LogTrace("Hide window");
|
|
|
|
HideSettingWindow();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigrcvd & (1 << Globals->Broker->UserPort->mp_SigBit))
|
|
|
|
{
|
|
|
|
struct AppWindowMessage *msg;
|
|
|
|
while ((msg = (struct AppWindowMessage *)GetMsg(Globals->Broker->UserPort)))
|
|
|
|
{
|
|
|
|
switch (msg->Type)
|
|
|
|
{
|
|
|
|
case ATK_LOGERROR:
|
|
|
|
LogError(msg->Text);
|
|
|
|
break;
|
|
|
|
case ATK_LOGWARN:
|
|
|
|
LogWarning(msg->Text);
|
|
|
|
break;
|
|
|
|
case ATK_LOGINFO:
|
|
|
|
LogInfo(msg->Text);
|
|
|
|
break;
|
|
|
|
case ATK_LOGTRACE:
|
|
|
|
LogTrace(msg->Text);
|
|
|
|
break;
|
|
|
|
case ATK_STORE:
|
|
|
|
SaveSettings(true);
|
|
|
|
SaveSettings(false);
|
|
|
|
break;
|
|
|
|
case ATK_APPLY:
|
|
|
|
SaveSettings(false);
|
|
|
|
break;
|
|
|
|
case ATK_UNDO:
|
|
|
|
ApplyAppSettings(Globals->Window->Settings, true);
|
|
|
|
break;
|
|
|
|
case ATK_RESTART:
|
|
|
|
RestartSntpAsync();
|
|
|
|
break;
|
|
|
|
case ATK_REFRESH:
|
|
|
|
// Broker cannot refresh
|
|
|
|
break;
|
|
|
|
case ATK_DISABLE:
|
|
|
|
Activate();
|
|
|
|
break;
|
|
|
|
case ATK_ENABLE:
|
|
|
|
Deactivate();
|
|
|
|
break;
|
|
|
|
case ATK_READONLY:
|
|
|
|
LogWarning("READONLY changed: 1 -> 0");
|
|
|
|
break;
|
|
|
|
case ATK_READWRITE:
|
|
|
|
LogWarning("READONLY changed: 0 -> 1");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ReplyMsg((struct Message *)msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigrcvd & (1 << Globals->Broker->ReplyPort->mp_SigBit))
|
|
|
|
{
|
|
|
|
struct AppWindowMessage *msg;
|
|
|
|
while ((msg = (struct AppWindowMessage *)GetMsg(Globals->Broker->ReplyPort)))
|
|
|
|
{
|
|
|
|
if (msg->Text != NULL)
|
|
|
|
{
|
|
|
|
FreeMemSafe(msg->Text);
|
|
|
|
}
|
|
|
|
FreeMemSafe(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigrcvd & (1 << Globals->Broker->ShutdownSigBit))
|
|
|
|
{
|
|
|
|
LogInfo("Received shut down from setting window");
|
|
|
|
StopSubProcesses();
|
|
|
|
run = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigrcvd & SIGBREAKF_CTRL_C)
|
|
|
|
{
|
|
|
|
LogInfo("Received CTRL + C");
|
|
|
|
StopSubProcesses();
|
|
|
|
run = false;
|
|
|
|
}
|
|
|
|
} while (run);
|
|
|
|
}
|
2021-01-12 21:53:12 +00:00
|
|
|
|
|
|
|
static void InitBroker(void)
|
|
|
|
{
|
|
|
|
Globals->Broker->Object = NULL;
|
|
|
|
Globals->Broker->ShutdownSigBit = -1;
|
|
|
|
Globals->Broker->Task = NULL;
|
|
|
|
Globals->Broker->BrokerPort = NULL;
|
|
|
|
Globals->Broker->UserPort = NULL;
|
|
|
|
Globals->Broker->ReplyPort = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CleanupBroker(void)
|
|
|
|
{
|
|
|
|
if (Globals->Broker->Object != NULL)
|
|
|
|
{
|
|
|
|
DeleteCxObjAll(Globals->Broker->Object);
|
|
|
|
Globals->Broker->Object = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Globals->Broker->ShutdownSigBit != -1)
|
|
|
|
{
|
|
|
|
FreeSignal(Globals->Broker->ShutdownSigBit);
|
|
|
|
Globals->Broker->ShutdownSigBit = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Globals->Broker->BrokerPort != NULL)
|
|
|
|
{
|
|
|
|
DeleteMsgPort(Globals->Broker->BrokerPort);
|
|
|
|
Globals->Broker->BrokerPort = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Globals->Broker->UserPort != NULL)
|
|
|
|
{
|
|
|
|
DeleteMsgPort(Globals->Broker->UserPort);
|
|
|
|
Globals->Broker->UserPort = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Globals->Broker->ReplyPort != NULL)
|
|
|
|
{
|
|
|
|
DeleteMsgPort(Globals->Broker->ReplyPort);
|
|
|
|
Globals->Broker->ReplyPort = NULL;
|
|
|
|
}
|
|
|
|
}
|