UDP & Ephemeral Port [SOLVED]

Hi,

What’s the best way to get the ephemeral port when sending udp packets so that I can listen for replays on the sent from port?

Something like this? https://docs.particle.io/reference/firmware/photon/#remoteport-

I believe that’s the port that the package was sent from on the remote device not from my local device.

I’ve put a small test together to see if joinMulticast() was what I was looking for and it seams to works (I can send and receive) but when I try to move it into my structure I can’t get it to work, I think when I’m passing my udp object by refinance to the different classes it’s not working the way I expect it to (most likely I’m doing something stupid).

anyways, the working code can send and listen: UDPTEST001.ino[code]
uint32_t now;
uint32_t lastGetService = 0;
/* UDP */
IPAddress broadcastIP;
uint16_t localPort = 56701;
uint16_t remotePort = 56700;
uint16_t udpPacketSize = 0;
UDP _udp;

void setup() {
_udp.begin(remotePort);

Serial.begin(115200);
delay(1000);

IPAddress myIP = WiFi.localIP();
Serial.printlnf("My IP:%d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]);

broadcastIP = IPAddress(myIP[0],myIP[1],myIP[2],255);
_udp.joinMulticast(broadcastIP);

}

void loop() {
now = millis();

// Discover Test
if(now - lastGetService > 30000)
{
    Serial.printlnf("%d: Discovering...", now);
    lastGetService = now;
    uint8_t sendBuffer[36] = {0x24, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00};
    //LIFX.discover();
    
    _udp.beginPacket(broadcastIP, remotePort);
    _udp.write(sendBuffer, 36);
    _udp.endPacket();
}

// Check if data has been received
udpPacketSize = _udp.parsePacket();
if (udpPacketSize > 0) 
{
    Serial.printlnf("%d: UDP Received...", now);
    byte packetBuffer[128]; //buffer to hold incoming packet
    
    // Read first 128 of data received
    _udp.read(packetBuffer, 128);
    
    // Ignore other chars
    _udp.flush();
    
    // Store sender ip and port
    IPAddress senderIP = _udp.remoteIP();
    int port = _udp.remotePort();
    Serial.printlnf("IP:%d.%d.%d.%d:%d", senderIP[0], senderIP[1], senderIP[2], senderIP[3], port);
    Serial.print("Raw: ");
    for(uint8_t i = 0; i < 128; i++)
    {
        Serial.printf("\\x%02x", packetBuffer[i]);
    }
    Serial.println("");
}

}[/code]
then on test 2 (not working) I’ve tried to put it in the structure of my program: UDPTEST02.ino[code]#include “common.h”
#include “lifx.h”

uint32_t now;
uint32_t lastGetService = 0;
/* UDP */
IPAddress broadcastIP;
uint16_t localPort = 56701;
uint16_t remotePort = 56700;
uint16_t udpPacketSize = 0;
UDP _udp;

lifx _lifx;

void setup() {

_lifx = lifx(_udp);

_udp.begin(remotePort);

Serial.begin(115200);
delay(1000);

IPAddress myIP = WiFi.localIP();
Serial.printlnf("My IP:%d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]);

broadcastIP = IPAddress(myIP[0],myIP[1],myIP[2],255);
_udp.joinMulticast(broadcastIP);

}

void loop() {
now = millis();

// Discover Test
if(now - lastGetService > 30000)
{
    Serial.printlnf("%d: Discovering...", now);
    lastGetService = now;
    
    _lifx.discover(broadcastIP, remotePort);

}

// Check if data has been received
udpPacketSize = _udp.parsePacket();
if (udpPacketSize > 0) 
{
    Serial.printlnf("%d: UDP Received...", now);
    byte packetBuffer[128]; //buffer to hold incoming packet
    
    // Read first 128 of data received
    _udp.read(packetBuffer, 128);
    
    // Ignore other chars
    _udp.flush();
    
    // Store sender ip and port
    IPAddress senderIP = _udp.remoteIP();
    int port = _udp.remotePort();
    Serial.printlnf("IP:%d.%d.%d.%d:%d", senderIP[0], senderIP[1], senderIP[2], senderIP[3], port);
    Serial.print("Raw: ");
    for(uint8_t i = 0; i < 128; i++)
    {
        Serial.printf("\\x%02x", packetBuffer[i]);
    }
    Serial.println("");
}

}[/code] common.h [code]#ifndef _common_h
#define _common_h
#include “application.h”

#define _DEBUG true

#endif[/code]lifx.h[code]#ifndef _lifx_h
#define _lifx_h

/* includes */
#include "device.h"

class lifx{
    public:
    	/* Members Functions */
    	lifx();
    	lifx(UDP &udpRef);
    	void discover(IPAddress broadcastIP, uint8_t remotePort);

    	/* Members */
    	

    private:
    	/* Members Functions */
    
    	/* Members */
    	UDP _udp;
    	device _device;
};

#endif[/code]lifx.cpp[code]#include “lifx.h”

lifx::lifx()
{
//Serial.printlnf(“lifx constructor…”);
}

lifx::lifx(UDP &udpRef)
{
//Serial.printlnf(“lifx constructor overload…”);
_udp = udpRef;
_device = device(udpRef);
}

void lifx::discover(IPAddress broadcastIP, uint8_t remotePort)
{
Serial.printlnf(“lifx discover…”);
_device.getService(broadcastIP, remotePort);
}[/code]device.h[code]#ifndef _device_h
#define _device_h

/* includes */
#include "common.h"

class device{
    public:
    	/* Members Functions */
    	device();
    	device(UDP &udpRef);
    	void getService(IPAddress broadcastIP, uint8_t remotePort);

    	/* Members */

    private:
    	/* Members Functions */
    
    	/* Members */
    	UDP _udp;
};

#endif[/code]device.cpp[code]#include “device.h”

device::device()
{

};

device::device(UDP &udpRef)
{
_udp = udpRef;
};

void device::getService(IPAddress broadcastIP, uint8_t remotePort)
{
Serial.printlnf(“device getService…”);
uint8_t sendBuffer[36] = {0x24, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00};
//LIFX.discover();

_udp.beginPacket(broadcastIP, remotePort);
_udp.write(sendBuffer, 36);
_udp.endPacket();

};[/code]
any advice would be greatly appreciated.

Ok worked my own problem out, It looks like I had to move the assignment of the _udp to a set function instead of doing it in a constructor.

if anyone would like to explain why it would be appreciated.

Here’s the working code: UDPTest02.ino[code]#include “common.h”
#include “lifx.h”

uint32_t now;
uint32_t lastGetService = 0;
/* UDP */
IPAddress broadcastIP;
//uint16_t localPort = 56701;
uint16_t remotePort = 56700;
uint16_t udpPacketSize = 0;
UDP _udp;

lifx _lifx;

void setup() {

Serial.begin(115200);
delay(1000);

IPAddress myIP = WiFi.localIP();
Serial.printlnf("My IP:%d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]);

broadcastIP = IPAddress(myIP[0],myIP[1],myIP[2],255);
_udp.begin(remotePort);
_udp.joinMulticast(broadcastIP);

_lifx = lifx();
_lifx.setUDP(_udp);
_lifx.setBroadcastIP(broadcastIP);
_lifx.setRemotePort(remotePort);

}

void loop() {
now = millis();

// Discover Test
if(now - lastGetService >= 30000)
{
    Serial.printlnf("%d: Discovering...", now);
    lastGetService = now;
    
    _lifx.discover();

}

// Check if data has been received
udpPacketSize = _udp.parsePacket();
if (udpPacketSize > 0) 
{
    Serial.printlnf("%d: UDP Received...", now);
    byte packetBuffer[128]; //buffer to hold incoming packet
    
    // Read first 128 of data received
    _udp.read(packetBuffer, 128);
    
    // Ignore other chars
    _udp.flush();
    
    // Store sender ip and port
    IPAddress senderIP = _udp.remoteIP();
    int port = _udp.remotePort();
    Serial.printlnf("IP:%d.%d.%d.%d:%d", senderIP[0], senderIP[1], senderIP[2], senderIP[3], port);
    Serial.print("Raw: ");
    for(uint8_t i = 0; i < 128; i++)
    {
        Serial.printf("\\x%02x", packetBuffer[i]);
    }
    Serial.println("");
}

}[/code] common.h[code]#ifndef _common_h
#define _common_h
#include “application.h”

#define _DEBUG true

#endif[/code]lifx.h[code]#ifndef _lifx_h
#define _lifx_h

/* includes */
#include "device.h"

class lifx{
    public:
    	/* Members Functions */
    	lifx();
    	void setUDP(UDP &udpRef);
    	void setBroadcastIP(IPAddress broadcastIP);
    	void setRemotePort(uint16_t remotePort);
    	void discover();

    	/* Members */
    	

    private:
    	/* Members Functions */
    
    	/* Members */
    	UDP _udp;
    	IPAddress _broadcastIP;
        uint16_t _remotePort;
    	device _device;
};

#endif[/code]lifx.cpp[code]#include “lifx.h”

lifx::lifx()
{
_device = device();
}

void lifx::setUDP(UDP &udpRef)
{
_udp = udpRef;
_device.setUDP(udpRef);
}

void lifx::setBroadcastIP(IPAddress broadcastIP)
{
_broadcastIP = broadcastIP;
_device.setBroadcastIP(broadcastIP);
}

void lifx::setRemotePort(uint16_t remotePort)
{
_remotePort = remotePort;
_device.setRemotePort(remotePort);
}

void lifx::discover()
{
//Serial.printlnf(“lifx discover…”);
_device.getService();
}[/code]device.h[code]#ifndef _device_h
#define _device_h

/* includes */
#include "common.h"

class device{
    public:
    	/* Members Functions */
    	device();
    	void setUDP(UDP &udpRef);
    	void setBroadcastIP(IPAddress broadcastIP);
    	void setRemotePort(uint16_t remotePort);
    	void getService();

    	/* Members */

    private:
    	/* Members Functions */
    
    	/* Members */
    	UDP _udp;
    	IPAddress _broadcastIP;
        uint16_t _remotePort;
};

#endif[/code]device.cpp[code]#include “device.h”

device::device()
{

};

void device::setUDP(UDP &udpRef)
{
_udp = udpRef;
}

void device::setBroadcastIP(IPAddress broadcastIP)
{
_broadcastIP = broadcastIP;
}

void device::setRemotePort(uint16_t remotePort)
{
_remotePort = remotePort;
}

void device::getService()
{
//Serial.printlnf(“device getService…”);
uint8_t sendBuffer[36] = {0x24, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00};

_udp.beginPacket(_broadcastIP, _remotePort);

Serial.printlnf("%d bytes sent to %d.%d.%d.%d:%d", _udp.write(sendBuffer, 36), _broadcastIP[0], _broadcastIP[1], _broadcastIP[2], _broadcastIP[3], _remotePort);
_udp.endPacket();
};[/code]

The problem with constructors of classes in different modules is that the order in which these are called is “unpredictable” by design.
So if you have to rely on one class to be initialized/constructed in order to have your own class working correctly, you need to do it as you did via a begin() method which is called in the normal code path and not during load/startup.

3 Likes