sepfy / libpeer

WebRTC Library for IoT/Embedded Device using C
MIT License
887 stars 132 forks source link

Windows support #53

Open darkuranium opened 1 year ago

darkuranium commented 1 year ago

Hi. I was wondering if there is any interest in adding Windows support. I know libpeer is primarily intended for embedded devices (ESP32, rPi, etc), but I do believe it has potential for other uses.

My own use-case is to use DataChannels for video game networking. (and perhaps at some point: audio for voice chat)

I'm more than willing to contribute towards such an implementation, though I reckon I'll need your help troubleshooting. In fact, I already worked on a port myself, and I believe I have a mostly-working version, though I get the following error:

ERROR <...>/libpeer/src/dtls_srtp.c 381 failed! mbedtls_ssl_handshake returned -0x7280

(that error code corresponds to MBEDTLS_ERR_SSL_CONN_EOF)

Update: Above issue was in Waterfox (& confirmed with Firefox), but Chrome seems to work — though only after a long delay (connection finally succeeds ~40-50 seconds after page load).

I suspect the difference between WF/FF & Chrome is one between aggressive nomination vs regular (which is the same issue affecting Firefox's non-compliance with ICE-lite, though as far as I can tell, libpeer doesn't advertise itself as ICE-lite?). Firefox, in particular, appears to send a ton of messages with USE_CANDIDATE attribute set, which might be an indicator to help out with the problem (at least according to https://github.com/versatica/mediasoup/issues/650).

Quick inspection reveals Firefox to send 30 messages with such an attribute, whereas Chrome sends none.


The good news, however, is that Chrome does work — with libpeer running in Windows! So my port was successful after all. I haven't yet tested it, but I've a sneaking suspicion Firefox would fail to work even with libpeer running on a POSIX system.

sepfy commented 1 year ago

good job! i never try on the windows. if the windows supports BSD sockets API, i think we can port to this. about firefox, you are right. libpeer cannot work with firefox now. In my experience, there is some error in STUN packet. But i don't have time to check it. If I have time I will look into this issue

darkuranium commented 1 year ago

Windows does in fact use Berkley sockets (from actual Berkley/BSD, in fact — obviously probably modified by Microsoft at various points). They are only a few (trivial) differences:

Other than that, I had to manually implement gettimeofday() & strndup(). The former exists in MinGW as-is, but I wanted to eventually support MSVC. ports.c is also different in Windows from POSIX, though the Windows implementation should at least in theory be usable in POSIX systems as-is — it's also much simpler! It relies on gethostbyname, using our own hostname (obtained via gethostname) as the parameter. As an aside, this also needs linking with iphlpapi in Windows.

My initial implementation replaced the necessary heads in-place, but I've since moved the compatibility parts into platform/{address,endian,socket,misc}.h, which is mostly just "forwarding macros"; one exception being gettimeofday(), strdup(), and initialization (the latter being a no-op outside of Windows). I'd like your feedback on what makes the most sense here. I personally think that having this stuff in a separate platform folder (or, alternatively, platform_* files) centralizes the platform-specific parts. The only remaining #ifdef inside the codebase is for handling ports_get_host_addr in ports.c.


I've also started working on a web/Emscripten wrapper for libpeer. Essentially, the idea is to provide the exact same API, but to make use of the browsers' WebRTC APIs internally. That one's progressing a little slowly because there are some API mismatches between the two, plus I've been having trouble with signaling. Not sure how much interest you would have in this, but it's a necessity for me (it's the whole reason as to why I'm using WebRTC for games instead of pure UDP implementations such as ENet).

There were a few other minor fixups, for example:


A few things I'd like to see for my own use-case (though I understand if some of these might not fit your goals):

I'm more than willing to help with all of these (though I won't be able to actually test IPv6 support), but it's your library, so I'd like your comments on this first!

And sorry about the wall of text, I just figured you'd appreciate the feedback, updates, and clarifications.

richlegrand commented 12 months ago

I'm seeing the long delays in the browser also. It happens when the browser is waiting for all of the ice candidates to come in. My thinking is that there is some logic in the browser that waits for a timeout period for "the right kind of candidate". This makes sense (for example) when there are only ipv6 candidates available (because the browser can see that the offer's candidates are ipv4-only) -- the browser will wait until the timeout period, which makes sense. What makes less sense is when the browser waits even when there are valid/compatible candidates in the offer.

I haven't seen long delays in the browser when using an aiortc (python) peer, for example. There may be a way to tweak the candidates' attributes such that the browser doesn't wait. The other idea is to use "trickle ice" -- this should reduce the connection times in all scenarios. Just thoughts though... :)

Regarding custom signaling, I'm using libpeer with different signaling and it's not a problem. The main discovery for me was that peer_connection.h is basically a simplified WebRTC API.

darkuranium commented 11 months ago

I'm seeing the long delays in the browser also. It happens when the browser is waiting for all of the ice candidates to come in. My thinking is that there is some logic in the browser that waits for a timeout period for "the right kind of candidate". This makes sense (for example) when there are only ipv6 candidates available (because the browser can see that the offer's candidates are ipv4-only) -- the browser will wait until the timeout period, which makes sense. What makes less sense is when the browser waits even when there are valid/compatible candidates in the offer.

I haven't seen long delays in the browser when using an aiortc (python) peer, for example. There may be a way to tweak the candidates' attributes such that the browser doesn't wait. The other idea is to use "trickle ice" -- this should reduce the connection times in all scenarios. Just thoughts though... :)

Regarding custom signaling, I'm using libpeer with different signaling and it's not a problem. The main discovery for me was that peer_connection.h is basically a simplified WebRTC API.

So, I've made progress in both Firefox & Chrome. I got Firefox working --- see #59!

Chrome, at least with trickle-ICE on seems to be instant when it has no microphone permission ... but takes ages when it does. So it must be something related to that.

darkuranium commented 11 months ago

@sepfy @richlegrand https://github.com/sepfy/libpeer/pull/60