From 8fabfa5fb3d53ccdf0ad88d13f380acc3fd0d80f Mon Sep 17 00:00:00 2001 From: TDF-PL-038 <145844128+tdf-pl-038@users.noreply.github.com> Date: Sat, 18 Nov 2023 09:34:21 +0100 Subject: [PATCH] TMP --- README.md | 29 ++++-- .../src/main/java/org/wot/tak/client/App.java | 2 +- .../resources/protocol/xml/wot/Detail.xsd | 2 +- .../resources/protocol/xml/wot/FlowTags.xsd | 2 +- .../connectors/SSLConnectorTest.java | 91 +++++++++++------- .../messages/ClientProtobufMessage.java | 14 +-- .../connection/messages/ClientXmlMessage.java | 94 +++++++++++-------- 7 files changed, 142 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 2972d6e..f24ff84 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,33 @@ # TakConn ## Założenia projektu -Projekt ma na celu stworzenie narzędzia integracji serwera TAK z dowolnym oprogramowaniem wykorzystującym kod Java lub C#, w zakresie wymiany komunikatów formatu CoT. -Oprogramowanie umożliwia wysyłanie wiadomości formatu CoT na serwer TAK przy wykorzystaniu zdefiniowanych sposobów komunikacji. +Projekt ma na celu stworzenie narzędzia integracji serwera TAK z dowolnym oprogramowaniem uruchamianym na maszynie +wirtualnej Java (Java Virtual Machine, JVM) lub kompilowanym z kodu bajtowego Javy do kodu maszynowego (np. przy użyciu +Graal VM). Integracja odbywa się w zakresie możliwości wymiany komunikatów protokołu COT (Cursor On Target), zarówno w +wersji klasycznej w formacie XML, jak i w wersji nowszej opartej na formacie Protocol Buffers. ## Stan projektu -Obecnie zaimplementowane funkcjonalności w języku Java: -- Połączenie TCP bez uwierzytelniania. -- Połączenie TCP przy uwierzytelnieniu certyfikatem. -- Połączenie UDP. +Obecnie zaimplementowane funkcjonalności: +- Połączenie TCP/SSL do serwera przy uwierzytelnieniu certyfikatem, z negocjacją formatu protokołu XML->Protobuff +- Połączenie TCP do serwera bez uwierzytelniania, z negocjacją formatu protokołu XML->Protobuff. + +Obecnie zaimplementowane funkcjonalności w formie prototypu: +- Połączenie TCP do serwera. +- Połączenie UDP do serwera. Lista funkcjonalności w trakcie implementacji: -- Połączenie TCP przy uwierzytelnieniu użytkownikiem i hasłem. -- Połączenie TCP przy uwierzytelnieniu certyfikatem, użytkownikiem i hasłem. +- Połączenie TCP do serwera przy uwierzytelnieniu użytkownikiem i hasłem. +- Połączenie TCP do serwera przy uwierzytelnieniu certyfikatem, użytkownikiem i hasłem. + +Planowane funkcjonalności: +- Komunikacja Mesh UDP typu Multicast bezpośrednio z innymi urządzeniami. +- Komunikacja Mesh Point-Point TCP z konkretnym urzadzeniem, z negocjacją formatu protokołu XML->Protobuff. -Kod w języku C# jest w trakcie tworzenia. +## Przykład: Połączenie TCP/SSL do serwera przy uwierzytelnieniu certyfikatem, z negocjacją formatu protokołu XML->Protobuff ## Certifikaty -Potrzebne są pliki truststore.p12 i user.p12 w katalogach java/src/main/resources/cot/cert i c#/src/WOT.TAK.Client/cot/cert +Potrzebne są pliki `truststore.p12` i `user.p12` w katalogach `java/src/main/resources/cot/cert` ## Plik konfiguracyjny (Java) diff --git a/client/src/main/java/org/wot/tak/client/App.java b/client/src/main/java/org/wot/tak/client/App.java index 35b8b91..6669b3e 100644 --- a/client/src/main/java/org/wot/tak/client/App.java +++ b/client/src/main/java/org/wot/tak/client/App.java @@ -152,7 +152,7 @@ private void sendFilesFromDirectoryUsingConnector(TAKServerConnector connector, for (File file : files) { var xml = Files.readString(file.toPath()); var event = EventMarshalling.fromBytes(xml.getBytes()); - connector.send(event); +// connector.send(event); } } } diff --git a/connection/src/main/resources/protocol/xml/wot/Detail.xsd b/connection/src/main/resources/protocol/xml/wot/Detail.xsd index 0ca38f3..046825b 100644 --- a/connection/src/main/resources/protocol/xml/wot/Detail.xsd +++ b/connection/src/main/resources/protocol/xml/wot/Detail.xsd @@ -211,7 +211,7 @@ Provides a place to annotate CoT with free text information. e.g. comments from other - users about the current COT. Used also fro the geoChat. + users about the current COT. Used also from the geoChat. the xml body of this class is used to transport the chat message diff --git a/connection/src/main/resources/protocol/xml/wot/FlowTags.xsd b/connection/src/main/resources/protocol/xml/wot/FlowTags.xsd index eabe88f..ecf59be 100644 --- a/connection/src/main/resources/protocol/xml/wot/FlowTags.xsd +++ b/connection/src/main/resources/protocol/xml/wot/FlowTags.xsd @@ -22,7 +22,7 @@ A system-specific flowtag identifier associated with the encapsulating CoT object. - The attribute value should be an xs:dateTime value. + The attribute value should be a xs:dateTime value. diff --git a/connection/src/test/java/org/wot/tak/connection/connectors/SSLConnectorTest.java b/connection/src/test/java/org/wot/tak/connection/connectors/SSLConnectorTest.java index 650c27c..4b42bf7 100644 --- a/connection/src/test/java/org/wot/tak/connection/connectors/SSLConnectorTest.java +++ b/connection/src/test/java/org/wot/tak/connection/connectors/SSLConnectorTest.java @@ -20,7 +20,7 @@ import org.wot.tak.connection.messages.ClientXmlMessage; import org.wot.tak.connection.protocol.ProtocolVersion; import org.wot.tak.connection.protocol.protobuf.DetailMarshalling; -import org.wot.tak.connection.protocol.xml.EventMarshalling; +import org.wot.tak.connection.protocol.xml.Detail; import org.wot.tak.connection.protocol.protobuf.Takmessage; import org.wot.tak.connection.protocol.xml.Event; @@ -48,21 +48,24 @@ class SSLConnectorTest { void Connector_can_send_and_and_receive_messages_using_XML_protocol() throws Exception { var socketFactory = new SocketFactory(config); - var callsignPattern = "[{0}][{1}] Automated Integration Tests"; + var callsignPattern = "[{0}],[{1}],[XML] Automated Integration Tests"; var alphaCallsign = MessageFormat.format(callsignPattern, SSLConnector.class.getSimpleName(), "Alpha"); var bravoCallsign = MessageFormat.format(callsignPattern, SSLConnector.class.getSimpleName(), "Bravo"); - var alphaChatMessage = MessageFormat.format("Test message {0}", UUID.randomUUID()); - var bravoChatMessage = MessageFormat.format("Test message {0}", UUID.randomUUID()); + var alphaChatText = MessageFormat.format("Test message {0}", UUID.randomUUID()); + var bravoChatText = MessageFormat.format("Test message {0}", UUID.randomUUID()); - var alphaMessage = ClientXmlMessage.announcement(alphaUid, alphaCallsign, alphaChatMessage); - var bravoMessage = ClientXmlMessage.chat(bravoUid, alphaCallsign, bravoChatMessage); + var alphaAnnouncementMessage = ClientXmlMessage.announcement(alphaUid, alphaCallsign); + var alphaChatMessage = ClientXmlMessage.chat(alphaUid, alphaCallsign, alphaChatText); + + var bravoAnnouncementMessage = ClientXmlMessage.announcement(bravoUid, bravoCallsign); + var bravoChatMessage = ClientXmlMessage.chat(bravoUid, bravoCallsign, bravoChatText); var alphaReceivedMessages = new CopyOnWriteArrayList(); - var alphaHandler = createXmlMessageReceiver(alphaReceivedMessages); + var alphaMessageHandler = createXmlMessageReceiver(alphaReceivedMessages); var bravoReceivedMessages = new CopyOnWriteArrayList(); - var bravoHandler = createXmlMessageReceiver(bravoReceivedMessages); + var bravoMessageHandler = createXmlMessageReceiver(bravoReceivedMessages); var negotiateProtocolVersion = false; try (var alphaClient = new SSLConnector( @@ -70,24 +73,29 @@ void Connector_can_send_and_and_receive_messages_using_XML_protocol() throws Exc var bravoClient = new SSLConnector( serverUrl.getHost(), port.toString(), socketFactory, negotiateProtocolVersion)) { - alphaClient.connect(alphaHandler); - bravoClient.connect(bravoHandler); + alphaClient.connect(alphaMessageHandler); + bravoClient.connect(bravoMessageHandler); + + alphaClient.send(alphaAnnouncementMessage); + bravoClient.send(bravoAnnouncementMessage); - alphaClient.send(alphaMessage); - bravoClient.send(bravoMessage); + alphaClient.send(alphaChatMessage); + bravoClient.send(bravoChatMessage); Awaitility.await() - .atMost(2, TimeUnit.SECONDS) + .atMost(10, TimeUnit.SECONDS) .untilAsserted( () -> { assertThat(alphaReceivedMessages) - .anyMatch(message -> EventMarshalling.toString(message) - .contains(bravoChatMessage)); + .anyMatch(message -> hasChatMessage(message, bravoCallsign, bravoChatText)); assertThat(bravoReceivedMessages) - .anyMatch(message -> EventMarshalling.toString(message) - .contains(alphaChatMessage)); + .anyMatch(message -> hasChatMessage(message, alphaCallsign, alphaChatText)); }); + + + assertThat(alphaClient.getProtocolVersion()).isEqualTo(ProtocolVersion.XML); + assertThat(bravoClient.getProtocolVersion()).isEqualTo(ProtocolVersion.XML); } } @@ -95,24 +103,24 @@ void Connector_can_send_and_and_receive_messages_using_XML_protocol() throws Exc void Connector_can_send_and_and_receive_messages_using_Protobuf_protocol() throws Exception { var socketFactory = new SocketFactory(config); - var callsignPattern = "[{0}][{1}] Automated Integration Tests"; + var callsignPattern = "[{0}][{1}][Protobuf] Automated Integration Tests"; var alphaCallsign = MessageFormat.format(callsignPattern, SSLConnector.class.getSimpleName(), "Alpha"); var bravoCallsign = MessageFormat.format(callsignPattern, SSLConnector.class.getSimpleName(), "Bravo"); - var alphaChat = MessageFormat.format("Test message {0}", UUID.randomUUID()); - var bravoChat = MessageFormat.format("Test message {0}", UUID.randomUUID()); + var alphaChatText = MessageFormat.format("Test message {0}", UUID.randomUUID()); + var bravoChatText = MessageFormat.format("Test message {0}", UUID.randomUUID()); var alphaAnnouncementMessage = ClientProtobufMessage.announcement(alphaUid, alphaCallsign); - var alphaChatMessage = ClientProtobufMessage.chat(alphaUid, alphaCallsign, alphaChat); + var alphaChatMessage = ClientProtobufMessage.chat(alphaUid, alphaCallsign, alphaChatText); var bravoAnnouncementMessage = ClientProtobufMessage.announcement(bravoUid, bravoCallsign); - var bravoChatMessage = ClientProtobufMessage.chat(bravoUid, bravoCallsign, bravoChat); + var bravoChatMessage = ClientProtobufMessage.chat(bravoUid, bravoCallsign, bravoChatText); - var alphaClientMessages = new CopyOnWriteArrayList(); - var alphaClientHandler = createProtobufMessageReceiver(alphaClientMessages); + var alphaReceivedMessages = new CopyOnWriteArrayList(); + var alphaMessageHandler = createProtobufMessageReceiver(alphaReceivedMessages); - var bravoClientMessages = new CopyOnWriteArrayList(); - var bravoClientHandler = createProtobufMessageReceiver(bravoClientMessages); + var bravoReceivedMessages = new CopyOnWriteArrayList(); + var bravoMessageHandler = createProtobufMessageReceiver(bravoReceivedMessages); var negotiateProtocolVersion = true; try (var alphaClient = new SSLConnector( @@ -120,8 +128,8 @@ void Connector_can_send_and_and_receive_messages_using_Protobuf_protocol() throw var bravoClient = new SSLConnector( serverUrl.getHost(), port.toString(), socketFactory, negotiateProtocolVersion)) { - alphaClient.connect(alphaClientHandler); - bravoClient.connect(bravoClientHandler); + alphaClient.connect(alphaMessageHandler); + bravoClient.connect(bravoMessageHandler); Awaitility.await() .atMost(10, TimeUnit.SECONDS) @@ -135,19 +143,19 @@ void Connector_can_send_and_and_receive_messages_using_Protobuf_protocol() throw }); alphaClient.send(alphaAnnouncementMessage); - alphaClient.send(alphaChatMessage); bravoClient.send(bravoAnnouncementMessage); + alphaClient.send(alphaChatMessage); bravoClient.send(bravoChatMessage); Awaitility.await() .atMost(10, TimeUnit.SECONDS) .untilAsserted( () -> { - assertThat(alphaClientMessages) - .anyMatch(message -> hasChatMessage(message, bravoCallsign, bravoChat)); + assertThat(alphaReceivedMessages) + .anyMatch(message -> hasChatMessage(message, bravoCallsign, bravoChatText)); - assertThat(bravoClientMessages) - .anyMatch(message -> hasChatMessage(message, alphaCallsign, alphaChat)); + assertThat(bravoReceivedMessages) + .anyMatch(message -> hasChatMessage(message, alphaCallsign, alphaChatText)); }); } } @@ -200,4 +208,21 @@ private boolean hasChatMessage(Takmessage.TakMessage message, String senderCalls return senderCallSignMatched && chatMessageMatched; } + + @SneakyThrows + private boolean hasChatMessage(Event message, String senderCallsign, String chatMessage) { + var detail = Optional.ofNullable(message.getDetail()); + + var senderCallSignMatched = detail + .map(Detail::getChat) + .map(chat -> senderCallsign.equals(chat.getSenderCallsign())) + .orElse(false); + + var chatMessageMatched = detail + .map(Detail::getRemarks) + .map(remarks -> chatMessage.equals(remarks.getContent())) + .orElse(false); + + return senderCallSignMatched && chatMessageMatched; + } } diff --git a/connection/src/test/java/org/wot/tak/connection/messages/ClientProtobufMessage.java b/connection/src/test/java/org/wot/tak/connection/messages/ClientProtobufMessage.java index a6d3f23..99f0ae6 100644 --- a/connection/src/test/java/org/wot/tak/connection/messages/ClientProtobufMessage.java +++ b/connection/src/test/java/org/wot/tak/connection/messages/ClientProtobufMessage.java @@ -28,12 +28,14 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.GregorianCalendar; -import java.util.Random; import java.util.TimeZone; import java.util.UUID; public final class ClientProtobufMessage { + private static final double LATITUDE = 27.85009; + private static final double LONGITUDE = -81.063847; + private ClientProtobufMessage() { } @@ -51,8 +53,8 @@ public static Takmessage.TakMessage announcement(UUID uid, String callsign) .setStartTime(now) .setStaleTime(now + 5 * 60 * 1000) .setHow("h-g-i-g-o") - .setLat(27.85009) - .setLon(-81.063847) + .setLat(LATITUDE) + .setLon(LONGITUDE) .setHae(9999999.0) .setCe(9999999.0) .setLe(9999999.0) @@ -107,8 +109,6 @@ public static Takmessage.TakMessage chat(UUID uid, String callsign, String chatM throws DatatypeConfigurationException, XMLStreamException, JAXBException { var now = System.currentTimeMillis(); - var latitude = 52.2312 + (0.5 - new Random().nextFloat()) / 10; - var longitude = 21.016 + (0.5 - new Random().nextFloat()) / 10; var message = Takmessage.TakMessage.newBuilder() .setCotEvent(Cotevent.CotEvent.newBuilder() @@ -119,8 +119,8 @@ public static Takmessage.TakMessage chat(UUID uid, String callsign, String chatM .setStartTime(now) .setStaleTime(now + 5 * 60 * 1000) .setHow("h-g-i-g-o") - .setLat(latitude) - .setLon(longitude) + .setLat(LATITUDE) + .setLon(LONGITUDE) .setHae(9999999.0) .setCe(9999999.0) .setLe(9999999.0) diff --git a/connection/src/test/java/org/wot/tak/connection/messages/ClientXmlMessage.java b/connection/src/test/java/org/wot/tak/connection/messages/ClientXmlMessage.java index d5e1a79..ec389b4 100644 --- a/connection/src/test/java/org/wot/tak/connection/messages/ClientXmlMessage.java +++ b/connection/src/test/java/org/wot/tak/connection/messages/ClientXmlMessage.java @@ -1,35 +1,27 @@ package org.wot.tak.connection.messages; -import org.wot.tak.connection.protocol.xml.Contact; -import org.wot.tak.connection.protocol.xml.Detail; -import org.wot.tak.connection.protocol.xml.Event; -import org.wot.tak.connection.protocol.xml.Group; -import org.wot.tak.connection.protocol.xml.Point; -import org.wot.tak.connection.protocol.xml.Precisionlocation; -import org.wot.tak.connection.protocol.xml.Remarks; -import org.wot.tak.connection.protocol.xml.Status; -import org.wot.tak.connection.protocol.xml.Takv; -import org.wot.tak.connection.protocol.xml.Track; -import org.wot.tak.connection.protocol.xml.Uid; -import org.wot.tak.connection.protocol.xml.Usericon; +import org.wot.tak.connection.protocol.xml.*; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import java.math.BigDecimal; import java.math.BigInteger; +import java.text.MessageFormat; import java.util.GregorianCalendar; -import java.util.Random; import java.util.TimeZone; import java.util.UUID; public final class ClientXmlMessage { + private static final double LATITUDE = 40.2100278338638; + private static final double LONGITUDE = -92.6243997054913; + private static final double HAE = 246.411508368538; + private ClientXmlMessage() { } public static Event announcement(UUID uuid, String callsign) throws DatatypeConfigurationException { - var now = new GregorianCalendar(TimeZone.getTimeZone("UTC")); var xmlNow = DatatypeFactory.newInstance().newXMLGregorianCalendar(now); var stale = xmlNow.toGregorianCalendar(); @@ -38,7 +30,7 @@ public static Event announcement(UUID uuid, String callsign) var event = new Event(); event.setAccess("Undefined"); - event.setHow("h-g-i-g-o"); + event.setHow("h-e"); event.setStale(xmlStale); event.setStart(xmlNow); event.setTime(xmlNow); @@ -49,10 +41,10 @@ public static Event announcement(UUID uuid, String callsign) var point = new Point(); event.setPoint(point); point.setCe(BigDecimal.valueOf(9999999.0)); - point.setHae(BigDecimal.valueOf(9999999.0)); - point.setLat(BigDecimal.valueOf(27.85009)); + point.setHae(BigDecimal.valueOf(HAE)); + point.setLat(BigDecimal.valueOf(LATITUDE)); point.setLe(BigDecimal.valueOf(9999999.0)); - point.setLon(BigDecimal.valueOf(-81.063847)); + point.setLon(BigDecimal.valueOf(LONGITUDE)); var detail = new Detail(); event.setDetail(detail); @@ -65,9 +57,9 @@ public static Event announcement(UUID uuid, String callsign) var contact = new Contact(); detail.setContact(contact); contact.setCallsign(callsign); - contact.setEndpoint("1:sctp"); + contact.setEndpoint("*:-1:stcp"); - var status = new Status(); + var status = new Status(); detail.setStatus(status); status.setBattery(BigInteger.valueOf(98)); @@ -107,40 +99,64 @@ public static Event chat(UUID id, String callsign, String chatMessage) var xmlStale = DatatypeFactory.newInstance().newXMLGregorianCalendar(stale); stale.add(GregorianCalendar.MINUTE, 5); - var latitude = 52.2312 + (0.5 - new Random().nextFloat()) / 10; - var longitude = 21.016 + (0.5 - new Random().nextFloat()) / 10; + var chatroomName = "All Chat Rooms"; + var messageId = UUID.randomUUID().toString(); + var geoChatId = MessageFormat.format("GeoChat.{0}.{1}.{2}", id, chatroomName, messageId); + var remarkSource = "BAO.F.WinTAK." + id; var event = new Event(); - event.setVersion(BigDecimal.valueOf(2)); - event.setUid(id.toString()); - event.setType("a-n-G"); - event.setTime(xmlNow); - event.setStart(xmlNow); - event.setStale(xmlStale); + event.setAccess("Undefined"); event.setHow("h-g-i-g-o"); + event.setStale(xmlStale); + event.setStart(xmlNow); + event.setTime(xmlNow); + event.setType("b-t-f"); + event.setUid(geoChatId); + event.setVersion(BigDecimal.valueOf(2)); var point = new Point(); - point.setLat(BigDecimal.valueOf(latitude)); - point.setLon(BigDecimal.valueOf(longitude)); - point.setHae(BigDecimal.valueOf(9999999.0)); + event.setPoint(point); point.setCe(BigDecimal.valueOf(9999999.0)); + point.setHae(BigDecimal.valueOf(HAE)); + point.setLat(BigDecimal.valueOf(LATITUDE)); point.setLe(BigDecimal.valueOf(9999999.0)); - event.setPoint(point); + point.setLon(BigDecimal.valueOf(LONGITUDE)); var detail = new Detail(); event.setDetail(detail); + var chat = new Chat(); + detail.setChat(chat); + chat.setChatroom(chatroomName); + chat.setGroupOwner(false); + chat.setId(chatroomName); + chat.setMessageId(messageId); + chat.setSenderCallsign(callsign); + + var chatgrp = new Chatgrp(); + chat.setChatgrp(chatgrp); + chatgrp.setId(chatroomName); + chatgrp.setUid0(id.toString()); + chatgrp.setUid1(chatroomName); + + var link = new Link(); + detail.setLink(link); + link.setRelation("p-p"); + link.setType("a-f-G-U-C-I"); + link.setUid(id.toString()); + var remarks = new Remarks(); - remarks.setSource("Automated-Integration-Test" + callsign); - remarks.setSourceID("Automated-Integration-Test" + callsign); + detail.setRemarks(remarks); + remarks.setSource(remarkSource); + remarks.setSourceID(id.toString()); remarks.setTime(xmlNow); - remarks.setTo("All Chat Rooms"); + remarks.setTo(chatroomName); remarks.setContent(chatMessage); - detail.setRemarks(remarks); - var contact = new Contact(); - contact.setCallsign(callsign); - detail.setContact(contact); + var flowTags = new FlowTags(); + detail.setFlowTags(flowTags); + flowTags.getOtherAttributes().put( + new javax.xml.namespace.QName("TAK-Server-" + UUID.randomUUID()), xmlNow.toString()); return event; }