Coder Social home page Coder Social logo

truvorskameikin / udp-discovery-cpp Goto Github PK

View Code? Open in Web Editor NEW
58.0 6.0 27.0 151 KB

A small library to add local network discovery feature to your C++ programs with no dependencies

License: MIT License

CMake 3.28% C++ 96.14% Shell 0.57%
udp broadcast discovery discovery-service-client zero-dependency cpp udp-discovery udp-broadcast multicast discovered-peers

udp-discovery-cpp's People

Contributors

bartekordek avatar g10h4ck avatar truvorskameikin avatar uginus avatar zapek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

udp-discovery-cpp's Issues

PacketIndex is increased even when userdata didn't change

When a packet is received, packet_index is checked for increments to see if the userdata needs to be updated:

bool update_user_data = ((*find_it).last_received_packet() < header.packet_index);

But here:

++packet_index_;

packet_index is incremented everytime a packet is sent, even if the userdata didn't change.

Shouldn't it be increased only if the userdata changed?

Make peerId to use UUID version 4

Now we use uint32_t as the peerId.

Also we use very strange logic to filter and compare discovered peers (see Same method at https://github.com/truvorskameikin/udp-discovery-cpp/blob/master/udp_discovery_peer.hpp#L87) - it uses peer address and maybe peer port. But if we implement sending packets to all the interfaces then this logic will just break showing multiple peers that are just single peer. Let's remove this comparison but rely on comparing peerIds.

This change will require protocol update.

Remove packet_index_reset parameter from protocol

It is not good to reset packet index while discovery application is running. Packet index reset is sent in single UDP packet that can be lost and other peers will not get it and will keep old and large value of packet index. So the solution is to store packet index in 64 bit integer. Even if the peer will send packet every second it can run without overflow of packet index almost forever.

Rename files with udp_discovery prefix

It safe to name files with the prefix of the library this files correspond to. So renaming of all files is needed. Also rename endpoint to something more suitable.

Windows compatibility

Has udp-discovery-cpp been tested with Windows 10?

The following software uses udp-discovery-cpp: https://github.com/RetroShare/RetroShare

If I use netstat, I can see that the port is bound properly with the right process but if I check with Wireshark, there's no packet being sent. If I run the linux version then I can see the traffic properly.

Add unit tests

Need to add some number of unit tests. Protocol part can be unit-tested, not sure about other parts.

Allow sending arbitrary messages to peers

We can send arbitrary messages over udp to discovered peers. The suggested flow can look like:

  • generate random message id
  • send message with generated id to peer using udp-discovery-cpp (specify response wait timeout, number of resend attempts)
  • wait for response and report either success or fail.

Use two threads for sending and receiving messages

Now the library uses only one thread for both sending and receiving messages. The waiting is done using recvfrom function in the blocking mode (with setting the appropriate timeout). This approach works well but having two threads (one for sending messages and one for receiving) will be much better and we can remove PeerParameters.receive_timeout_ms_ parameter.
The receiving thread can use the default socket timeout.
For doing that we will introduce the ref counter in the env struct. Both threads will increase the counter at start and decrease at exit (also thread will delete env when ref count will reach 0). We assume that threads live longer than udpdiscovery::Peer object and that is why udpdiscovery::Peer object doesn't need to increase ref counter.

Finish writing README

Finish writing README file in develop branch. Add:

  • "Design" section describing the design of the library.
  • "How to use" section describing how to setup and use Endpoint.

Support multiple instance of application per host

Right now if I start two instance of the same application on the same host, it seems that udp-discovery-cpp will see only one of them, at first it seems this happens because because the same socket is used both for listening and sending packets, so the source port is de same as destination port and is the same for all instances, thus as IP:Port is used as identifier for endpoint, seems there is no way to have multiple different endpoints on same host.

This probably can be easily solved using a different socket to send the packets so the source port can be random, and automatically the different endpoints should be recognized.

multiple network interfaces

When I ran ./udp-discovery-example both both test1 and the same with test2 on the same windows computer, they both discovered each other.

It worked also when I ran it with test3 and test4 on another linux computer on the same network.

But the services test1 and test2 didn't discover test3 and test4 and vice versa.

I suspect this issue might be related to having multiple network interfaces on both computers (mostly created by docker). I had similar problem with my simple UDP broadcast implementation using Qt. First two examples below worked only in some cases, but the third one worked well in all my tests. Maybe it could help you to solve the issue also in this project.

This didn't work:

QUdpSocket s;
s.writeDatagram(QByteArray(), QHostAddress::Broadcast, PORT);

This didn't work either:

QUdpSocket s;
QNetworkDatagram datagram(QByteArray(), QHostAddress::Broadcast, PORT);
// Send the packet to all network interfaces
for (int i=0; i<QNetworkInterface::allInterfaces().size(); i++) {
	datagram.setInterfaceIndex(i);
	s.writeDatagram(datagram);
}

This finally worked (got it from here: https://forum.qt.io/post/187963):

// Get network interfaces list
QUdpSocket s;
QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < ifaces.size(); i++) {
	auto iface = ifaces[i];
	// Get all IP addresses for the current interface
	QList<QNetworkAddressEntry> addrs = iface.addressEntries();
	// And for any IP address, if it is IPv4 and the interface is active, send the packet
	for (int j = 0; j < addrs.size(); j++) {
		auto addr = addrs[j];
		if ((addr.ip().protocol() == QAbstractSocket::IPv4Protocol) && (addr.broadcast().toString() != "")) {
			s.writeDatagram(QByteArray(), addr.broadcast(), PORT);
		}
	}
}

You can search for documentation of Qt classes here: https://doc.qt.io/qt-5/index.html

to_sleep_ms can be negative, causing SleepFor to wait for (almost) ever

Hello,

IsRightTime can set a negative value to to_sleep_until_next_delete_idle, causing the subsequent call to SleepFor to wait for a very long time on windows, and the process getting stuck when calling Stop(true) on the peer.
Indeed, Sleep((DWORD)time_ms) casts the negative value to a very large positive value.

I don't know if IsRightTime is buggy; a possible fix would be replacing "SleepFor(to_sleep_ms);" with "SleepFor(std::max((long)0, to_sleep_ms));", or maybe do the check in the function itself.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.