From 45c8bb73faaccd02255a9aba45d6c22b020de494 Mon Sep 17 00:00:00 2001 From: tadscottsmith <78445808+tadscottsmith@users.noreply.github.com> Date: Wed, 29 Nov 2023 14:40:45 -0600 Subject: [PATCH] Authorization features. --- .../broadcast/openmhz/OpenMHzBroadcaster.java | 69 +++++++++++-------- .../broadcast/openmhz/OpenMHzBuilder.java | 3 +- .../openmhz/OpenMHzConfiguration.java | 7 ++ .../broadcast/openmhz/OpenMHzEditor.java | 4 +- 4 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBroadcaster.java b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBroadcaster.java index c3ef5e25..4d1441a9 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBroadcaster.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBroadcaster.java @@ -70,7 +70,7 @@ /** - * Audio broadcaster to push completed audio recordings to the Rdio Scanner call upload API. + * Audio broadcaster to push completed audio recordings to the OpenMHz call upload API. * */ public class OpenMHzBroadcaster extends AbstractAudioBroadcaster @@ -81,6 +81,7 @@ private static final String MULTIPART_TYPE = "multipart"; private static final String DEFAULT_SUBTYPE = "form-data"; private static final String MULTIPART_FORM_DATA = MULTIPART_TYPE + "/" + DEFAULT_SUBTYPE; + private static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; private Queue mAudioRecordingQueue = new LinkedTransferQueue<>(); private ScheduledFuture mAudioRecordingProcessorFuture; private HttpClient mHttpClient = HttpClient.newBuilder() @@ -115,16 +116,16 @@ mLastConnectionAttempt = System.currentTimeMillis(); /** - * Rdio Scanner API does not currently expose a test method. + * OpenMHz API does not currently expose a test method. * TODO: FIX THIS */ - if(response != null)// && response.toLowerCase().startsWith("502 bad gateway")) + if(response == "OK")// && response.toLowerCase().startsWith("502 bad gateway")) { setBroadcastState(BroadcastState.CONNECTED); } else { - mLog.error("Error connecting to Rdio Scanner server on startup [" + response + "]"); + mLog.error("Error connecting to OpenMHz server on startup [" + response + "]"); setBroadcastState(BroadcastState.ERROR); } @@ -170,7 +171,7 @@ * server. If there is a connectivity or other issue, the broadcast state is set to temporary error and * the audio processor thread will persistently invoke this method to attempt a reconnect. * - * Rdio Scanner does not have a test API endpoint, so we look for the incomplete call response. + * OpenMHz does not have a test API endpoint, so we look for the incomplete call response. */ private boolean connected() { @@ -182,7 +183,7 @@ String response = testConnection(getBroadcastConfiguration()); mLastConnectionAttempt = System.currentTimeMillis(); - if(response != null && response.toLowerCase().startsWith("incomplete call data: no talkgroup")) + if(response != null && response == "200") { setBroadcastState(BroadcastState.CONNECTED); } @@ -256,11 +257,12 @@ } catch(IOException e) { - mLog.error("Rdio Scanner API - audio recording file not found - ignoring upload"); + mLog.error("OpenMHz - audio recording file not found - ignoring upload"); } if(audioBytes != null) { + String uri = getBroadcastConfiguration().getHost() + "/" + getBroadcastConfiguration().getSystemName() + "/upload"; OpenMHzBuilder bodyBuilder = new OpenMHzBuilder(); bodyBuilder @@ -272,17 +274,14 @@ .addPart(FormField.TALKGROUP_NUM, talkgroup) .addPart(FormField.EMERGENCY, 0) .addPart(FormField.API_KEY, getBroadcastConfiguration().getApiKey()) - .addPart(FormField.PATCHES, patches) + // For future use if OpenMHz supports patch information + //.addPart(FormField.PATCHES, patches) .addPart(FormField.SOURCE_LIST, "[{ \"pos\": 0.00, \"src\": " + radioId + "}]"); - //.addPart(FormField.FREQ_LIST, frequency) - - HttpRequest fileRequest = HttpRequest.newBuilder() - .uri(URI.create(getBroadcastConfiguration().getHost())) + .uri(URI.create(uri)) .header(HttpHeaders.CONTENT_TYPE, MULTIPART_FORM_DATA + "; boundary=" + bodyBuilder.getBoundary()) .header(HttpHeaders.USER_AGENT, "sdrtrunk") - //.header(HttpHeaders.CONTENT_TYPE, "application/octet-stream") .POST(bodyBuilder.build()) .build(); @@ -295,14 +294,14 @@ //We get socket reset exceptions occasionally when the remote server doesn't //fully read our request and immediately responds. setBroadcastState(BroadcastState.TEMPORARY_BROADCAST_ERROR); - mLog.error("Rdio Scanner API file upload fail [" + + mLog.error("OpenMHz API file upload fail [" + fileResponse.statusCode() + "] response [" + fileResponse.body() + "]"); } else { setBroadcastState(BroadcastState.TEMPORARY_BROADCAST_ERROR); - mLog.error("Rdio Scanner API file upload fail [" + + mLog.error("OpenMHz API file upload fail [" + fileResponse.statusCode() + "] response [" + fileResponse.body() + "]"); } @@ -324,7 +323,7 @@ else { setBroadcastState(BroadcastState.TEMPORARY_BROADCAST_ERROR); - mLog.error("Rdio Scanner API file upload fail [" + + mLog.error("OpenMHz API file upload fail [" + fileResponse.statusCode() + "] response [" + fileResponse.body() + "]"); } @@ -337,7 +336,7 @@ else { //Register an error for the file not found exception - mLog.error("Rdio Scanner API - upload file not found [" + + mLog.error("OpenMHz API - upload file not found [" + audioRecording.getPath().toString() + "]"); incrementErrorAudioCount(); broadcast(new BroadcastEvent(OpenMHzBroadcaster.this, @@ -547,21 +546,19 @@ */ public static String testConnection(OpenMHzConfiguration configuration) { + String uri = configuration.getHost() + "/" + configuration.getSystemName() + "/authorize"; + HttpClient httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_1_1) .followRedirects(HttpClient.Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(20)) .build(); - OpenMHzBuilder bodyBuilder = new OpenMHzBuilder(); - bodyBuilder.addPart(FormField.API_KEY, configuration.getApiKey()); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(configuration.getHost())) - .header(HttpHeaders.CONTENT_TYPE, MULTIPART_FORM_DATA + "; boundary=" + bodyBuilder.getBoundary()) + .uri(URI.create(uri)) + .header(HttpHeaders.CONTENT_TYPE, APPLICATION_FORM_URLENCODED) .header(HttpHeaders.USER_AGENT, "sdrtrunk") - .header(HttpHeaders.ACCEPT, "*/*") - .POST(bodyBuilder.build()) + .POST(HttpRequest.BodyPublishers.ofString("api_key="+configuration.getApiKey())) .build(); HttpResponse.BodyHandler responseHandler = HttpResponse.BodyHandlers.ofString(); @@ -570,7 +567,20 @@ { HttpResponse response = httpClient.send(request, responseHandler); String responseBody = response.body(); - return (responseBody != null ? responseBody : "(no response)") + " Status Code:" + response.statusCode(); + if (response.statusCode() == 200) + { + return "OK"; + } + else if(response.statusCode() == 403) + { + return "Invalid API Key"; + } + else if(response.statusCode() == 500) + { + return "Invalid System Name"; + } + + return "No Response"; } catch(Exception e) { @@ -597,20 +607,21 @@ config.setSystemName("systemx"); String response = testConnection(config); + mLog.error("Response: " + response); - if(response == null) + if(response == "OK") { mLog.debug("Test Successful!"); } else { - if(response.contains("1 Invalid-API-Key")) + if(response.contains("Invalid API Key")) { mLog.error("Invalid API Key"); } - else if(response.contains("1 API-Key-Access-Denied")) + else if(response.contains("Invalid System Name")) { - mLog.error("System ID not valid for API Key"); + mLog.error("Invalid System Name"); } else { diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBuilder.java b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBuilder.java index 406aab2d..0e971707 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBuilder.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzBuilder.java @@ -110,8 +110,7 @@ } StringBuilder sb= new StringBuilder(); sb.append(DASH_DASH).append(boundary).append("\r\n"); - sb.append("Content-Disposition: form-data; name=\"").append("call").append("\"; filename=\"test.m4a\"\r\n"); - sb.append("Content-Type: application/octet-stream\r\n\r\n"); + sb.append("Content-Disposition: form-data; name=\"").append("call").append("\"; filename=\"audio.mp3\"\r\n\r\n"); return sb.toString(); } diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzConfiguration.java b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzConfiguration.java index 8d778897..540c0f81 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzConfiguration.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzConfiguration.java @@ -39,6 +39,8 @@ */ public class OpenMHzConfiguration extends BroadcastConfiguration { + public static final String PRODUCTION_ENDPOINT = "https://api.openmhz.com"; + private StringProperty mSystemName = new SimpleStringProperty(); private StringProperty mApiKey = new SimpleStringProperty(); @@ -58,6 +60,11 @@ { super(format); + if(getHost() == null) + { + setHost(PRODUCTION_ENDPOINT); + } + //The parent class binds this property, so we unbind it and rebind it here mValid.unbind(); mValid.bind(Bindings.and(Bindings.and(Bindings.isNotNull(mSystemName), Bindings.isNotNull(mApiKey)), diff --git a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzEditor.java b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzEditor.java index 520fe6fc..07ccbedb 100644 --- a/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzEditor.java +++ b/src/main/java/io/github/dsheirer/audio/broadcast/openmhz/OpenMHzEditor.java @@ -152,7 +152,7 @@ GridPane.setConstraints(getApiKeyTextField(), 1, row); mEditorPane.getChildren().add(getApiKeyTextField()); - Label systemNameLabel = new Label("System Name"); + Label systemNameLabel = new Label("System Short Name"); GridPane.setHalignment(systemNameLabel, HPos.RIGHT); GridPane.setConstraints(systemNameLabel, 0, ++row); mEditorPane.getChildren().add(systemNameLabel); @@ -160,7 +160,7 @@ GridPane.setConstraints(getSystemNameTextField(), 1, row); mEditorPane.getChildren().add(getSystemNameTextField()); - Label hostLabel = new Label("OpenMHz URL"); + Label hostLabel = new Label("OpenMHz Upload Server (API)"); GridPane.setHalignment(hostLabel, HPos.RIGHT); GridPane.setConstraints(hostLabel, 0, ++row); mEditorPane.getChildren().add(hostLabel);