initial commit
This commit is contained in:
		
							
								
								
									
										34
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | cmake_minimum_required(VERSION 3.9 FATAL_ERROR) | ||||||
|  |  | ||||||
|  | add_library(solanaceae_ipc_client | ||||||
|  | 	./solanaceae/ipc1/zpp_rpc_cldev.hpp | ||||||
|  |  | ||||||
|  | 	./solanaceae/ipc1/tox_ipc_client.hpp | ||||||
|  | 	./solanaceae/ipc1/tox_ipc_client.cpp | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | target_include_directories(solana_ipc_client PUBLIC .) | ||||||
|  | target_compile_features(solana_ipc_client PRIVATE cxx_std_20) | ||||||
|  | target_link_libraries(solana_ipc_client PUBLIC | ||||||
|  | 	solanaceae_core | ||||||
|  | 	ipc | ||||||
|  | 	zpp_bits | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | ################################################# | ||||||
|  |  | ||||||
|  | add_library(solanaceae_ipc_server | ||||||
|  | 	./solanaceae/ipc1/zpp_rpc_cldev.hpp | ||||||
|  |  | ||||||
|  | 	./solanaceae/ipc1/tox_ipc_server.hpp | ||||||
|  | 	./solanaceae/ipc1/tox_ipc_server.cpp | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | target_include_directories(solana_ipc_server PUBLIC .) | ||||||
|  | target_compile_features(solana_ipc_server PRIVATE cxx_std_20) | ||||||
|  | target_link_libraries(solana_ipc_server PUBLIC | ||||||
|  | 	solanaceae_core | ||||||
|  | 	ipc | ||||||
|  | 	zpp_bits | ||||||
|  | ) | ||||||
|  |  | ||||||
							
								
								
									
										319
									
								
								solanaceae/ipc1/tox_ipc_client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								solanaceae/ipc1/tox_ipc_client.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | |||||||
|  | #include "./tox_ipc_client.hpp" | ||||||
|  |  | ||||||
|  | #include "./zpp_rpc_cldev.hpp" | ||||||
|  |  | ||||||
|  | #include <span> | ||||||
|  | #include <iostream> | ||||||
|  |  | ||||||
|  | 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<uint8_t> 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<uint8_t> 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<std::optional<uint32_t>, Tox_Err_Friend_Add> ToxIPCClient::toxFriendAdd(const std::vector<uint8_t>& address, std::string_view message) { | ||||||
|  | 	CL_BODY(toxFriendAdd, address, std::string{message}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<uint32_t>, Tox_Err_Friend_Add> ToxIPCClient::toxFriendAddNorequest(const std::vector<uint8_t>& public_key) { | ||||||
|  | 	CL_BODY(toxFriendAddNorequest, public_key) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Tox_Err_Friend_Delete ToxIPCClient::toxFriendDelete(uint32_t friend_number) { | ||||||
|  | 	CL_BODY(toxFriendDelete, friend_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<std::vector<uint8_t>>, Tox_Err_Friend_Get_Public_Key> ToxIPCClient::toxFriendGetPublicKey(uint32_t friend_number) { | ||||||
|  | 	CL_BODY(toxFriendGetPublicKey, friend_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<uint32_t>, 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<uint8_t> ToxIPCClient::toxHash(const std::vector<uint8_t>& data) { | ||||||
|  | 	CL_BODY(toxHash, data) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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<uint8_t>& data) { | ||||||
|  | 	CL_BODY(toxFriendSendLossyPacket, friend_number, data) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Tox_Err_Friend_Custom_Packet ToxIPCClient::toxFriendSendLosslessPacket(uint32_t friend_number, const std::vector<uint8_t>& data) { | ||||||
|  | 	CL_BODY(toxFriendSendLosslessPacket, friend_number, data) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<uint32_t>, 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<std::optional<uint32_t>, Tox_Err_Group_Join> ToxIPCClient::toxGroupJoin(const std::vector<uint8_t>& chat_id, std::string_view name, std::string_view password) { | ||||||
|  | 	CL_BODY(toxGroupJoin, chat_id, std::string{name}, std::string{password}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::optional<bool> 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<std::string> ToxIPCClient::toxGroupSelfGetName(uint32_t group_number) { | ||||||
|  | 	CL_BODY(toxGroupSelfGetName, group_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<std::string>, Tox_Err_Group_Peer_Query> ToxIPCClient::toxGroupPeerGetName(uint32_t group_number, uint32_t peer_id) { | ||||||
|  | 	CL_BODY(toxGroupPeerGetName, group_number, peer_id) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<Tox_Connection>, 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<std::string> ToxIPCClient::toxGroupGetTopic(uint32_t group_number) { | ||||||
|  | 	CL_BODY(toxGroupGetTopic, group_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::optional<std::string> ToxIPCClient::toxGroupGetName(uint32_t group_number) { | ||||||
|  | 	CL_BODY(toxGroupGetName, group_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::optional<std::vector<uint8_t>> ToxIPCClient::toxGroupGetChatId(uint32_t group_number) { | ||||||
|  | 	CL_BODY(toxGroupGetChatId, group_number) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::tuple<std::optional<uint32_t>, 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<uint8_t>& 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<uint8_t>& 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<std::optional<uint32_t>, Tox_Err_Group_Invite_Accept> ToxIPCClient::toxGroupInviteAccept(uint32_t friend_number, const std::vector<uint8_t>& invite_data, std::string_view name, std::string_view password) { | ||||||
|  | 	CL_BODY(toxGroupInviteAccept, friend_number, invite_data, std::string{name}, std::string{password}) | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										96
									
								
								solanaceae/ipc1/tox_ipc_client.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								solanaceae/ipc1/tox_ipc_client.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <solanaceae/core/tox_interface.hpp> | ||||||
|  | #include <solanaceae/core/tox_event_provider_base.hpp> | ||||||
|  |  | ||||||
|  | #include <ipc.h> | ||||||
|  |  | ||||||
|  | class ToxIPCClient : public ToxI, public ToxEventProviderBase { | ||||||
|  | 	ipc_sharedmemory _mem_rpc; | ||||||
|  | 	ipc_sharedsemaphore _sem_rpc_c; | ||||||
|  | 	ipc_sharedsemaphore _sem_rpc_s; | ||||||
|  |  | ||||||
|  | 	ipc_sharedmemory _mem_events; | ||||||
|  | 	ipc_sharedsemaphore _sem_events_lock; | ||||||
|  |  | ||||||
|  | 	public: | ||||||
|  | 		ToxIPCClient(void); | ||||||
|  | 		~ToxIPCClient(void); | ||||||
|  |  | ||||||
|  | 		bool connect(void); | ||||||
|  |  | ||||||
|  | 		// pulls events and handles them | ||||||
|  | 		void iterate(void); | ||||||
|  |  | ||||||
|  | 	public: // ToxI | ||||||
|  | 		Tox_Connection toxSelfGetConnectionStatus(void) override; | ||||||
|  | 		uint32_t toxIterationInterval(void) override; | ||||||
|  |  | ||||||
|  | 		std::vector<uint8_t> toxSelfGetAddress(void) override; | ||||||
|  |  | ||||||
|  | 		void toxSelfSetNospam(uint32_t nospam) override; | ||||||
|  | 		uint32_t toxSelfGetNospam(void) override; | ||||||
|  |  | ||||||
|  | 		std::vector<uint8_t> toxSelfGetPublicKey(void) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Set_Info toxSelfSetName(std::string_view name) override; | ||||||
|  | 		std::string toxSelfGetName(void) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Set_Info toxSelfSetStatusMessage(std::string_view status_message) override; | ||||||
|  | 		std::string toxSelfGetStatusMessage(void) override; | ||||||
|  |  | ||||||
|  | 		void toxSelfSetStatus(Tox_User_Status status) override; | ||||||
|  | 		Tox_User_Status toxSelfGetStatus(void) override; | ||||||
|  |  | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Friend_Add> toxFriendAdd(const std::vector<uint8_t>& address, std::string_view message) override; | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Friend_Add> toxFriendAddNorequest(const std::vector<uint8_t>& public_key) override; | ||||||
|  | 		Tox_Err_Friend_Delete toxFriendDelete(uint32_t friend_number) override; | ||||||
|  | 		std::tuple<std::optional<std::vector<uint8_t>>, Tox_Err_Friend_Get_Public_Key> toxFriendGetPublicKey(uint32_t friend_number) override; | ||||||
|  |  | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Friend_Send_Message> toxFriendSendMessage(uint32_t friend_number, Tox_Message_Type type, std::string_view message) override; | ||||||
|  |  | ||||||
|  | 		// should this be virtual at all? | ||||||
|  | 		// TODO: array? make it type agnostic? | ||||||
|  | 		std::vector<uint8_t> toxHash(const std::vector<uint8_t>& data) override; | ||||||
|  |  | ||||||
|  | 		// files | ||||||
|  | 		// conferece | ||||||
|  | 		Tox_Err_Conference_Send_Message toxConferenceSendMessage(uint32_t conference_number, Tox_Message_Type type, std::string_view message) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Friend_Custom_Packet toxFriendSendLossyPacket(uint32_t friend_number, const std::vector<uint8_t>& data) override; | ||||||
|  | 		Tox_Err_Friend_Custom_Packet toxFriendSendLosslessPacket(uint32_t friend_number, const std::vector<uint8_t>& data) override; | ||||||
|  |  | ||||||
|  | 		// dht | ||||||
|  | 		// udp | ||||||
|  | 		// tcp | ||||||
|  |  | ||||||
|  | 		// group | ||||||
|  |  | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Group_New> toxGroupNew(Tox_Group_Privacy_State privacy_state, std::string_view group_name, std::string_view name) override; | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Group_Join> toxGroupJoin(const std::vector<uint8_t>& chat_id, std::string_view name, std::string_view password) override; | ||||||
|  | 		std::optional<bool> toxGroupIsConnected(uint32_t group_number) override; | ||||||
|  | 		Tox_Err_Group_Reconnect toxGroupReconnect(uint32_t group_number) override; | ||||||
|  | 		Tox_Err_Group_Leave toxGroupLeave(uint32_t group_number, std::string_view part_message) override; | ||||||
|  |  | ||||||
|  | 		std::optional<std::string> toxGroupSelfGetName(uint32_t group_number) override; | ||||||
|  |  | ||||||
|  | 		std::tuple<std::optional<std::string>, Tox_Err_Group_Peer_Query> toxGroupPeerGetName(uint32_t group_number, uint32_t peer_id) override; | ||||||
|  | 		std::tuple<std::optional<Tox_Connection>, Tox_Err_Group_Peer_Query> toxGroupPeerGetConnectionStatus(uint32_t group_number, uint32_t peer_id) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Group_Topic_Set toxGroupSetTopic(uint32_t group_number, std::string_view topic) override; | ||||||
|  | 		std::optional<std::string> toxGroupGetTopic(uint32_t group_number) override; | ||||||
|  |  | ||||||
|  | 		std::optional<std::string> toxGroupGetName(uint32_t group_number) override; | ||||||
|  | 		std::optional<std::vector<uint8_t>> toxGroupGetChatId(uint32_t group_number) override; | ||||||
|  | 		// TODO: str | ||||||
|  |  | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Group_Send_Message> toxGroupSendMessage(uint32_t group_number, Tox_Message_Type type, std::string_view message) override; | ||||||
|  | 		Tox_Err_Group_Send_Private_Message toxGroupSendPrivateMessage(uint32_t group_number, uint32_t peer_id, Tox_Message_Type type, std::string_view message) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Group_Send_Custom_Packet toxGroupSendCustomPacket(uint32_t group_number, bool lossless, const std::vector<uint8_t>& data) override; | ||||||
|  | 		Tox_Err_Group_Send_Custom_Private_Packet toxGroupSendCustomPrivatePacket(uint32_t group_number, uint32_t peer_id, bool lossless, const std::vector<uint8_t>& data) override; | ||||||
|  |  | ||||||
|  | 		Tox_Err_Group_Invite_Friend toxGroupInviteFriend(uint32_t group_number, uint32_t friend_number) override; | ||||||
|  | 		std::tuple<std::optional<uint32_t>, Tox_Err_Group_Invite_Accept> toxGroupInviteAccept(uint32_t friend_number, const std::vector<uint8_t>& invite_data, std::string_view name, std::string_view password) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										147
									
								
								solanaceae/ipc1/tox_ipc_server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								solanaceae/ipc1/tox_ipc_server.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | |||||||
|  | #include "./tox_ipc_server.hpp" | ||||||
|  |  | ||||||
|  | #include "./zpp_rpc_cldev.hpp" | ||||||
|  |  | ||||||
|  | #include <tox/tox_events.h> | ||||||
|  |  | ||||||
|  | #include <span> | ||||||
|  | #include <thread> | ||||||
|  | #include <cstring> | ||||||
|  | #include <iostream> | ||||||
|  |  | ||||||
|  | ToxIPCServer::ToxIPCServer(ToxI& t, std::mutex& t_m) : _t(t), _t_m(t_m) { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ToxIPCServer::~ToxIPCServer(void) { | ||||||
|  | 	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); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool ToxIPCServer::connect(void) { | ||||||
|  | 	{ // rpc | ||||||
|  | 		ipc_mem_init(&_mem_rpc, "solana_toxI_rpc.shm", RPC_MEM_SIZE); // 2k prob enough for now | ||||||
|  | 		// server creates | ||||||
|  | 		if (ipc_mem_create(&_mem_rpc) != 0) { | ||||||
|  | 			std::cerr << "rpc shared mem already exists or failed\n"; | ||||||
|  | 			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"; | ||||||
|  | 			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"; | ||||||
|  | 			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_create(&_mem_events) != 0) { | ||||||
|  | 			std::cerr << "events shared mem already exists or failed\n"; | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		// TODO: do this with the lock? | ||||||
|  | 		ipc_mem_access(&_mem_events)[0] = EVENTS_READ; // reset | ||||||
|  |  | ||||||
|  | 		// 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | using namespace std::chrono_literals; | ||||||
|  |  | ||||||
|  | void ToxIPCServer::run(void) { | ||||||
|  | 	while (!_quit) { | ||||||
|  | 		// wait for client call | ||||||
|  | 		ipc_sem_decrement(&_sem_rpc_c); | ||||||
|  |  | ||||||
|  | 		if (_quit) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		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::server se{in, out, _t}; // ephimeral, should be cheap | ||||||
|  |  | ||||||
|  | 		{ | ||||||
|  | 			std::lock_guard lg{_t_m}; | ||||||
|  | 			se.serve().or_throw(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// signal client | ||||||
|  | 		ipc_sem_increment(&_sem_rpc_s); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ToxIPCServer::start(void) { | ||||||
|  | 	_thread = std::thread([this](){ this->run(); }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ToxIPCServer::stop(void) { | ||||||
|  | 	_quit = true; | ||||||
|  | 	ipc_sem_increment(&_sem_rpc_c); // hack, wake up server thread | ||||||
|  | 	_thread.join(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ToxIPCServer::updateEvents(const Tox_Events* events) { | ||||||
|  | 	if (uint32_t size = tox_events_bytes_size(events); size <= EVENTS_MEM_SIZE-1) { | ||||||
|  | 		_tmp_events_buf.resize(size); | ||||||
|  | 		tox_events_get_bytes(events, _tmp_events_buf.data()); | ||||||
|  | 	} else { | ||||||
|  | 		std::cerr << "events data bigger than space (" << size << " > " << EVENTS_MEM_SIZE-1 << ")\n"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ToxIPCServer::pub(void) { | ||||||
|  | 	if (_tmp_events_buf.empty()) { | ||||||
|  | 		return; // no events, no op | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// if noone is reading the events, this loop sleeps ~30ms | ||||||
|  | 	for (size_t i = 0; i < 10; i++) { | ||||||
|  | 		// grap mutex | ||||||
|  | 		ipc_sem_decrement(&_sem_events_lock); | ||||||
|  |  | ||||||
|  | 		// look at first byte if it got read | ||||||
|  | 		const uint8_t zbyte = ipc_mem_access(&_mem_events)[0]; | ||||||
|  | 		if (zbyte == EVENTS_WRITTEN) { | ||||||
|  | 			// if not, release mutex and short sleep | ||||||
|  | 			ipc_sem_increment(&_sem_events_lock); | ||||||
|  | 			std::this_thread::sleep_for(3ms); | ||||||
|  | 		} else { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// after loop we write events (potentially overwriting) | ||||||
|  |  | ||||||
|  | 	// memcpy new events, set first byte | ||||||
|  | 	std::memcpy(ipc_mem_access(&_mem_events)+1, _tmp_events_buf.data(), _tmp_events_buf.size()); | ||||||
|  | 	ipc_mem_access(&_mem_events)[0] = EVENTS_WRITTEN; | ||||||
|  |  | ||||||
|  | 	_tmp_events_buf.clear(); // TODO: just mark read, and keep around | ||||||
|  |  | ||||||
|  | 	// release mutex | ||||||
|  | 	ipc_sem_increment(&_sem_events_lock); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										51
									
								
								solanaceae/ipc1/tox_ipc_server.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								solanaceae/ipc1/tox_ipc_server.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | //#include <solanaceae/core/tox_interface.hpp> | ||||||
|  |  | ||||||
|  | #include <ipc.h> | ||||||
|  |  | ||||||
|  | #include <atomic> | ||||||
|  | #include <mutex> | ||||||
|  | #include <thread> | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
|  | // fwd | ||||||
|  | struct ToxI; | ||||||
|  | struct Tox_Events; | ||||||
|  |  | ||||||
|  | class ToxIPCServer { | ||||||
|  | 	ipc_sharedmemory _mem_rpc; | ||||||
|  | 	ipc_sharedsemaphore _sem_rpc_c; | ||||||
|  | 	ipc_sharedsemaphore _sem_rpc_s; | ||||||
|  |  | ||||||
|  | 	ipc_sharedmemory _mem_events; | ||||||
|  | 	ipc_sharedsemaphore _sem_events_lock; | ||||||
|  |  | ||||||
|  | 	ToxI& _t; | ||||||
|  | 	std::mutex& _t_m; | ||||||
|  |  | ||||||
|  | 	std::atomic_bool _quit = false; | ||||||
|  |  | ||||||
|  | 	std::thread _thread; | ||||||
|  |  | ||||||
|  | 	std::vector<uint8_t> _tmp_events_buf; | ||||||
|  |  | ||||||
|  | 	void run(void); | ||||||
|  |  | ||||||
|  | 	public: | ||||||
|  | 		ToxIPCServer(ToxI& t, std::mutex& t_m); | ||||||
|  | 		~ToxIPCServer(void); | ||||||
|  |  | ||||||
|  | 		bool connect(void); | ||||||
|  |  | ||||||
|  | 		// starts a thread and serves | ||||||
|  | 		void start(void); | ||||||
|  | 		void stop(void); | ||||||
|  |  | ||||||
|  | 		// take events, serialize | ||||||
|  | 		void updateEvents(const Tox_Events* events); | ||||||
|  |  | ||||||
|  | 		// this might sleep for longer, and events might get discarded | ||||||
|  | 		void pub(void); | ||||||
|  | }; | ||||||
|  |  | ||||||
							
								
								
									
										56
									
								
								solanaceae/ipc1/zpp_rpc_cldev.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								solanaceae/ipc1/zpp_rpc_cldev.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <solanaceae/core/tox_interface.hpp> | ||||||
|  |  | ||||||
|  | #include <zpp_bits/zpp_bits.h> | ||||||
|  |  | ||||||
|  | static constexpr size_t RPC_MEM_SIZE = 1024u * 4u; // 4kb | ||||||
|  | static constexpr size_t EVENTS_MEM_SIZE = 1024u * 1024u * 64u; // 64mb | ||||||
|  |  | ||||||
|  | static constexpr uint8_t EVENTS_WRITTEN = 0x05; | ||||||
|  | static constexpr uint8_t EVENTS_READ = 0x00; | ||||||
|  |  | ||||||
|  | using namespace zpp::bits::literals; | ||||||
|  |  | ||||||
|  | using ToxI_rpc = zpp::bits::rpc< | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetConnectionStatus, "ToxI::toxSelfGetConnectionStatus"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxIterationInterval, "ToxI::toxIterationInterval"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetAddress, "ToxI::toxSelfGetAddress"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfSetNospam, "ToxI::toxSelfSetNospam"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetNospam, "ToxI::toxSelfGetNospam"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetPublicKey, "ToxI::toxSelfGetPublicKey"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfSetName_str, "ToxI::toxSelfSetName"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetName, "ToxI::toxSelfGetName"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfSetStatusMessage_str, "ToxI::toxSelfSetStatusMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetStatusMessage, "ToxI::toxSelfGetStatusMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfSetStatus, "ToxI::toxSelfSetStatus"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxSelfGetStatus, "ToxI::toxSelfGetStatus"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendAdd_str, "ToxI::toxFriendAdd"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendAddNorequest, "ToxI::toxFriendAddNorequest"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendDelete, "ToxI::toxFriendDelete"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendGetPublicKey, "ToxI::toxFriendGetPublicKey"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendSendMessage_str, "ToxI::toxFriendSendMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxHash, "ToxI::toxHash"_sha1_int>, // TODO: remove lol | ||||||
|  | 	zpp::bits::bind<&ToxI::toxConferenceSendMessage_str, "ToxI::toxConferenceSendMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendSendLossyPacket, "ToxI::toxFriendSendLossyPacket"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxFriendSendLosslessPacket, "ToxI::toxFriendSendLosslessPacket"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupNew_str, "ToxI::toxGroupNew"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupJoin_str, "ToxI::toxGroupJoin"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupIsConnected, "ToxI::toxGroupIsConnected"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupReconnect, "ToxI::toxGroupReconnect"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupLeave_str, "ToxI::toxGroupLeave"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSelfGetName, "ToxI::toxGroupSelfGetName"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupPeerGetName, "ToxI::toxGroupPeerGetName"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupPeerGetConnectionStatus, "ToxI::toxGroupPeerGetConnectionStatus"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSetTopic_str, "ToxI::toxGroupSetTopic"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupGetTopic, "ToxI::toxGroupGetTopic"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupGetName, "ToxI::toxGroupGetName"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupGetChatId, "ToxI::toxGroupGetChatId"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSendMessage_str, "ToxI::toxGroupSendMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSendPrivateMessage_str, "ToxI::toxGroupSendPrivateMessage"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSendCustomPacket, "ToxI::toxGroupSendCustomPacket"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupSendCustomPrivatePacket, "ToxI::toxGroupSendCustomPrivatePacket"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupInviteFriend, "ToxI::toxGroupInviteFriend"_sha1_int>, | ||||||
|  | 	zpp::bits::bind<&ToxI::toxGroupInviteAccept_str, "ToxI::toxGroupInviteAccept"_sha1_int> | ||||||
|  | >; | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user