commit 16221f3c296fd14335951e1557d2cf4370cfb57f
Author: 2123000 <2123000@stud.hs-mannheim.de>
Date: Fri Apr 12 12:09:15 2024 +0200
Test
diff --git a/Service-Discovery/.classpath b/Service-Discovery/.classpath
new file mode 100644
index 0000000..8eabddc
--- /dev/null
+++ b/Service-Discovery/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Service-Discovery/.project b/Service-Discovery/.project
new file mode 100644
index 0000000..ca38c8b
--- /dev/null
+++ b/Service-Discovery/.project
@@ -0,0 +1,17 @@
+
+
+ Service-Discovery
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Service-Discovery/.settings/org.eclipse.jdt.core.prefs b/Service-Discovery/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..223b166
--- /dev/null
+++ b/Service-Discovery/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,14 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=15
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=15
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=15
diff --git a/Service-Discovery/bin/.gitignore b/Service-Discovery/bin/.gitignore
new file mode 100644
index 0000000..e01d7df
--- /dev/null
+++ b/Service-Discovery/bin/.gitignore
@@ -0,0 +1,2 @@
+/X.class
+/de/
diff --git a/Service-Discovery/src/X.java b/Service-Discovery/src/X.java
new file mode 100644
index 0000000..d524f13
--- /dev/null
+++ b/Service-Discovery/src/X.java
@@ -0,0 +1,9 @@
+
+public class X {
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+System.out.println("test");
+ }
+
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/AsciiChars.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/AsciiChars.java
new file mode 100644
index 0000000..e8248c2
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/AsciiChars.java
@@ -0,0 +1,78 @@
+package de.hs_mannheim.ffi.vs.syslog.model;
+
+/**
+ * helper class for RFC 5424 (https://datatracker.ietf.org/doc/html/rfc5424)
+ * compliant log messages as immutable Java objects - representation of a subset
+ * of printable strings of specific length
+ *
+ * @author Sandro Leuchter
+ *
+ */
+public abstract class AsciiChars {
+ private final String value;
+
+ public String value() {
+ return this.value;
+ }
+
+ protected AsciiChars(int length, String value) {
+ if (value != null) {
+ if (value.length() > length) {
+ throw new IllegalArgumentException(
+ "Stringlänge = " + value.length() + " > " + length);
+ }
+ for (int c : value.getBytes()) {
+ if (c < 33 || c > 126) {
+ throw new IllegalArgumentException(
+ "Stringinhalt nicht printable US-ASCII ohne Space");
+ }
+ }
+ }
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ if (value() == null || value().length() == 0) {
+ return "-";
+ } else {
+ return value();
+ }
+ }
+
+ static public final class L004 extends AsciiChars {
+ public L004(String value) {
+ super(4, value);
+ }
+ }
+
+ static public final class L012 extends AsciiChars {
+ public L012(String value) {
+ super(12, value);
+ }
+ }
+
+ static public final class L032 extends AsciiChars {
+ public L032(String value) {
+ super(32, value);
+ }
+ }
+
+ static public final class L048 extends AsciiChars {
+ public L048(String value) {
+ super(48, value);
+ }
+ }
+
+ static public final class L128 extends AsciiChars {
+ public L128(String value) {
+ super(128, value);
+ }
+ }
+
+ static public final class L255 extends AsciiChars {
+ public L255(String value) {
+ super(255, value);
+ }
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/StructuredData.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/StructuredData.java
new file mode 100644
index 0000000..27cc53f
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/StructuredData.java
@@ -0,0 +1,147 @@
+package de.hs_mannheim.ffi.vs.syslog.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * helper class for RFC 5424 (https://datatracker.ietf.org/doc/html/rfc5424)
+ * compliant log messages as immutable Java objects - structured data (set of
+ * key/value-pairs) with some predefined sets according to the standard
+ *
+ * @author Sandro Leuchter
+ *
+ */
+public class StructuredData {
+ static public class Element {
+ private final String name;
+ private List parameters;
+
+ public static Element newTimeQuality(boolean tzKnown,
+ boolean isSynced) {
+ return newTimeQuality(tzKnown, isSynced, null);
+ }
+
+ public static Element newTimeQuality(boolean tzKnown, boolean isSynced,
+ Integer syncAccuracy) {
+ var e = new Element("timeQuality");
+ e.add(new Param("tzKnown", (tzKnown) ? "1" : "0"));
+ e.add(new Param("isSynced", (isSynced) ? "1" : "0"));
+ if (syncAccuracy != null && !isSynced) {
+ e.add(new Param("syncAccuracy", String.valueOf(syncAccuracy)));
+ }
+ return e;
+ }
+
+ public static Element newOrigin(String enterpriseId, String software,
+ String swVersion) {
+ return newOrigin(new String[] {}, enterpriseId, software,
+ swVersion);
+ }
+
+ public static Element newOrigin(String ip, String enterpriseId,
+ String software, String swVersion) {
+ return newOrigin(new String[] { ip }, enterpriseId, software,
+ swVersion);
+ }
+
+ public static Element newOrigin(String[] ip, String enterpriseId,
+ String software, String swVersion) {
+ var e = new Element("origin");
+ for (var p : ip) {
+ e = e.add(new Param("ip", p));
+ }
+ if (enterpriseId != null && !enterpriseId.equals("")) {
+ e = e.add(new Param("enterpriseId", enterpriseId));
+ }
+ if (software != null && !software.equals("")) {
+ e = e.add(new Param("software", software));
+ }
+ if (swVersion != null && !swVersion.equals("")) {
+ e = e.add(new Param("swVersion", swVersion));
+ }
+ return e;
+ }
+
+ public static Element newMeta(Integer sequenceId, Integer sysUpTime,
+ String language) {
+ var e = new Element("meta");
+ if (sequenceId != null && sequenceId > 0) {
+ e = e.add(new Param("sequenceId",
+ String.valueOf(sequenceId % 2147483647)));
+ }
+ if (sysUpTime != null && sysUpTime >= 0) {
+ e = e.add(new Param("sysUpTime", String.valueOf(sysUpTime)));
+ }
+ if (language != null && !language.equals("")) {
+ e = e.add(new Param("language", language));
+ }
+ return e;
+ }
+
+ public Element(String name) {
+ this.name = name;
+ this.parameters = new ArrayList<>();
+ }
+
+ public Element add(Param parameter) {
+ var e = new Element(this.name);
+ e.parameters = this.parameters;
+ e.parameters.add(parameter);
+ return e;
+ }
+
+ @Override
+ public String toString() {
+ var str = "[" + this.name;
+ for (var p : this.parameters) {
+ str = str + " " + p.toString();
+ }
+ return str + "]";
+ }
+ }
+
+ static public class Param {
+ private final String name;
+ // name: printable US-ASCII string ^[@=\]\"\s]+
+ // "@" + private enterpise number "@\d+(\.\d+)*"
+ private final String value;
+
+ public Param(String name, String value) {
+ this.name = name; // 7-Bit ASCII
+ this.value = value; // UTF-8
+ }
+
+ @Override
+ public String toString() {
+ return this.name + "=\"" + this.value + "\"";
+ }
+ }
+
+ private List params;
+
+ public StructuredData() {
+ this.params = new ArrayList<>();
+ }
+
+ public StructuredData(List params) {
+ this.params = params;
+ }
+
+ public String toString() {
+ if (this.params.size() == 0) {
+ return "-";
+ }
+ var str = "";
+ for (var p : this.params) {
+ str = str + p.toString();
+ }
+ return str;
+ }
+
+ public StructuredData add(Element e) {
+ var p = this.params;
+ p.add(e);
+ return new StructuredData(p);
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogClient.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogClient.java
new file mode 100644
index 0000000..8360fa3
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogClient.java
@@ -0,0 +1,52 @@
+package de.hs_mannheim.ffi.vs.syslog.model;
+
+import java.io.IOException;
+import java.net.*;
+
+public class SyslogClient {
+
+ private static final int SYSLOG_PORT = 514;
+ private static final int DISCOVERY_PORT = 8888;
+ private static final int TIMEOUT = 2000;
+
+ public static void main(String[] args) throws SocketException {
+
+
+ String message = "Test message from SyslogClient";
+
+ try {
+ sendToSyslogPort(message);
+
+ sendDiscoveryMessage();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ private static void sendToSyslogPort(String message) throws IOException {
+ DatagramSocket socket = new DatagramSocket();
+ InetAddress serverAddress = InetAddress.getLocalHost();
+ DatagramPacket packet = new DatagramPacket(message.getBytes(), message.getBytes().length, serverAddress,
+ SYSLOG_PORT);
+ socket.send(packet);
+ socket.close();
+ }
+
+ private static void sendDiscoveryMessage() throws IOException {
+ DatagramSocket socket = new DatagramSocket();
+ socket.setBroadcast(true);
+ byte[] buffer = new byte[0]; // Leer, da nur die IP-Adresse des Servers benötigt wird
+ DatagramPacket discoveryPacket = new DatagramPacket(buffer, buffer.length,
+ InetAddress.getByName("255.255.255.255"), DISCOVERY_PORT);
+ socket.send(discoveryPacket);
+
+ // Warten auf die Antwort vom Server
+ byte[] responseBuffer = new byte[1024];
+ DatagramPacket responsePacket = new DatagramPacket(responseBuffer, responseBuffer.length);
+ socket.receive(responsePacket);
+ System.out.println("Received response from SyslogServer: " + responsePacket.getAddress());
+
+ socket.close();
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogMessage.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogMessage.java
new file mode 100644
index 0000000..696172e
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogMessage.java
@@ -0,0 +1,159 @@
+package de.hs_mannheim.ffi.vs.syslog.model;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * RFC 5424 (https://datatracker.ietf.org/doc/html/rfc5424) compliant log
+ * messages as immutable Java objects
+ *
+ * @author Sandro Leuchter
+ *
+ */
+public class SyslogMessage implements Serializable {
+ private static final long serialVersionUID = -5895573029109990861L;
+ private final Facility fac;
+ private final Severity sev;
+ private final AsciiChars.L255 host;
+ private final AsciiChars.L048 appName;
+ private final AsciiChars.L128 procId;
+ private final AsciiChars.L032 msgId;
+ private final StructuredData data;
+ private final Message message;
+
+ public SyslogMessage(Facility fac, Severity sev, AsciiChars.L255 host,
+ AsciiChars.L048 appName, AsciiChars.L128 procId,
+ AsciiChars.L032 msgId, StructuredData data, Message message) {
+ this.fac = fac;
+ this.sev = sev;
+ this.host = host;
+ this.appName = appName;
+ this.procId = procId;
+ this.msgId = msgId;
+ this.data = data;
+ this.message = message;
+ }
+
+ public Facility fac() {
+ return this.fac;
+ }
+
+
+ public Severity sev() {
+ return sev;
+ }
+
+ public AsciiChars.L255 host() {
+ return host;
+ }
+
+ public AsciiChars.L048 appName() {
+ return appName;
+ }
+
+ public AsciiChars.L128 procId() {
+ return procId;
+ }
+
+ public AsciiChars.L032 msgId() {
+ return msgId;
+ }
+
+ public StructuredData data() {
+ return data;
+ }
+
+ public Message message() {
+ return message;
+ }
+
+ public static int version() {
+ return VERSION;
+ }
+
+
+ public static enum Facility {
+ KERNEL, USER, MAIL_SYSTEM, SYS_DAEMON, SECURITY1, INTERNAL, PRINTER,
+ NEWS, UUCP, CLOCK1, SECURITY2, FTP, NTP, AUDIT, ALERT, CLOCK2, LOCAL0,
+ LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7;
+ }
+
+ public static enum Severity {
+ EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFORMATIONAL,
+ DEBUG;
+ }
+
+ public static interface Message {
+ public Object message();
+
+ public int length();
+ }
+
+ public static class BinaryMessage implements Message {
+ private Byte[] message;
+
+ public BinaryMessage(Byte[] message) {
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return message.toString();
+ }
+
+ @Override
+ public Object message() {
+ return this.message;
+ }
+
+ @Override
+ public int length() {
+ return this.message.length;
+ }
+ }
+
+ public static class TextMessage implements Message {
+ private String message; // UTF8
+
+ public TextMessage(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return "\u00EF\u00BB\u00BF" + message.toString();
+ }
+
+ @Override
+ public Object message() {
+ return this.message;
+ }
+
+ @Override
+ public int length() {
+ return this.message.length();
+ }
+ }
+
+ static final int VERSION = 1; // RFC 5424, Mar 2009
+
+ @Override
+ public String toString() {
+ var prival = String.valueOf(fac().ordinal() * 8 + sev().ordinal());
+ var d = "";
+ if (data() != null) {
+ d = " " + data();
+ }
+ var m = "";
+ if (message() != null && message().message() != null
+ && message().length() > 0) {
+ m = " " + message();
+ }
+ var timestamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
+ .format(new Date());
+ return "<" + prival + ">" + VERSION + " " + timestamp + " "
+ + host().toString() + " " + appName().toString() + " "
+ + procId().toString() + " " + msgId().toString() + d + m;
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogServer.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogServer.java
new file mode 100644
index 0000000..1932d56
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/model/SyslogServer.java
@@ -0,0 +1,58 @@
+package de.hs_mannheim.ffi.vs.syslog.model;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+public class SyslogServer {
+ private static final int SYSLOG_PORT = 514;
+ private static final int DISCOVERY_PORT = 8888;
+ private static final int MAX_MESSAGE_LENGTH = 1024;
+
+ public void startServer() {
+ try{
+ DatagramSocket syslogSocket = new DatagramSocket(SYSLOG_PORT);
+ DatagramSocket discoverySocket = new DatagramSocket(DISCOVERY_PORT);
+
+ System.out.println("Server gestartet ...");
+
+ byte[] buffer = new byte[MAX_MESSAGE_LENGTH];
+
+ while (true) {
+ DatagramPacket syslogPacket = new DatagramPacket(buffer, buffer.length);
+ syslogSocket.receive(syslogPacket);
+ processMessage(syslogPacket);
+
+ DatagramPacket discoveryPacket = new DatagramPacket(buffer, buffer.length);
+ discoverySocket.receive(discoveryPacket);
+ processDiscovery(discoveryPacket);
+ }
+ } catch (IOException e) {
+ System.err.println(e);
+ }
+ }
+
+ private void processMessage(DatagramPacket packet) {
+
+ System.out.println("Message received from " + packet.getAddress() + ": " + new String(packet.getData()).trim());
+ }
+
+ private void processDiscovery(DatagramPacket packet) {
+
+ DatagramSocket socket;
+ try {
+ socket = new DatagramSocket();
+ DatagramPacket responsePacket = new DatagramPacket(new byte[0], 0, packet.getAddress(), packet.getPort());
+ socket.send(responsePacket);
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ //Bind nicht verwenden
+
+ public static void main(String[] args) {
+ SyslogServer server = new SyslogServer();
+ server.startServer();
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/AsciiCharsTest.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/AsciiCharsTest.java
new file mode 100644
index 0000000..2476ff5
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/AsciiCharsTest.java
@@ -0,0 +1,54 @@
+package de.hs_mannheim.ffi.vs.syslog.test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+import de.hs_mannheim.ffi.vs.syslog.model.AsciiChars;
+
+class AsciiCharsTest {
+
+ @Test
+ void nullValue() {
+ var ac = new AsciiChars.L004(null);
+ assertEquals(ac.toString(), "-");
+ }
+
+ @Test
+ void emptyValue() {
+ var ac = new AsciiChars.L004("");
+ assertEquals(ac.toString(), "-");
+ }
+
+ @Test
+ void longValue() {
+ var ac = new AsciiChars.L004("1234");
+ assertEquals(ac.toString(), "1234");
+ }
+
+ @Test
+ void longerValue() {
+ var thrown = assertThrows(IllegalArgumentException.class, () -> {
+ new AsciiChars.L004("12345");
+ });
+ assertEquals("Stringlänge = 5 > 4", thrown.getMessage());
+ }
+
+ @Test
+ void space() {
+ var thrown = assertThrows(IllegalArgumentException.class, () -> {
+ new AsciiChars.L004("1 1");
+ });
+ assertEquals("Stringinhalt nicht printable US-ASCII ohne Space",
+ thrown.getMessage());
+ }
+
+ @Test
+ void special() {
+ var thrown = assertThrows(IllegalArgumentException.class, () -> {
+ new AsciiChars.L004("ä");
+ });
+ assertEquals("Stringinhalt nicht printable US-ASCII ohne Space",
+ thrown.getMessage());
+ }
+}
diff --git a/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/SyslogMessageTest.java b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/SyslogMessageTest.java
new file mode 100644
index 0000000..7efe792
--- /dev/null
+++ b/Service-Discovery/src/de/hs_mannheim/ffi/vs/syslog/test/SyslogMessageTest.java
@@ -0,0 +1,82 @@
+package de.hs_mannheim.ffi.vs.syslog.test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+import de.hs_mannheim.ffi.vs.syslog.model.AsciiChars;
+import de.hs_mannheim.ffi.vs.syslog.model.StructuredData;
+import de.hs_mannheim.ffi.vs.syslog.model.SyslogMessage;
+import de.hs_mannheim.ffi.vs.syslog.model.StructuredData.Element;
+import de.hs_mannheim.ffi.vs.syslog.model.StructuredData.Param;
+import de.hs_mannheim.ffi.vs.syslog.model.SyslogMessage.BinaryMessage;
+import de.hs_mannheim.ffi.vs.syslog.model.SyslogMessage.Facility;
+import de.hs_mannheim.ffi.vs.syslog.model.SyslogMessage.Severity;
+import de.hs_mannheim.ffi.vs.syslog.model.SyslogMessage.TextMessage;
+
+class SyslogMessageTest {
+
+ @Test
+ void testToString() {
+ var m1 = new SyslogMessage(//
+ Facility.SECURITY1, //
+ Severity.CRITICAL, //
+ new AsciiChars.L255("mymachine.example.com"), //
+ new AsciiChars.L048("su"), //
+ new AsciiChars.L128(""), //
+ new AsciiChars.L032("ID47"),//
+ new StructuredData()//
+ .add(Element.newTimeQuality(true, true))
+ .add(new Element("exampleSDID@32473")
+ .add(new Param("iut", "3"))
+ .add(new Param("eventSource", "Application"))
+ .add(new Param("eventID", "1011")))
+ .add(new Element("examplePriority@32473")
+ .add(new Param("class", "high"))),
+ new TextMessage("'su root' failed for lonvick on /dev/pts/8"));
+ var s = m1.toString();
+ assertEquals(s.substring(0, 6), "<34>1 ");
+ assertEquals(s.substring(s.length() - 221, s.length()),
+ " mymachine.example.com su - ID47 [timeQuality tzKnown=\"1\" isSynced=\"1\"][exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"][examplePriority@32473 class=\"high\"] 'su root' failed for lonvick on /dev/pts/8");
+ }
+
+ @Test
+ void test2() {
+ var m1 = new SyslogMessage(//
+ Facility.SECURITY1, //
+ Severity.CRITICAL, //
+ new AsciiChars.L255("mymachine.example.com"), //
+ new AsciiChars.L048("su"), //
+ new AsciiChars.L128(""), //
+ new AsciiChars.L032("ID47"),//
+ null, //
+ new TextMessage("'su root' failed for lonvick on /dev/pts/8"));
+ var s = m1.toString();
+ assertEquals(s.substring(0, 6), "<34>1 ");
+ assertEquals(s.substring(s.length() - 78, s.length()),
+ " mymachine.example.com su - ID47 'su root' failed for lonvick on /dev/pts/8");
+
+ }
+
+ @Test
+ void test3() {
+ var m1 = new SyslogMessage(//
+ Facility.SECURITY1, //
+ Severity.CRITICAL, //
+ new AsciiChars.L255("mymachine.example.com"), //
+ new AsciiChars.L048("su"), //
+ new AsciiChars.L128(""), //
+ new AsciiChars.L032("ID47"),//
+ new StructuredData()//
+ .add(Element.newTimeQuality(true, true))
+ .add(Element.newOrigin(
+ new String[] { "0.0.8.8", "8.8.8.8" }, null,
+ null, null))
+ .add(Element.newMeta(null, 32, "de")),
+ new BinaryMessage(null));
+ assertEquals(m1.data().toString(),
+ "[timeQuality tzKnown=\"1\" isSynced=\"1\"][origin ip=\"0.0.8.8\" ip=\"8.8.8.8\"][meta sysUpTime=\"32\" language=\"de\"]");
+ ;
+
+ }
+}