Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blob size unpack_from with wrong unit #72

Closed
felixdollack opened this issue Dec 14, 2022 · 3 comments
Closed

Blob size unpack_from with wrong unit #72

felixdollack opened this issue Dec 14, 2022 · 3 comments
Labels
bug Something isn't working good first issue Good for newcomers

Comments

@felixdollack
Copy link
Contributor

Describe the bug
I am sending an OSC message containing a single blob of data:
/destn/1\x00\x00\x00\x00,b\x00\x00\x00\x00\x00\x08...
[28 bytes] /destn/1 b [8]0123456789ABCDEF

I am getting this result for both OSC data send from C and using Dart.

To Reproduce
Code example showing the issue is the example code from the readme:

from oscpy.server import OSCThreadServer
from time import sleep

osc = OSCThreadServer()
sock = osc.listen(address='0.0.0.0', port=9000, default=True)

@osc.address(b'/destn/*')
def callback(*values):
    print("got values: {}".format(values))

sleep(1000)
osc.stop()

Here the sending portion in C using tinyosc compiled with gcc *.c -Werror -std=c99 -O0 -g -o sendosc Note: main.c from tinyosc has to be removed or the content be replaced with below:

#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>

#include "tinyosc.h"

int main(int argc, char *argv[]) {
  char buffer[128];
  int len = 0;
  char blob[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
  len = tosc_writeMessage(buffer, sizeof(buffer), "/destn/1", "b",
      sizeof(blob), blob);
  tosc_printOscBuffer(buffer, len);

  struct sockaddr_in client_addr;
  client_addr.sin_family = AF_INET;
  client_addr.sin_port = htons(9000);
  client_addr.sin_addr.s_addr = INADDR_ANY;
  const int fd_send = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd_send < 0)
  {
    fprintf(stderr, "Error opening socket");
    return -1;
  }
  int response = sendto(
    fd_send, (void*) &buffer[0], len, 0,
    (struct sockaddr*)&client_addr, sizeof(client_addr)
  );
  if (response < 0) {
    fprintf(stderr, "Error in sendto()\n");
    return -1;
  }
  // close the UDP socket
  close(fd_send);
  return 0;
}

Expected behavior
Read the correct size of the blob and get a binary array same way it was written.
The same message works without any issue using e.g. python-osc.
blob = b'\x01#Eg\x89\xab\xcd\xef'

Logs/output

Exception in thread Thread-1:
Traceback (most recent call last):
  File "miniconda3/envs/v/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "miniconda3/envs/v/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/server.py", line 338, in _run_listener
    self._listen()
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/server.py", line 386, in _listen
    for address, tags, values, offset in read_packet(
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/parser.py", line 409, in read_packet
    read_message(
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/parser.py", line 309, in read_message
    value, off = parse(
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/parser.py", line 206, in parse
    return parser(
  File "miniconda3/envs/v/lib/python3.9/site-packages/oscpy/parser.py", line 96, in parse_blob
    data = unpack_from('>%iQ' % length, value, offset + size)
struct.error: unpack_from requires a buffer of at least 84 bytes for unpacking 64 bytes at offset 20 (actual buffer size is 28)
^CTraceback (most recent call last):
  File "Documents/code/udp_test/osc_example.py", line 11, in <module>
    sleep(1000)
KeyboardInterrupt

Platform (please complete the following information):

  • OS: OSX 12.5.1
  • Python 3.9
  • OSCpy 0.6.0 (installed with pip)

Additional context
Add any other context about the problem here.

@felixdollack
Copy link
Contributor Author

When parsing the blob, why do you use an integer (>%iQ) instead of a char (>%cQ)?

From osc.parser:

def parse_blob(value, offset=0, **kwargs):
    """Return a blob from offset in value."""
    size = calcsize('>i')
    length = unpack_from('>i', value, offset)[0]
    data = unpack_from('>%iQ' % length, value, offset + size)
    return data, padded(length, 8)

The specification says:

OSC-blob
An int32 size count, followed by that many 8-bit bytes of arbitrary binary data, followed by 0-3 additional zero bytes to make the total number of bits a multiple of 32.

I think the line where the data is unpacked should be something like:

data = unpack_from('>%ic' % length value, offset + size)

@felixdollack felixdollack changed the title Blob size read wrong Blob size unpack_from with wrong unit Dec 16, 2022
@tshirtman
Copy link
Member

Seems like a bug indeed, i didn’t put a lot of attention in the project since i don’t need it currently, but i’ll try to have a look at it, of course, if someone else has time before that, PR welcome.

@tshirtman tshirtman added bug Something isn't working good first issue Good for newcomers labels May 9, 2023
felixdollack added a commit to felixdollack/oscpy that referenced this issue May 31, 2023
tshirtman added a commit that referenced this issue Jun 8, 2023
Modify blob parser and test_blob to address issue #72.
@felixdollack
Copy link
Contributor Author

Solved by PR #74 and commit 696e5b9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants