mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 09:28:40 +02:00
Add device sharing support
This commit is contained in:
+101
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
APIEvent::APIEvent(Type type, APIEvent::Severity severity, const Device* device) : eventStruct({}) {
|
||||
APIEvent::APIEvent(Type type, Severity severity, const Device* device) : eventStruct({}) {
|
||||
this->device = device;
|
||||
if(device) {
|
||||
serial = device->getSerial();
|
||||
@@ -14,6 +14,17 @@ APIEvent::APIEvent(Type type, APIEvent::Severity severity, const Device* device)
|
||||
init(type, severity);
|
||||
}
|
||||
|
||||
APIEvent::APIEvent(neosocketevent_t evStruct, const Device* device)
|
||||
{
|
||||
this->device = device;
|
||||
timepoint = EventClock::from_time_t(evStruct.timestamp);
|
||||
serial = std::string(evStruct.serial);
|
||||
eventStruct.eventNumber = evStruct.eventNumber;
|
||||
eventStruct.severity = evStruct.severity;
|
||||
eventStruct.description = DescriptionForType(APIEvent::getType());
|
||||
eventStruct.timestamp = evStruct.timestamp;
|
||||
}
|
||||
|
||||
void APIEvent::init(Type event, APIEvent::Severity severity) {
|
||||
timepoint = EventClock::now();
|
||||
eventStruct.description = DescriptionForType(event);
|
||||
@@ -45,6 +56,15 @@ std::string APIEvent::describe() const noexcept {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
neosocketevent_t APIEvent::getNeoSocketEvent() const noexcept {
|
||||
neosocketevent_t neoSocketEvent;
|
||||
neoSocketEvent.eventNumber = eventStruct.eventNumber;
|
||||
neoSocketEvent.severity = eventStruct.severity;
|
||||
std::memcpy(neoSocketEvent.serial, eventStruct.serial, sizeof(eventStruct.serial));
|
||||
neoSocketEvent.timestamp = eventStruct.timestamp;
|
||||
return neoSocketEvent;
|
||||
}
|
||||
|
||||
void APIEvent::downgradeFromError() noexcept {
|
||||
eventStruct.severity = (uint8_t) APIEvent::Severity::EventWarning;
|
||||
}
|
||||
@@ -126,8 +146,31 @@ static constexpr const char* PCAP_COULD_NOT_START = "The PCAP driver could not b
|
||||
static constexpr const char* PCAP_COULD_NOT_FIND_DEVICES = "The PCAP driver failed to find devices. Ethernet devices will not be found.";
|
||||
static constexpr const char* PACKET_DECODING = "There was an error decoding a packet from the device.";
|
||||
|
||||
static constexpr const char* SHARED_MEMORY_DATA_IS_NULL = "data() was called on invalid object.";
|
||||
static constexpr const char* SHARED_MEMORY_FAILED_TO_CLOSE = "The server failed to close a shared memory location.";
|
||||
static constexpr const char* SHARED_MEMORY_FAILED_TO_OPEN = "The server failed to open a shared memory location.";
|
||||
static constexpr const char* SHARED_MEMORY_FAILED_TO_UNLINK = "The server failed to unlink a shared memory location.";
|
||||
static constexpr const char* SHARED_MEMORY_FILE_TRUNCATE_ERROR = "The server failed to truncate shared memory file.";
|
||||
static constexpr const char* SHARED_MEMORY_MAPPING_ERROR = "The server failed to map a shared memory file.";
|
||||
static constexpr const char* SHARED_MEMORY_UNMAP_ERROR = "The server failed to unmap a shared memory file.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_FAILED_TO_CLOSE = "The server failed to close a shared semaphore.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_FAILED_TO_OPEN = "The server failed to open a shared semaphore.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_FAILED_TO_POST = "A post() call failed on a shared semaphore.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_FAILED_TO_UNLINK = "The server failed to unlink a shared semaphore.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_FAILED_TO_WAIT = "A wait() call failed on a shared semaphore.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_NOT_OPEN_FOR_POST = "post() was called on a shared semaphore that is not open.";
|
||||
static constexpr const char* SHARED_SEMAPHORE_NOT_OPEN_FOR_WAIT = "wait() was called on a shared semaphore that is not open.";
|
||||
static constexpr const char* SOCKET_FAILED_CONNECT = "A socket connection was attempted but failed.";
|
||||
static constexpr const char* SOCKET_FAILED_OPEN = "A socket failed to open.";
|
||||
static constexpr const char* SOCKET_FAILED_CLOSE = "A socket failed to close.";
|
||||
static constexpr const char* SOCKET_FAILED_READ = "A socket read operation failed.";
|
||||
static constexpr const char* SOCKET_FAILED_WRITE = "A socket write operation failed.";
|
||||
static constexpr const char* ACCEPTOR_FAILED_BIND = "A socket acceptor failed to bind.";
|
||||
static constexpr const char* ACCEPTOR_FAILED_LISTEN = "A socket acceptor failed to listen.";
|
||||
|
||||
static constexpr const char* TOO_MANY_EVENTS = "Too many events have occurred. The list has been truncated.";
|
||||
static constexpr const char* UNKNOWN = "An unknown internal error occurred.";
|
||||
static constexpr const char* NO_ERROR_FOUND = "No errors found.";
|
||||
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
||||
const char* APIEvent::DescriptionForType(Type type) {
|
||||
switch(type) {
|
||||
@@ -266,12 +309,58 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return PCAP_COULD_NOT_FIND_DEVICES;
|
||||
case Type::PacketDecodingError:
|
||||
return PACKET_DECODING;
|
||||
|
||||
|
||||
// Device Sharing Server Events
|
||||
case Type::SharedMemoryDataIsNull:
|
||||
return SHARED_MEMORY_DATA_IS_NULL;
|
||||
case Type::SharedMemoryFailedToClose:
|
||||
return SHARED_MEMORY_FAILED_TO_CLOSE;
|
||||
case Type::SharedMemoryFailedToOpen:
|
||||
return SHARED_MEMORY_FAILED_TO_OPEN;
|
||||
case Type::SharedMemoryFailedToUnlink:
|
||||
return SHARED_MEMORY_FAILED_TO_UNLINK;
|
||||
case Type::SharedMemoryFileTruncateError:
|
||||
return SHARED_MEMORY_FILE_TRUNCATE_ERROR;
|
||||
case Type::SharedMemoryMappingError:
|
||||
return SHARED_MEMORY_MAPPING_ERROR;
|
||||
case Type::SharedMemoryUnmapError:
|
||||
return SHARED_MEMORY_UNMAP_ERROR;
|
||||
case Type::SharedSemaphoreFailedToClose:
|
||||
return SHARED_SEMAPHORE_FAILED_TO_CLOSE;
|
||||
case Type::SharedSemaphoreFailedToOpen:
|
||||
return SHARED_SEMAPHORE_FAILED_TO_OPEN;
|
||||
case Type::SharedSemaphoreFailedToPost:
|
||||
return SHARED_SEMAPHORE_FAILED_TO_POST;
|
||||
case Type::SharedSemaphoreFailedToUnlink:
|
||||
return SHARED_SEMAPHORE_FAILED_TO_UNLINK;
|
||||
case Type::SharedSemaphoreFailedToWait:
|
||||
return SHARED_SEMAPHORE_FAILED_TO_WAIT;
|
||||
case Type::SharedSemaphoreNotOpenForPost:
|
||||
return SHARED_SEMAPHORE_NOT_OPEN_FOR_POST;
|
||||
case Type::SharedSemaphoreNotOpenForWait:
|
||||
return SHARED_SEMAPHORE_NOT_OPEN_FOR_WAIT;
|
||||
case Type::SocketFailedToOpen:
|
||||
return SOCKET_FAILED_OPEN;
|
||||
case Type::SocketFailedToClose:
|
||||
return SOCKET_FAILED_CLOSE;
|
||||
case Type::SocketFailedToConnect:
|
||||
return SOCKET_FAILED_CONNECT;
|
||||
case Type::SocketFailedToRead:
|
||||
return SOCKET_FAILED_READ;
|
||||
case Type::SocketFailedToWrite:
|
||||
return SOCKET_FAILED_WRITE;
|
||||
case Type::SocketAcceptorFailedToBind:
|
||||
return ACCEPTOR_FAILED_BIND;
|
||||
case Type::SocketAcceptorFailedToListen:
|
||||
return ACCEPTOR_FAILED_LISTEN;
|
||||
|
||||
// Other Errors
|
||||
case Type::TooManyEvents:
|
||||
return TOO_MANY_EVENTS;
|
||||
case Type::Unknown:
|
||||
return UNKNOWN;
|
||||
case Type::NoErrorFound:
|
||||
return NO_ERROR_FOUND;
|
||||
default:
|
||||
return INVALID;
|
||||
}
|
||||
@@ -291,4 +380,14 @@ bool EventFilter::match(const APIEvent& event) const noexcept {
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
neosocketeventfilter_t EventFilter::getNeoSocketEventFilter() const noexcept {
|
||||
neosocketeventfilter_t filterStruct;
|
||||
filterStruct.eventNumber = static_cast<decltype(filterStruct.eventNumber)>(type);
|
||||
filterStruct.severity = static_cast<decltype(filterStruct.severity)>(severity);
|
||||
if((serial.length() + 1) == sizeof(filterStruct.serial)) {
|
||||
std::memcpy(&filterStruct.serial[0], serial.c_str(), sizeof(filterStruct.serial));
|
||||
}
|
||||
return filterStruct;
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/api/event.h"
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
#include "icsneo/communication/socket.h"
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
@@ -40,7 +46,7 @@ void EventManager::add(APIEvent event) {
|
||||
if(i != downgradedThreads.end() && i->second) {
|
||||
event.downgradeFromError();
|
||||
{
|
||||
std::lock_guard<std::mutex> eventsLock(eventsMutex);
|
||||
std::lock_guard<std::mutex> eventsLock{eventsMutex};
|
||||
addEventInternal(event);
|
||||
} // free the lock so that callbacks may modify events
|
||||
runCallbacks(event);
|
||||
@@ -146,23 +152,60 @@ bool EventManager::isDowngradingErrorsOnCurrentThread() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
std::optional<std::vector<neosocketevent_t>> EventManager::getServerEvents(const size_t& max)
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!(socket.writeTyped<RPC>(RPC::GET_EVENTS) && socket.writeTyped<size_t>(max)))
|
||||
return std::nullopt;
|
||||
|
||||
size_t count;
|
||||
if(!socket.readTyped(count) || count < 0 || count > eventLimit)
|
||||
return std::nullopt;
|
||||
|
||||
std::optional<std::vector<neosocketevent_t>> ret;
|
||||
if(count == size_t(0))
|
||||
return ret;
|
||||
|
||||
auto& eventStructs = ret.emplace(count);
|
||||
if(!socket.read(eventStructs.data(), (eventStructs.size() * sizeof(neosocketevent_t))))
|
||||
return std::nullopt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // ICSNEO_ENABLE_DEVICE_SHARING
|
||||
|
||||
void EventManager::get(std::vector<APIEvent>& eventOutput, size_t max, EventFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(eventsMutex);
|
||||
|
||||
if(max == 0) // A limit of 0 indicates no limit
|
||||
max = (size_t)-1;
|
||||
|
||||
size_t count = 0;
|
||||
eventOutput.clear();
|
||||
auto it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if(filter.match(*it)) {
|
||||
eventOutput.push_back(*it);
|
||||
it = events.erase(it);
|
||||
if(++count >= max)
|
||||
break; // We now have as many written to output as we can
|
||||
} else {
|
||||
it++;
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto serverEvents = getServerEvents(max);
|
||||
if(serverEvents) {
|
||||
std::scoped_lock eventsLock{eventsMutex};
|
||||
for(neosocketevent_t& event : *serverEvents) {
|
||||
eventOutput.emplace_back(event);
|
||||
}
|
||||
if(max != 0u)
|
||||
max -= eventOutput.size();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::scoped_lock eventsLock{eventsMutex};
|
||||
{
|
||||
if(max == 0) // A limit of 0 indicates no limit
|
||||
max = (size_t)-1;
|
||||
|
||||
size_t count = 0;
|
||||
auto it = events.begin();
|
||||
while(it != events.end()) {
|
||||
if(filter.match(*it)) {
|
||||
eventOutput.push_back(*it);
|
||||
it = events.erase(it);
|
||||
if(++count >= max)
|
||||
break; // We now have as many written to output as we can
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user