Issues with ofxUdpManager

Hello,

I’m trying to use ofxUdpManager to listen for a UDP Broadcast, and then parse the received packet and create objects in my openframeworks program based off of this.

My openframeworks app is extremely spartan, with just:

void testApp::setup(){
  listener = new DiscoveryListener();

}

//--------------------------------------------------------------
void testApp::update(){
  listener->update();
}

//--------------------------------------------------------------
void testApp::draw(){
}

The DiscoveryListener does all of the heavy lifting:

DiscoveryListener::DiscoveryListener() {
  udpConnection.Create();
  udpConnection.SetEnableBroadcast(true);
  udpConnection.BindMcast("0.0.0.0",portNo);
  udpConnection.SetNonBlocking(true);

  newMessage = 0;
}

void DiscoveryListener::update() {
  char udpMessage[76];
  newMessage = udpConnection.Receive(udpMessage,incomingPacketSize); //returns number of bytes received
  unsigned char *message = (unsigned char *)udpMessage;
  std::cout << "Packet Size: " << newMessage << std::endl;
  std::cout << "UDP Packet: " << std::endl;
  if(newMessage != -1) {
    DeviceHeader* header;
    header = new DeviceHeader(&message, incomingPacketSize);
    std::string readout = header->getMacAddressString();
    std::cout << readout << std::endl;
  }
}

However, this always results in a segmentation fault:

black-rainbows:example morphogen$ make run
HOST_OS=Darwin
HOST_ARCH=x86_64
[ error ] ofxNetwork: ../../../addons/ofxNetwork/src/ofxUDPManager.cpp: 122 EINVAL: invalid argument
Packet Size: -1
UDP Packet: 
Packet Size: -1
UDP Packet: 
Packet Size: 76
UDP Packet: 
/bin/sh: line 1: 19985 Bus error: 10           ./example
make: *** [run] Error 138

Searching for the error messages on google hasn’t provided many helpful results, but i seem to have narrowed the issue down to either a problem with the ofxUdpManager addon (related to the EINVAL error?), or something with how I’m storing and allocating memory for the incoming packet. Any suggestions?

broadcast and multicast are different things. you are enabling broadcast and then binding to multicast to an address that doesn’t really make sense. just use normal Bind and you should be able to receive on the broadcast address. that might be the error you are getting at the beginning. the crash might be because how you are converting the message into a string. strings in c end in a null character so you need to append a \0 at the end of the received message before being able to use it as a string. the easiest way is by using a buffer of +1 the size you intend to receive and initialize it to all zeros before receiving any data on it like:

vector<char> udpMessage(77,0);
newMessage = udpConnection.Receive(&udpMessage[0],76);
....

Slick! I didn’t know that I could use a vector instead of a character array like that; that’s very nice :slight_smile:

I edited the code to have two private member variables in addition to the code above (for performance reasons, so I’m not constantly reallocating memory and recreating and destroying vectors):

class DiscoveryListener {
 private:
  vector<char> incomingUdpMessage;
  vector<unsigned char> udpMessage;
};

DiscoveryListener::DiscoveryListener() {
  udpConnection.Create();
  udpConnection.SetEnableBroadcast(true);
  //  udpConnection.BindMcast("0.0.0.0",portNo);
  udpConnection.Bind(portNo);
  udpConnection.SetNonBlocking(true);

  newMessage = 0;
  incomingUdpMessage.reserve(incomingPacketSize + 1);
  std::fill(incomingUdpMessage.begin(), incomingUdpMessage.end(), 0);
  udpMessage.reserve(incomingPacketSize + 1);
  std::fill(udpMessage.begin(), udpMessage.end(), 0);
}

void DiscoveryListener::update() {
  newMessage = udpConnection.Receive(&incomingUdpMessage[0],incomingPacketSize); //returns number of bytes received
  std::copy(incomingUdpMessage.begin(), incomingUdpMessage.end(), udpMessage.begin());
  std::cout << "Packet Size: " << newMessage << std::endl;
  std::cout << "UDP Packet: " << std::endl;
  if(newMessage != -1) {
    DeviceHeader* header;
    header = new DeviceHeader(&udpMessage[0], incomingPacketSize);
    std::string readout = header->getMacAddressString();
    std::cout << readout << std::endl;
  }
}

So now I’m reserving space in the vector, setting them to all zeros, and then copying the vector from a vector<char> to a vector<unsigned char> (because the library I’m using has unsigned char as is native data structure).

However, now I get:

/bin/sh: line 1: 30741 Abort trp: 6        ./example

as an error. Further investigation and it seems like it the program thinks that the vectors are of size 0, so there’s nothing to read. Why would this happen?

you should use .resize(size,0). reserve only tells the vector to reserve that much memory but doesn’t resize it, it’s only a way of avoiding reallocations when you push back or resize later but the size() stays as 0

thank you!