#include "./tox_ipc_client.hpp" #include "./zpp_rpc_cldev.hpp" #include #include using namespace zpp::bits::literals; ToxIPCClient::ToxIPCClient(void) { } ToxIPCClient::~ToxIPCClient(void) { // TODO: add free (not close) to ipc api #if 0 // they gone, so no ipc_mem_close(&_mem_rpc); ipc_sem_close(&_sem_rpc_c); ipc_sem_close(&_sem_rpc_s); ipc_mem_close(&_mem_events); ipc_sem_close(&_sem_events_lock); #endif } bool ToxIPCClient::connect(void) { // TODO: more cleanup? { // rpc ipc_mem_init(&_mem_rpc, "solana_toxI_rpc.shm", RPC_MEM_SIZE); // 2k prob enough for now // client expects it to exist if (ipc_mem_open_existing(&_mem_rpc) != 0) { std::cerr << "rpc shared mem not open\n"; ipc_mem_close(&_mem_rpc); return false; } // client write lock (server waits on this) ipc_sem_init(&_sem_rpc_c, "solana_toxI_rpc_client.lock"); if (ipc_sem_create(&_sem_rpc_c, 0) != 0) { std::cerr << "failed to create sem_rpc_c\n"; ipc_mem_close(&_mem_rpc); return false; } // server write lock (client waits on this) ipc_sem_init(&_sem_rpc_s, "solana_toxI_rpc_server.lock"); if (ipc_sem_create(&_sem_rpc_s, 0) != 0) { std::cerr << "failed to create sem_rpc_s\n"; ipc_mem_close(&_mem_rpc); return false; } // if no call is in progress, both sems are 0 } { // events ipc_mem_init(&_mem_events, "solana_toxEventsI_events.shm", EVENTS_MEM_SIZE); // server creates if (ipc_mem_open_existing(&_mem_events) != 0) { std::cerr << "events shared mem not open\n"; return false; } // mutex ipc_sem_init(&_sem_events_lock, "solana_toxEventsI_events.lock"); if (ipc_sem_create(&_sem_events_lock, 1) != 0) { std::cerr << "failed to create sem_events_lock\n"; return false; } } return true; } void ToxIPCClient::iterate(void) { Tox_Events* events = nullptr; // grap mutex ipc_sem_decrement(&_sem_events_lock); // read first byte const uint8_t zbyte = ipc_mem_access(&_mem_events)[0]; if (zbyte == EVENTS_WRITTEN) { // if WRITTEN, serl, release mutex events = tox_events_load(ipc_mem_access(&_mem_events)+1, EVENTS_MEM_SIZE-1); ipc_mem_access(&_mem_events)[0] = EVENTS_READ; ipc_sem_increment(&_sem_events_lock); } else { // if not, release mutex exit ipc_sem_increment(&_sem_events_lock); return; } // handle events if (events == nullptr) { std::cerr << "error: read back empty events list?\n"; return; } dispatchEvents(events); tox_events_free(events); } Tox_Connection ToxIPCClient::toxSelfGetConnectionStatus(void) { // we assume we can write (warn) zpp::bits::in in{std::span{ipc_mem_access(&_mem_rpc), RPC_MEM_SIZE}}; zpp::bits::out out{std::span{ipc_mem_access(&_mem_rpc), RPC_MEM_SIZE}}; // TODO: write magic on client and server to very // serl call ToxI_rpc::client cl{in, out}; // ephimeral, should be cheap // TODO: no throw // write to mem cl.request<"ToxI::toxSelfGetConnectionStatus"_sha1_int>().or_throw(); // inc sem ipc_sem_increment(&_sem_rpc_c); // wait on sem (block) ipc_sem_decrement(&_sem_rpc_s); // deserl res and return return cl.response<"ToxI::toxSelfGetConnectionStatus"_sha1_int>().or_throw(); } #define CL_SETUP_BUFS \ zpp::bits::in in{std::span{ipc_mem_access(&_mem_rpc), RPC_MEM_SIZE}}; \ zpp::bits::out out{std::span{ipc_mem_access(&_mem_rpc), RPC_MEM_SIZE}}; \ ToxI_rpc::client cl{in, out}; #define CL_REQUEST(X, ...) cl.request<"ToxI::" #X##_sha1_int>(__VA_ARGS__).or_throw(); #define CL_REQUEST_STR(X, ...) cl.request<"ToxI::" #X "_str"_sha1_int>(__VA_ARGS__).or_throw(); #define CL_SEMWAIT \ ipc_sem_increment(&_sem_rpc_c); \ ipc_sem_decrement(&_sem_rpc_s); #define CL_RESPONSE(X) return cl.response<"ToxI::" #X##_sha1_int>().or_throw(); #define CL_RESPONSE_STR(X) return cl.response<"ToxI::" #X "_str"_sha1_int>().or_throw(); // TODO: for real? #define CL_RESPONSE_VOID(X) cl.response<"ToxI::" #X##_sha1_int>().or_throw(); #define CL_BODY(X, ...) \ CL_SETUP_BUFS \ CL_REQUEST(X, __VA_ARGS__) \ CL_SEMWAIT \ CL_RESPONSE(X) #define CL_BODY_STR(X, ...) \ CL_SETUP_BUFS \ CL_REQUEST_STR(X, __VA_ARGS__) \ CL_SEMWAIT \ CL_RESPONSE_STR(X) #define CL_BODY_VOID(X, ...) \ CL_SETUP_BUFS \ CL_REQUEST(X, __VA_ARGS__) \ CL_SEMWAIT // TODO: response with void? uint32_t ToxIPCClient::toxIterationInterval(void) { CL_BODY(toxIterationInterval) } std::vector ToxIPCClient::toxSelfGetAddress(void) { CL_BODY(toxSelfGetAddress) } void ToxIPCClient::toxSelfSetNospam(uint32_t nospam) { CL_BODY_VOID(toxSelfSetNospam, nospam) } uint32_t ToxIPCClient::toxSelfGetNospam(void) { CL_BODY(toxSelfGetNospam) } std::vector ToxIPCClient::toxSelfGetPublicKey(void) { CL_BODY(toxSelfGetPublicKey) } Tox_Err_Set_Info ToxIPCClient::toxSelfSetName(std::string_view name) { CL_BODY(toxSelfSetName, std::string{name}) } std::string ToxIPCClient::toxSelfGetName(void) { CL_BODY(toxSelfGetName) } Tox_Err_Set_Info ToxIPCClient::toxSelfSetStatusMessage(std::string_view status_message) { CL_BODY(toxSelfSetStatusMessage, std::string{status_message}) } std::string ToxIPCClient::toxSelfGetStatusMessage(void) { CL_BODY(toxSelfGetStatusMessage) } void ToxIPCClient::toxSelfSetStatus(Tox_User_Status status) { CL_BODY_VOID(toxSelfSetStatus, status) } Tox_User_Status ToxIPCClient::toxSelfGetStatus(void) { CL_BODY(toxSelfGetStatus) } std::tuple, Tox_Err_Friend_Add> ToxIPCClient::toxFriendAdd(const std::vector& address, std::string_view message) { CL_BODY(toxFriendAdd, address, std::string{message}) } std::tuple, Tox_Err_Friend_Add> ToxIPCClient::toxFriendAddNorequest(const std::vector& public_key) { CL_BODY(toxFriendAddNorequest, public_key) } Tox_Err_Friend_Delete ToxIPCClient::toxFriendDelete(uint32_t friend_number) { CL_BODY(toxFriendDelete, friend_number) } std::tuple>, Tox_Err_Friend_Get_Public_Key> ToxIPCClient::toxFriendGetPublicKey(uint32_t friend_number) { CL_BODY(toxFriendGetPublicKey, friend_number) } std::tuple, Tox_Err_Friend_Send_Message> ToxIPCClient::toxFriendSendMessage(uint32_t friend_number, Tox_Message_Type type, std::string_view message) { CL_BODY(toxFriendSendMessage, friend_number, type, std::string{message}) } std::vector ToxIPCClient::toxHash(const std::vector& data) { CL_BODY(toxHash, data) } std::tuple, Tox_Err_Conference_Join> ToxIPCClient::toxConferenceJoin(uint32_t friend_number, const std::vector& cookie) { CL_BODY(toxConferenceJoin, friend_number, cookie) } Tox_Err_Conference_Send_Message ToxIPCClient::toxConferenceSendMessage(uint32_t conference_number, Tox_Message_Type type, std::string_view message) { CL_BODY(toxConferenceSendMessage, conference_number, type, std::string{message}) } Tox_Err_Friend_Custom_Packet ToxIPCClient::toxFriendSendLossyPacket(uint32_t friend_number, const std::vector& data) { CL_BODY(toxFriendSendLossyPacket, friend_number, data) } Tox_Err_Friend_Custom_Packet ToxIPCClient::toxFriendSendLosslessPacket(uint32_t friend_number, const std::vector& data) { CL_BODY(toxFriendSendLosslessPacket, friend_number, data) } std::tuple, Tox_Err_Group_New> ToxIPCClient::toxGroupNew(Tox_Group_Privacy_State privacy_state, std::string_view group_name, std::string_view name) { CL_BODY(toxGroupNew, privacy_state, std::string{group_name}, std::string{name}) } std::tuple, Tox_Err_Group_Join> ToxIPCClient::toxGroupJoin(const std::vector& chat_id, std::string_view name, std::string_view password) { CL_BODY(toxGroupJoin, chat_id, std::string{name}, std::string{password}) } std::optional ToxIPCClient::toxGroupIsConnected(uint32_t group_number) { CL_BODY(toxGroupIsConnected, group_number) } Tox_Err_Group_Reconnect ToxIPCClient::toxGroupReconnect(uint32_t group_number) { CL_BODY(toxGroupReconnect, group_number) } Tox_Err_Group_Leave ToxIPCClient::toxGroupLeave(uint32_t group_number, std::string_view part_message) { CL_BODY(toxGroupLeave, group_number, std::string{part_message}) } std::optional ToxIPCClient::toxGroupSelfGetName(uint32_t group_number) { CL_BODY(toxGroupSelfGetName, group_number) } std::tuple, Tox_Err_Group_Peer_Query> ToxIPCClient::toxGroupPeerGetName(uint32_t group_number, uint32_t peer_id) { CL_BODY(toxGroupPeerGetName, group_number, peer_id) } std::tuple, Tox_Err_Group_Peer_Query> ToxIPCClient::toxGroupPeerGetConnectionStatus(uint32_t group_number, uint32_t peer_id) { CL_BODY(toxGroupPeerGetConnectionStatus, group_number, peer_id) } Tox_Err_Group_Topic_Set ToxIPCClient::toxGroupSetTopic(uint32_t group_number, std::string_view topic) { CL_BODY(toxGroupSetTopic, group_number, std::string{topic}) } std::optional ToxIPCClient::toxGroupGetTopic(uint32_t group_number) { CL_BODY(toxGroupGetTopic, group_number) } std::optional ToxIPCClient::toxGroupGetName(uint32_t group_number) { CL_BODY(toxGroupGetName, group_number) } std::optional> ToxIPCClient::toxGroupGetChatId(uint32_t group_number) { CL_BODY(toxGroupGetChatId, group_number) } std::tuple, Tox_Err_Group_Send_Message> ToxIPCClient::toxGroupSendMessage(uint32_t group_number, Tox_Message_Type type, std::string_view message) { CL_BODY(toxGroupSendMessage, group_number, type, std::string{message}) } Tox_Err_Group_Send_Private_Message ToxIPCClient::toxGroupSendPrivateMessage(uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, std::string_view message) { CL_BODY(toxGroupSendPrivateMessage, group_number, peer_id, type, std::string{message}) } Tox_Err_Group_Send_Custom_Packet ToxIPCClient::toxGroupSendCustomPacket(uint32_t group_number, bool lossless, const std::vector& data) { CL_BODY(toxGroupSendCustomPacket, group_number, lossless, data) } Tox_Err_Group_Send_Custom_Private_Packet ToxIPCClient::toxGroupSendCustomPrivatePacket(uint32_t group_number, uint32_t peer_id, bool lossless, const std::vector& data) { CL_BODY(toxGroupSendCustomPrivatePacket, group_number, peer_id, lossless, data) } Tox_Err_Group_Invite_Friend ToxIPCClient::toxGroupInviteFriend(uint32_t group_number, uint32_t friend_number) { CL_BODY(toxGroupInviteFriend, group_number, friend_number) } std::tuple, Tox_Err_Group_Invite_Accept> ToxIPCClient::toxGroupInviteAccept(uint32_t friend_number, const std::vector& invite_data, std::string_view name, std::string_view password) { CL_BODY(toxGroupInviteAccept, friend_number, invite_data, std::string{name}, std::string{password}) }