Files
handleaiuinew/env/LMI/include/GoSdk/GoAccelerator.c
T

442 lines
14 KiB
C
Raw Normal View History

2024-05-18 23:53:26 +08:00
/**
* @file GoAccelerator.c
*
* @internal
* Copyright (C) 2016-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#include <kApi/Io/kPath.h>
#include <GoSdk/GoAccelerator.h>
#include <GoSdk/GoSensor.h>
#if defined(K_WINDOWS)
#include <Windows.h> // added for global mutex checking mechanism in function GoAccelerator_Init()
HANDLE globalMutexApi = NULL; // store handle to mutex for API level locking
#endif
kBeginClassEx(Go, GoAccelerator)
kAddVMethod(GoAccelerator, kObject, VRelease)
kEndClassEx()
GoFx(kStatus) GoAccelerator_Construct(GoAccelerator* accelerator, kAlloc allocator)
{
#if defined(K_WINDOWS)
kAlloc alloc = kAlloc_Fallback(allocator);
kStatus status;
kCheck(kAlloc_GetObject(alloc, kTypeOf(GoAccelerator), accelerator));
if (!kSuccess(status = GoAccelerator_Init(*accelerator, kTypeOf(GoAccelerator), alloc)))
{
kAlloc_FreeRef(alloc, accelerator);
}
return status;
#else
return kERROR_UNIMPLEMENTED; // Currently only supported on Windows
#endif
}
GoFx(kStatus) GoAccelerator_Init(GoAccelerator accelerator, kType type, kAlloc alloc)
{
kObjR(GoAccelerator, accelerator);
kText256 libPath = { 0 };
kStatus exception;
kCheck(kObject_Init(accelerator, type, alloc));
kZero(obj->serverLib);
kZero(obj->gsLibAssembly);
kZero(obj->gsLibConstruct);
kZero(obj->serverConstruct);
kZero(obj->serverSetIpAddress);
kZero(obj->serverIpAddress);
kZero(obj->serverSetControlPort);
kZero(obj->serverControlPort);
kZero(obj->serverSetHealthPort);
kZero(obj->serverHealthPort);
kZero(obj->serverSetUpgradePort);
kZero(obj->serverUpgradePort);
kZero(obj->serverSetWebPort);
kZero(obj->serverWebPort);
kZero(obj->serverSetPrivateDataPort);
kZero(obj->serverPrivateDataPort);
kZero(obj->serverSetPublicDataPort);
kZero(obj->serverPublicDataPort);
kZero(obj->serverStart);
kZero(obj->serverStop);
kZero(obj->serverSetAcceleratorUpdateHandler);
kZero(obj->server);
obj->isRunning = kFALSE;
kZero(obj->attachedSensorAddress);
obj->attachedSensor = kNULL;
kTry
{
// get server library path
kTest(kPath_LibraryName(GS_REMOTE_APP_LIB_NAME, libPath, kCountOf(libPath)));
kTest(kDynamicLib_Construct(&obj->serverLib, libPath, alloc));
kTest(kDynamicLib_FindFunction(obj->serverLib, GSA_ASM_CONSTRUCT_FX, (kFunction*)&obj->gsLibConstruct));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_CONSTRUCT_FX, (kFunction*)&obj->serverConstruct));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_IP_ADDRESS_FX, (kFunction*)&obj->serverSetIpAddress));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_IP_ADDRESS_FX, (kFunction*)&obj->serverIpAddress));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_CONTROL_PORT_FX, (kFunction*)&obj->serverSetControlPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_CONTROL_PORT_FX, (kFunction*)&obj->serverControlPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_HEALTH_PORT_FX, (kFunction*)&obj->serverSetHealthPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_HEALTH_PORT_FX, (kFunction*)&obj->serverHealthPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_UPGRADE_PORT_FX, (kFunction*)&obj->serverSetUpgradePort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_UPGRADE_PORT_FX, (kFunction*)&obj->serverUpgradePort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_WEB_PORT_FX, (kFunction*)&obj->serverSetWebPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_WEB_PORT_FX, (kFunction*)&obj->serverWebPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_PRIVATE_DATA_PORT_FX, (kFunction*)&obj->serverSetPrivateDataPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_PRIVATE_DATA_PORT_FX, (kFunction*)&obj->serverPrivateDataPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_PUBLIC_DATA_PORT_FX, (kFunction*)&obj->serverSetPublicDataPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_PUBLIC_DATA_PORT_FX, (kFunction*)&obj->serverPublicDataPort));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_START_FX, (kFunction*)&obj->serverStart));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_STOP_FX, (kFunction*)&obj->serverStop));
kTest(kDynamicLib_FindFunction(obj->serverLib, GS_REMOTE_APP_SET_ACCELERATOR_UPDATE_HANDLER_FX, (kFunction*)&obj->serverSetAcceleratorUpdateHandler));
// Construct the GsLib assembly
kTest(obj->gsLibConstruct(&obj->gsLibAssembly));
// Construct the accelerator server
kTest(obj->serverConstruct(&obj->server, alloc));
}
kCatch(&exception)
{
kDestroyRef(&obj->server);
kDestroyRef(&obj->gsLibAssembly);
kDestroyRef(&obj->serverLib);
kEndCatch(exception);
}
return kOK;
}
GoFx(kStatus) GoAccelerator_VRelease(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
kDestroyRef(&obj->attachedSensor);
kDestroyRef(&obj->server);
kDestroyRef(&obj->gsLibAssembly);
kDestroyRef(&obj->serverLib);
return kObject_VRelease(accelerator);
}
GoFx(kStatus) GoAccelerator_Start(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
obj->isRunning = kTRUE;
return kOK;
}
GoFx(kStatus) GoAccelerator_Attach(GoAccelerator accelerator, GoSensor sensor)
{
kObj(GoAccelerator, accelerator);
kSize i = 0;
k32u id = GoSensor_Id(sensor);
kBool useStdPorts = kTRUE;
kStatus exception;
GoState state = GO_STATE_OFFLINE;
k64u start;
if (kIsNull(sensor))
{
return kERROR;
}
// ensure the sensor is not already attached
else if (GoAccelerator_IsAttached(accelerator, sensor))
{
return kERROR_ALREADY_EXISTS;
}
// already attached to another sensor
else if (kNULL != obj->attachedSensor)
{
return kERROR_BUSY;
}
// ensure the sensor is disconnected
kCheck(GoSensor_Disconnect(sensor));
#if defined(K_WINDOWS)
{
// Mutex name needs to match GoEmulateApp/Program.cs
if ((globalMutexApi = CreateMutexA(NULL, TRUE, "Global/GocatorPortMutex-0")) != NULL)
{
DWORD result = GetLastError();
if (result != 0)
{
CloseHandle(globalMutexApi);
globalMutexApi = NULL;
//useStdPorts = kFALSE;
}
}
}
#endif
kTry
{
// get the sensor's address
obj->attachedSensorAddress = *GoSensor_AddressInfo(sensor);
if (!useStdPorts)
{
kTest(GoAccelerator_SetControlPort(accelerator, kIP_PORT_ANY));
kTest(GoAccelerator_SetUpgradePort(accelerator, kIP_PORT_ANY));
kTest(GoAccelerator_SetPrivateDataPort(accelerator, kIP_PORT_ANY));
kTest(GoAccelerator_SetPublicDataPort(accelerator, kIP_PORT_ANY));
kTest(GoAccelerator_SetHealthPort(accelerator, kIP_PORT_ANY));
}
// start accelerating this sensor
kTest(obj->serverStart(obj->server, id));
// store the sensor details
kTest(kShareRef(&obj->attachedSensor, sensor));
// update the control port
GoSensor_SetControlPort(sensor, GoAccelerator_ControlPort(accelerator));
// update the upgrade port
GoSensor_SetUpgradePort(sensor, GoAccelerator_UpgradePort(accelerator));
// update the data port
GoSensor_SetDataPort(sensor, GoAccelerator_PublicDataPort(accelerator));
// update the health port
GoSensor_SetHealthPort(sensor, GoAccelerator_HealthPort(accelerator));
// Update the sensor address to point to the local PC
// TODO: this is a workaround in lieu of a proper wait for discovery update.
// Should remove when proper fix is done. e.g. some way to invalidate old
// discovery info, and then wait for new updates.
// Directly modifying the value by pointer is also bad form.
GoSensor_AddressInfo(sensor)->address = kIpAddress_LoopbackV4();
start = kTimer_Now();
while (ACCELERATOR_START_TIMEOUT >= (kTimer_Now()-start) &&
GO_STATE_ONLINE != (state = GoSensor_State(obj->attachedSensor)))
{
kThread_Sleep(10 * 1000); //10ms sleep
}
if (GO_STATE_ONLINE != state)
{
kTest(kERROR_TIMEOUT);
}
}
kCatch(&exception)
{
#if defined(K_WINDOWS)
// this clears the global mutexes if the actual attachment fails
if (globalMutexApi != NULL)
{
CloseHandle(globalMutexApi);
globalMutexApi = NULL;
}
#endif
kEndCatch(exception);
}
// the parent system needs to be updated too
//kCheck(GoSensor_RefreshSystem(sensor));
return kOK;
}
GoFx(kStatus) GoAccelerator_Detach(GoAccelerator accelerator, GoSensor sensor)
{
kObj(GoAccelerator, accelerator);
kSize i = 0;
kSize itemIndex = kSIZE_NULL;
k32u id = GoSensor_Id(sensor);
GoAddressInfo* address = kNULL;
GoControl control = kNULL;
if (!GoAccelerator_IsAttached(accelerator, sensor)) { return kERROR_NOT_FOUND; }
// ensure the sensor is disconnected
kCheck(GoSensor_Disconnect(sensor));
// stop the server
// Note - this should only stop the server for the sensor at hand,
// but it only works for 1 sensor right now
kCheck(obj->serverStop(obj->server));
// update the control channel to point to the sensor
control = GoSensor_Control(sensor);
kCheck(GoControl_SetRemoteAddress(control, obj->attachedSensorAddress.address));
// update the sensor address to point to the sensor
address = GoSensor_AddressInfo(sensor);
*address = obj->attachedSensorAddress;
// detach the sensor from the accelerator
kCheck(kDestroyRef(&obj->attachedSensor));
#if defined(K_WINDOWS)
// clear the global mutexes
if (globalMutexApi != NULL)
{
CloseHandle(globalMutexApi);
globalMutexApi = NULL;
}
#endif
return kOK;
}
GoFx(GoSensor) GoAccelerator_Sensor(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->attachedSensor;
}
GoFx(kStatus) GoAccelerator_Stop(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
obj->isRunning = kFALSE;
return kOK;
}
GoFx(kBool) GoAccelerator_IsRunning(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->isRunning;
}
GoFx(kBool) GoAccelerator_IsAttached(GoAccelerator accelerator, GoSensor sensor)
{
kObj(GoAccelerator, accelerator);
if (kIsNull(obj->attachedSensor) || kIsNull(sensor))
{
return kFALSE;
}
else if (GoSensor_Id(sensor) == GoSensor_Id(obj->attachedSensor))
{
return kTRUE;
}
return kFALSE;
}
GoFx(kStatus) GoAccelerator_SetAcceleratorUpdateHandler(GoAccelerator accelerator, kCallbackFx function, kPointer receiver)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetAcceleratorUpdateHandler(obj->server, function, receiver);
}
GoFx(kStatus) GoAccelerator_SetIpAddress(GoAccelerator accelerator, kIpAddress address)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetIpAddress(obj->server, address);
}
GoFx(kIpAddress) GoAccelerator_IpAddress(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverIpAddress(obj->server);
}
GoFx(kStatus) GoAccelerator_SetControlPort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetControlPort(obj->server, port);
}
GoFx(k32u) GoAccelerator_ControlPort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverControlPort(obj->server);
}
GoFx(kStatus) GoAccelerator_SetHealthPort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetHealthPort(obj->server, port);
}
GoFx(k32u) GoAccelerator_HealthPort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverHealthPort(obj->server);
}
GoFx(kStatus) GoAccelerator_SetUpgradePort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetUpgradePort(obj->server, port);
}
GoFx(k32u) GoAccelerator_UpgradePort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverUpgradePort(obj->server);
}
GoFx(kStatus) GoAccelerator_SetWebPort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetWebPort(obj->server, port);
}
GoFx(k32u) GoAccelerator_WebPort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverWebPort(obj->server);
}
GoFx(kStatus) GoAccelerator_SetPrivateDataPort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetPrivateDataPort(obj->server, port);
}
GoFx(k32u) GoAccelerator_PrivateDataPort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverPrivateDataPort(obj->server);
}
GoFx(kStatus) GoAccelerator_SetPublicDataPort(GoAccelerator accelerator, k32u port)
{
kObj(GoAccelerator, accelerator);
return obj->serverSetPublicDataPort(obj->server, port);
}
GoFx(k32u) GoAccelerator_PublicDataPort(GoAccelerator accelerator)
{
kObj(GoAccelerator, accelerator);
return obj->serverPublicDataPort(obj->server);
}