Repository: obspy/obspy

Issue:
Use clibmseed to parse INFO responses in MiniSEED
Previously, INFO responses were "parsed" like this:

``` python
lenmsr = len(slpacket.msrecord)
data = slpacket.msrecord[64:lenmsr]
```

I.e. the MiniSEED headers were just assumed to be 8 bytes. This causes problems with e.g. IRIS Ringserver, (which only uses 7 bytes), effectively cutting off the first 8 charaters of the response.

This pull request fixes that by parsing the MiniSEED packet using `clibmseed`. I also added a test case including two actual packets sent by GEOFON and IRIS SeedLink servers.



Discussion:

Resolving patch:
diff --git a/obspy/seedlink/client/seedlinkconnection.py b/obspy/seedlink/client/seedlinkconnection.py
--- a/obspy/seedlink/client/seedlinkconnection.py
+++ b/obspy/seedlink/client/seedlinkconnection.py
@@ -892,13 +892,12 @@ def collect(self):
                                 #print SLPacket.TYPE_SLINF
                                 #print "DEBUG: SLPacket.TYPE_SLINFT:",
                                 #print SLPacket.TYPE_SLINFT
-                                lenmsr = len(slpacket.msrecord)
                                 if (type == SLPacket.TYPE_SLINF):
                                     self.infoStrBuf += \
-                                        str(slpacket.msrecord)[64: lenmsr]
+                                        slpacket.getStringPayload()
                                 elif (type == SLPacket.TYPE_SLINFT):
                                     self.infoStrBuf += \
-                                        str(slpacket.msrecord)[64: lenmsr]
+                                        slpacket.getStringPayload()
                                     self.info_string = \
                                         self.createInfoString(self.infoStrBuf)
                                     self.infoStrBuf = ""
diff --git a/obspy/seedlink/slpacket.py b/obspy/seedlink/slpacket.py
--- a/obspy/seedlink/slpacket.py
+++ b/obspy/seedlink/slpacket.py
@@ -137,6 +137,18 @@ def getTrace(self):
         self.trace = Trace(data, header)
         return self.trace
 
+    def getStringPayload(self):
+        """
+        Get the MiniSEED payload, parsed as string.
+        """
+        msrecord_py = self.getMSRecord()
+
+        # This is the same data buffer that is accessed by
+        # _ctypesArray2NumpyArray in getTrace above.
+        payload = C.string_at(msrecord_py.datasamples, msrecord_py.samplecnt)
+
+        return payload
+
     def getType(self):
         #print "DEBUG: self.slhead:", repr(self.slhead)
         if self.slhead[0: len(SLPacket.INFOSIGNATURE)].lower() == \


Test patch:
diff --git a/obspy/seedlink/tests/data/info_packet_geofon.slink b/obspy/seedlink/tests/data/info_packet_geofon.slink
new file mode 100644
Binary files /dev/null and b/obspy/seedlink/tests/data/info_packet_geofon.slink differ
diff --git a/obspy/seedlink/tests/data/info_packet_iris.slink b/obspy/seedlink/tests/data/info_packet_iris.slink
new file mode 100644
Binary files /dev/null and b/obspy/seedlink/tests/data/info_packet_iris.slink differ
diff --git a/obspy/seedlink/tests/test_seedlinkconnection.py b/obspy/seedlink/tests/test_seedlinkconnection.py
--- a/obspy/seedlink/tests/test_seedlinkconnection.py
+++ b/obspy/seedlink/tests/test_seedlinkconnection.py
@@ -11,7 +11,7 @@
 
 class SeedLinkConnectionTestCase(unittest.TestCase):
 
-    def test_issueXXX(self):
+    def test_issue777(self):
         """
         Regression tests for Github issue #777
         """
diff --git a/obspy/seedlink/tests/test_slpacket.py b/obspy/seedlink/tests/test_slpacket.py
new file mode 100644
--- /dev/null
+++ b/obspy/seedlink/tests/test_slpacket.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+"""
+The obspy.seedlink.slpacket test suite.
+"""
+import os.path
+
+from obspy.seedlink.slpacket import SLPacket
+import unittest
+
+
+class SLPacketTestCase(unittest.TestCase):
+
+    def _read_data_file(self, fn):
+        path = os.path.dirname(__file__)
+        fn = os.path.join(path, 'data', fn)
+
+        with open(fn, 'rb') as f:
+            data = f.read()
+
+        return data
+
+    def test_getStringPayload(self):
+        """
+        Test parsing of SeedLink MiniSEED payload as XML string.
+
+        The GEOFON and the IRIS Ringserver packets differ in the size of bytes
+        used for MiniSEED headers (8 vs. 7 bytes).
+        """
+        # Check the INFO CAPABILITIES response from GEOFON
+        packet = self._read_data_file('info_packet_geofon.slink')
+        packet = SLPacket(packet, 0)
+        payload = packet.getStringPayload()
+
+        xml = b'<?xml version="1.0"?>'
+        self.assertTrue(payload.startswith(xml))
+        self.assertEqual(len(payload), 368)
+
+        # Check the INFO CAPABILITIES response from IRIS Ringserver
+        packet = self._read_data_file('info_packet_iris.slink')
+        packet = SLPacket(packet, 0)
+        payload = packet.getStringPayload()
+
+        xml = b'<?xml version="1.0" encoding="utf-8"?>'
+        self.assertTrue(payload.startswith(xml))
+        self.assertEqual(len(payload), 456)
+
+
+def suite():
+    return unittest.makeSuite(SLPacketTestCase, 'test')
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='suite')