[Mammoth] Move ipc calls to separate folder mammoth.
This commit is contained in:
parent
19e394ae7b
commit
ad5b55bf37
19 changed files with 21 additions and 27 deletions
57
lib/mammoth/ipc/channel.cpp
Normal file
57
lib/mammoth/ipc/channel.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "ipc/channel.h"
|
||||
|
||||
#include <zcall.h>
|
||||
|
||||
#include "mammoth/debug.h"
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t strlen(const char* ptr) {
|
||||
uint64_t len = 0;
|
||||
while (*ptr != '\0') {
|
||||
len++;
|
||||
ptr++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Channel::adopt_cap(uint64_t id) {
|
||||
if (chan_cap_ != 0) {
|
||||
crash("Adopting over channel.", glcr::ALREADY_EXISTS);
|
||||
}
|
||||
chan_cap_ = id;
|
||||
}
|
||||
z_cap_t Channel::release_cap() {
|
||||
z_cap_t cap = chan_cap_;
|
||||
chan_cap_ = 0;
|
||||
return cap;
|
||||
}
|
||||
|
||||
z_cap_t Channel::cap() { return chan_cap_; }
|
||||
|
||||
z_err_t Channel::WriteStr(const char* msg) {
|
||||
if (!chan_cap_) {
|
||||
return glcr::NULL_PTR;
|
||||
}
|
||||
return ZChannelSend(chan_cap_, strlen(msg), msg, 0, nullptr);
|
||||
}
|
||||
|
||||
z_err_t Channel::ReadStr(char* buffer, uint64_t* size) {
|
||||
if (!chan_cap_) {
|
||||
return glcr::NULL_PTR;
|
||||
}
|
||||
uint64_t num_caps = 0;
|
||||
return ZChannelRecv(chan_cap_, size, reinterpret_cast<uint8_t*>(buffer),
|
||||
&num_caps, nullptr);
|
||||
}
|
||||
|
||||
z_err_t CreateChannels(Channel& c1, Channel& c2) {
|
||||
z_cap_t chan1, chan2;
|
||||
RET_ERR(ZChannelCreate(&chan1, &chan2));
|
||||
|
||||
c1.adopt_cap(chan1);
|
||||
c2.adopt_cap(chan2);
|
||||
return glcr::OK;
|
||||
}
|
||||
47
lib/mammoth/ipc/channel.h
Normal file
47
lib/mammoth/ipc/channel.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <stdint.h>
|
||||
#include <zcall.h>
|
||||
|
||||
class Channel {
|
||||
public:
|
||||
Channel() {}
|
||||
void adopt_cap(uint64_t id);
|
||||
z_cap_t release_cap();
|
||||
z_cap_t cap();
|
||||
|
||||
z_err_t WriteStr(const char* msg);
|
||||
z_err_t ReadStr(char* buffer, uint64_t* size);
|
||||
|
||||
template <typename T>
|
||||
z_err_t WriteStruct(T*);
|
||||
|
||||
template <typename T>
|
||||
z_err_t ReadStructAndCap(T*, uint64_t*);
|
||||
|
||||
// FIXME: Close channel here.
|
||||
~Channel() {}
|
||||
|
||||
private:
|
||||
z_cap_t chan_cap_ = 0;
|
||||
};
|
||||
|
||||
uint64_t CreateChannels(Channel& c1, Channel& c2);
|
||||
|
||||
template <typename T>
|
||||
z_err_t Channel::WriteStruct(T* obj) {
|
||||
return ZChannelSend(chan_cap_, sizeof(T), obj, 0, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
z_err_t Channel::ReadStructAndCap(T* obj, uint64_t* cap) {
|
||||
uint64_t num_bytes = sizeof(T);
|
||||
uint64_t num_caps = 1;
|
||||
RET_ERR(ZChannelRecv(chan_cap_, &num_bytes, obj, &num_caps, cap));
|
||||
|
||||
if (num_caps != 1 || num_bytes != sizeof(T)) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
5
lib/mammoth/ipc/endpoint_client.cpp
Normal file
5
lib/mammoth/ipc/endpoint_client.cpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include "ipc/endpoint_server.h"
|
||||
|
||||
glcr::UniquePtr<EndpointClient> EndpointClient::AdoptEndpoint(z_cap_t cap) {
|
||||
return glcr::UniquePtr<EndpointClient>(new EndpointClient(cap));
|
||||
}
|
||||
65
lib/mammoth/ipc/endpoint_client.h
Normal file
65
lib/mammoth/ipc/endpoint_client.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/pair.h>
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <zcall.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
class EndpointClient {
|
||||
public:
|
||||
EndpointClient() = delete;
|
||||
EndpointClient(const EndpointClient&) = delete;
|
||||
EndpointClient& operator=(const EndpointClient&) = delete;
|
||||
|
||||
static glcr::UniquePtr<EndpointClient> AdoptEndpoint(z_cap_t cap);
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> CallEndpointGetCap(const Req& req);
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<Resp> CallEndpoint(const Req& req);
|
||||
|
||||
z_cap_t GetCap() const { return cap_; }
|
||||
|
||||
private:
|
||||
EndpointClient(uint64_t cap) : cap_(cap) {}
|
||||
z_cap_t cap_;
|
||||
};
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> EndpointClient::CallEndpointGetCap(
|
||||
const Req& req) {
|
||||
uint64_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, 0, nullptr, &reply_port_cap));
|
||||
|
||||
Resp resp;
|
||||
z_cap_t cap = 0;
|
||||
uint64_t num_caps = 1;
|
||||
uint64_t num_bytes = sizeof(Resp);
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, &cap));
|
||||
|
||||
if (num_bytes != sizeof(resp) || num_caps != 1) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
|
||||
return glcr::Pair{resp, cap};
|
||||
}
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<Resp> EndpointClient::CallEndpoint(const Req& req) {
|
||||
uint64_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, 0, nullptr, &reply_port_cap));
|
||||
|
||||
Resp resp;
|
||||
uint64_t num_bytes = sizeof(Resp);
|
||||
uint64_t num_caps = 0;
|
||||
RET_ERR(
|
||||
ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, nullptr));
|
||||
|
||||
if (num_bytes != sizeof(resp)) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
42
lib/mammoth/ipc/endpoint_server.cpp
Normal file
42
lib/mammoth/ipc/endpoint_server.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include "ipc/endpoint_server.h"
|
||||
|
||||
#include "mammoth/debug.h"
|
||||
|
||||
// Declared as friend in EndpointServer.
|
||||
void EndpointServerThreadBootstrap(void* endpoint_server) {
|
||||
reinterpret_cast<EndpointServer*>(endpoint_server)->ServerThread();
|
||||
}
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<EndpointClient>> EndpointServer::CreateClient() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_cap_, ~(kZionPerm_Read), &client_cap));
|
||||
return EndpointClient::AdoptEndpoint(client_cap);
|
||||
}
|
||||
|
||||
Thread EndpointServer::RunServer() {
|
||||
return Thread(EndpointServerThreadBootstrap, this);
|
||||
}
|
||||
|
||||
void EndpointServer::ServerThread() {
|
||||
while (true) {
|
||||
uint64_t message_size = kBufferSize;
|
||||
uint64_t reply_port_cap = 0;
|
||||
uint64_t num_caps = 0;
|
||||
glcr::ErrorCode err = static_cast<glcr::ErrorCode>(
|
||||
ZEndpointRecv(endpoint_cap_, &message_size, recieve_buffer_, &num_caps,
|
||||
nullptr, &reply_port_cap));
|
||||
if (err != glcr::OK) {
|
||||
dbgln("Error in receive: {x}", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
RequestContext request(recieve_buffer_, message_size);
|
||||
ResponseContext response(reply_port_cap);
|
||||
// FIXME: Consider pumping these errors into the response as well.
|
||||
check(HandleRequest(request, response));
|
||||
if (!response.HasWritten()) {
|
||||
dbgln("Returning without having written a response. Req type {x}",
|
||||
request.request_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
36
lib/mammoth/ipc/endpoint_server.h
Normal file
36
lib/mammoth/ipc/endpoint_server.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "mammoth/ipc/endpoint_client.h"
|
||||
#include "mammoth/request_context.h"
|
||||
#include "mammoth/response_context.h"
|
||||
#include "mammoth/thread.h"
|
||||
|
||||
class EndpointServer {
|
||||
public:
|
||||
EndpointServer() = delete;
|
||||
EndpointServer(const EndpointServer&) = delete;
|
||||
EndpointServer& operator=(const EndpointServer&) = delete;
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<EndpointClient>> CreateClient();
|
||||
|
||||
Thread RunServer();
|
||||
|
||||
virtual glcr::ErrorCode HandleRequest(RequestContext& request,
|
||||
ResponseContext& response) = 0;
|
||||
|
||||
protected:
|
||||
EndpointServer(z_cap_t cap) : endpoint_cap_(cap) {}
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_cap_;
|
||||
|
||||
static const uint64_t kBufferSize = 1024;
|
||||
uint8_t recieve_buffer_[kBufferSize];
|
||||
|
||||
friend void EndpointServerThreadBootstrap(void* endpoint_server);
|
||||
void ServerThread();
|
||||
};
|
||||
14
lib/mammoth/ipc/port_client.cpp
Normal file
14
lib/mammoth/ipc/port_client.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include "ipc/port_client.h"
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#include "mammoth/debug.h"
|
||||
|
||||
PortClient PortClient::AdoptPort(z_cap_t cap) { return PortClient(cap); }
|
||||
PortClient::PortClient(z_cap_t port_cap) : port_cap_(port_cap) {}
|
||||
|
||||
glcr::ErrorCode PortClient::WriteString(glcr::String str, z_cap_t cap) {
|
||||
return static_cast<glcr::ErrorCode>(
|
||||
ZPortSend(port_cap_, str.length() + 1, str.cstr(), 1, &cap));
|
||||
}
|
||||
31
lib/mammoth/ipc/port_client.h
Normal file
31
lib/mammoth/ipc/port_client.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <glacier/string/string.h>
|
||||
#include <stdint.h>
|
||||
#include <zcall.h>
|
||||
|
||||
class PortClient {
|
||||
public:
|
||||
PortClient() {}
|
||||
static PortClient AdoptPort(z_cap_t port_cap);
|
||||
|
||||
template <typename T>
|
||||
z_err_t WriteMessage(const T& obj, z_cap_t cap);
|
||||
|
||||
glcr::ErrorCode WriteString(glcr::String str, z_cap_t cap);
|
||||
|
||||
z_cap_t cap() { return port_cap_; }
|
||||
|
||||
bool empty() { return port_cap_ == 0; }
|
||||
|
||||
private:
|
||||
z_cap_t port_cap_ = 0;
|
||||
|
||||
PortClient(z_cap_t port_cap);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
z_err_t PortClient::WriteMessage(const T& obj, z_cap_t cap) {
|
||||
return ZPortSend(port_cap_, sizeof(obj), &obj, 1, &cap);
|
||||
}
|
||||
46
lib/mammoth/ipc/port_server.cpp
Normal file
46
lib/mammoth/ipc/port_server.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "ipc/port_server.h"
|
||||
|
||||
#include <zcall.h>
|
||||
|
||||
glcr::ErrorOr<PortServer> PortServer::Create() {
|
||||
z_cap_t port;
|
||||
RET_ERR(ZPortCreate(&port));
|
||||
return PortServer(port);
|
||||
}
|
||||
|
||||
PortServer PortServer::AdoptCap(z_cap_t cap) { return PortServer(cap); }
|
||||
|
||||
PortServer::PortServer(z_cap_t port_cap) : port_cap_(port_cap) {}
|
||||
|
||||
glcr::ErrorOr<PortClient> PortServer::CreateClient() {
|
||||
z_cap_t new_port;
|
||||
RET_ERR(ZCapDuplicate(port_cap_, ~(kZionPerm_Read), &new_port));
|
||||
return PortClient::AdoptPort(new_port);
|
||||
}
|
||||
|
||||
glcr::ErrorCode PortServer::RecvCap(uint64_t *num_bytes, char *msg,
|
||||
uint64_t *cap) {
|
||||
uint64_t caps = 1;
|
||||
RET_ERR(ZPortRecv(port_cap_, num_bytes, reinterpret_cast<uint8_t *>(msg),
|
||||
&caps, cap));
|
||||
|
||||
if (caps != 1) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorCode PortServer::PollForIntCap(uint64_t *msg, uint64_t *cap) {
|
||||
uint64_t bytes = sizeof(uint64_t);
|
||||
uint64_t caps = 1;
|
||||
RET_ERR(ZPortPoll(port_cap_, &bytes, reinterpret_cast<uint8_t *>(msg), &caps,
|
||||
cap));
|
||||
|
||||
if (bytes != sizeof(uint64_t)) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
if (caps != 1) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
24
lib/mammoth/ipc/port_server.h
Normal file
24
lib/mammoth/ipc/port_server.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "mammoth/ipc/port_client.h"
|
||||
|
||||
class PortServer {
|
||||
public:
|
||||
static glcr::ErrorOr<PortServer> Create();
|
||||
static PortServer AdoptCap(z_cap_t cap);
|
||||
|
||||
glcr::ErrorOr<PortClient> CreateClient();
|
||||
|
||||
glcr::ErrorCode RecvCap(uint64_t* num_bytes, char* msg, uint64_t* cap);
|
||||
glcr::ErrorCode PollForIntCap(uint64_t* msg, uint64_t* cap);
|
||||
|
||||
z_cap_t cap() { return port_cap_; }
|
||||
|
||||
private:
|
||||
z_cap_t port_cap_;
|
||||
|
||||
PortServer(z_cap_t cap);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue