81 socket.AssignDir( wxS(
"/tmp" ) );
83 socket.AssignDir( wxStandardPaths::Get().GetTempDir() );
85 socket.AppendDir( wxS(
"kicad" ) );
86 socket.SetFullName( wxS(
"api.sock" ) );
90 wxLogTrace(
traceApi, wxString::Format(
"Server: socket path %s could not be created",
100 wxFileName lockFilePath( socket.GetPath(), wxS(
"api.lock" ) );
102 int lockFile = open( lockFilePath.GetFullPath().c_str(), O_RDONLY | O_CREAT, 0600 );
104 if( lockFile >= 0 && flock( lockFile, LOCK_EX | LOCK_NB ) == 0 )
106 if( socket.Exists() )
108 wxLogTrace(
traceApi, wxString::Format(
"Server: cleaning up stale socket path %s",
109 socket.GetFullPath() ) );
110 wxRemoveFile( socket.GetFullPath() );
115 if( socket.Exists() )
117 socket.SetFullName( wxString::Format( wxS(
"api-%lu.sock" ), ::wxGetProcessId() ) );
119 if( socket.Exists() )
121 wxLogTrace(
traceApi, wxString::Format(
"Server: PID socket path %s already exists!",
122 socket.GetFullPath() ) );
127 m_server = std::make_unique<KINNG_REQUEST_SERVER>(
128 fmt::format(
"ipc://{}", socket.GetFullPath().ToStdString() ) );
137 log( fmt::format(
"--- KiCad API server started at {} ---\n",
SocketPath() ) );
188 ApiResponse notHandled;
189 notHandled.mutable_status()->set_status( ApiStatusCode::AS_NOT_READY );
190 notHandled.mutable_status()->set_error_message(
"KiCad is not ready to reply" );
191 m_server->Reply( notHandled.SerializeAsString() );
192 log(
"Got incoming request but was not yet ready to reply." );
196 wxCommandEvent* evt =
new wxCommandEvent( API_REQUEST_EVENT );
199 evt->SetClientData(
static_cast<void*
>( aRequest ) );
208 std::string& requestString = *
static_cast<std::string*
>( aEvent.GetClientData() );
211 if( !request.ParseFromString( requestString ) )
214 error.mutable_header()->set_kicad_token(
m_token );
215 error.mutable_status()->set_status( ApiStatusCode::AS_BAD_REQUEST );
216 error.mutable_status()->set_error_message(
"request could not be parsed" );
217 m_server->Reply( error.SerializeAsString() );
220 log(
"Response (ERROR): " + error.Utf8DebugString() );
224 log(
"Request: " + request.Utf8DebugString() );
226 if( !request.header().kicad_token().empty() &&
227 request.header().kicad_token().compare(
m_token ) != 0 )
230 error.mutable_header()->set_kicad_token(
m_token );
231 error.mutable_status()->set_status( ApiStatusCode::AS_TOKEN_MISMATCH );
232 error.mutable_status()->set_error_message(
233 "the provided kicad_token did not match this KiCad instance's token" );
234 m_server->Reply( error.SerializeAsString() );
237 log(
"Response (ERROR): " + error.Utf8DebugString() );
246 result = handler->Handle( request );
250 else if(
result.error().status() != ApiStatusCode::AS_UNHANDLED )
262 log(
"Response: " +
result->Utf8DebugString() );
267 error.mutable_status()->CopyFrom(
result.error() );
268 error.mutable_header()->set_kicad_token(
m_token );
270 if(
result.error().status() == ApiStatusCode::AS_UNHANDLED )
272 std::string type =
"<unparseable Any>";
273 google::protobuf::Any::ParseAnyTypeUrl( request.message().type_url(), &type );
274 std::string msg = fmt::format(
"no handler available for request of type {}", type );
275 error.mutable_status()->set_error_message( msg );
278 m_server->Reply( error.SerializeAsString() );
281 log(
"Response (ERROR): " + error.Utf8DebugString() );
wxString result
Test unit parsing edge cases and error handling.