OpenCPN Partial API docs
ipc_api.cpp
1 /***************************************************************************
2  * Copyright (C) 2023 Alec Leamas *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 2 of the License, or *
7  * (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License *
15  * along with this program; if not, write to the *
16  * Free Software Foundation, Inc., *
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18  ***************************************************************************/
19 
20 #include <sstream>
21 
22 #include <wx/filename.h>
23 
24 #include "model/ipc_api.h"
25 #include "model/base_platform.h"
26 #include "model/logger.h"
27 #include "model/ocpn_utils.h"
28 
29 IpcServer* IpcConnection::s_instance = nullptr;
30 
31 // FIXME (leamas) Bad name
32 std::string GetSocketPath() {
33  auto const static sep = static_cast<char>(wxFileName::GetPathSeparator());
34  auto dirpath = g_BasePlatform->GetPrivateDataDir();
35  if (!wxFileName::DirExists(dirpath)) wxFileName::Mkdir(dirpath);
36  return dirpath.ToStdString() + sep + "opencpn-ipc";
37 }
38 
39 IpcClient::IpcClient(const std::string& path) {
40  connection = MakeConnection("localhost", path, "OpenCPN");
41  if (!connection)
42  throw LocalApiException(std::string("Cannot connect to: ") + path);
43 };
44 
45 
46 LocalApiResult IpcClient::SendQuit() {
47  if (connection->Execute(wxString("quit"))) {
48  return LocalApiResult(true, "");
49  } else {
50  return LocalApiResult(false, "Server error running quit command");
51  }
52 }
53 
54 
55 LocalApiResult IpcClient::SendRaise() {
56  if (connection->Execute(wxString("raise"))) {
57  return LocalApiResult(true, "");
58  } else {
59  return LocalApiResult(false, "Server error running raise command");
60  }
61 }
62 
63 
64 LocalApiResult IpcClient::SendOpen(const char* path) {
65  const void* reply = connection->Request(wxString("open " ) + path);
66  if (reply) return LocalApiResult(true, static_cast<const char*>(reply));
67  return LocalApiResult(false, "");
68 }
69 
70 
71 LocalApiResult IpcClient::GetRestEndpoint() {
72  const void* reply = connection->Request("get_rest_endpoint");
73  if (reply) {
74  return LocalApiResult(true, static_cast<const char*>(reply));
75  }
76  return LocalApiResult(false, "Server error running get_rest_endpoint");
77 }
78 
79 LocalServerApi& IpcConnection::GetInstance() {
80  if (!s_instance) s_instance = new IpcServer(GetSocketPath());
81  return *s_instance;
82 }
83 
84 void IpcConnection::ReleaseInstance() {
85  if (s_instance) {
86  delete s_instance;
87  s_instance = nullptr;
88  }
89 }
90 
91 bool IpcConnection::OnExec(const wxString&, const wxString& data) {
92  if (data == "quit") {
93  server.on_quit.Notify();
94  return true;
95  } else if (data == "raise") {
96  server.on_raise.Notify();
97  return true;
98  } else {
99  return false;
100  }
101 }
102 
103 const void* IpcConnection::OnRequest(const wxString& topic,
104  const wxString& item, size_t* size,
105  wxIPCFormat format) {
106  if (format != wxIPC_TEXT) return 0;
107 
108  std::string line = item.ToStdString();
109  if (ocpn::startswith(line, "get_rest_endpoint")) {
110  buffer = server.get_rest_api_endpoint_cb();
111  if (size) *size = buffer.size();
112  return buffer.c_str();
113  } else if( ocpn::startswith(line, "open")) {
114  auto words = ocpn::split(line.c_str(), " ");
115  if (words.size() != 2) {
116  wxLogWarning("Illegal open cmd line: %s", line.c_str());
117  return 0;
118  }
119  bool ok = server.open_file_cb(words[1]);
120  const char* reply = ok ? "ok" : "fail";
121  if (size) *size = strlen(reply);
122  return reply;
123  } else {
124  wxLogWarning("Illegal cmd line: %s", line.c_str());
125  return 0;
126  }
127 }
wxString & GetPrivateDataDir()
Return dir path for opencpn.log, etc., respecting -c cli option.
const void Notify()
Notify all listeners, no data supplied.
bool OnExec(const wxString &, const wxString &data)
Handle commands without reply: quit and raise.
Definition: ipc_api.cpp:91
const void * OnRequest(const wxString &topic, const wxString &item, size_t *size, wxIPCFormat format)
Handle commands with a reply.
Definition: ipc_api.cpp:103
Implement LocalServerApi using a filesystem fifo/socket.
Definition: ipc_api.h:108
Base interface for local server command handling.
Definition: local_api.h:62
std::function< bool(const std::string &)> open_file_cb
Callback invoked on open command with a file path argument.
Definition: local_api.h:78
EventVar on_raise
Notified on the Raise command.
Definition: local_api.h:72
EventVar on_quit
Notified on the Quit command.
Definition: local_api.h:75