Add device sharing support

This commit is contained in:
Kyle Schwarz
2022-12-13 11:46:32 -05:00
parent 78465e0f20
commit a9157c82e5
46 changed files with 1946 additions and 102 deletions
+101 -2
View File
@@ -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;
}
+59 -16
View File
@@ -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++;
}
}
}
}