Comments (32)
Fine, I will use in single thread for now. I guess all will be okay.
from datachannel-wasm.
Thank you for this. Everything works now!
from datachannel-wasm.
The issue is that your code opens the WebSocket, then immediately returns which destroys it. The API is asynchronous like the JavaScript one, so when returning from open the WebSocket connection is pending. If you wait for some time without returning immediately it should connect properly.
The function console log 5279128 and I have no idea why it console log a numeric type data.
pUrl
is actually a C pointer passed to Javascript, that's why it is a number. You need to log url
, which is a string.
from datachannel-wasm.
But how would you wait?
I haven't found a method to wait.
I tried with while(true) loop and that also didn't work, error was out instantly but browser halted due to high CPU usage
from datachannel-wasm.
Oh yes sorry, you need to return from wasm code. You should actually put the ws
smart point as a global variable to keep it alive.
You can also look into emscripten which has some utilities to simulate infinite loops in wasm code.
from datachannel-wasm.
Global vars are really ugly. How did you used this on your game? Was it global vars?
I've looked but you've not used that. There were no signs of loop either other than the render loop
from datachannel-wasm.
Note that I compile with NO_EXIT_RUNTIME which should allow the WS callbacks to run since NO_EXIT_RUNTIME doesn't run destructors.
from datachannel-wasm.
Global variables are ugly in general, however they are necessary here to keep references between calls from Javascript. You can still organize everything cleanly. In fact, I use one global variable only in my game, here engine
actually keeps everything alive, including game state:
https://github.com/paullouisageneau/convergence/blob/d8cdcdfc7e3237e7b1c164d3479be3c684a9f8e6/src/main.cpp#L34
The main loop is simulated with emscripten_set_main_loop
:
https://github.com/paullouisageneau/convergence/blob/d8cdcdfc7e3237e7b1c164d3479be3c684a9f8e6/src/main.cpp#L46
NO_EXIT_RUNTIME
is enabled by default and it does not do what you think it does, see https://emscripten.org/docs/getting_started/FAQ.html
By default Emscripten sets EXIT_RUNTIME=0, which means that we don’t include code to shut down the runtime. That means that when main() exits, we don’t flush the stdio streams, or call the destructors of global C++ objects, or call atexit callbacks. This lets us emit smaller code by default, and is normally what you want on the web: even though main() exited, you may have something asynchronous happening later that you want to execute.
The point is only not to destroy global objects. It means destructors of objects going out of scope are still called, even in the main function scope.
from datachannel-wasm.
The thing is I need to run your websoocket abstraction in pThreads and when we use shared pointer I guess it use main thread.
from datachannel-wasm.
Hmm there is a keyword called thread_local but not sure whether it would work or not
from datachannel-wasm.
You could set a global shared pointer from a thread.
However, multithreading in wasm is an extremely recent functionality that won't be supported everywhere. Note you might need to configure emscripten to output wasm threads rather than converting them to dummy code if you haven't already.
Also, parts of the wrapper might not work because it calls the Javascript API under the hood. For instance, PeerConnection is not accessible to WebWorkers so I think it may also not be accessible to wasm threads.
My point here is that using threads will cause a lot of issues.
from datachannel-wasm.
So I got the Websocket part fixed by using what you suggested. Now, however; the RTC part seems broken.
std::shared_ptr<rtc::PeerConnection>
RTCTransport::createPeerConnection(const rtc::Configuration &config, std::weak_ptr<rtc::WebSocket> ws, std::string id)
{
auto pc = std::make_shared<rtc::PeerConnection>(config);
std::cout << "DEBUG: createPeerConnection has been called" << "\n";
pc->onLocalDescription([ws, id](rtc::Description description) {
nlohmann::json message = {{"id", id}, {"type", description.typeString()}, {"sdp", std::string(description)}};
auto socket = ws.lock();
if (socket)
{
socket->send(message.dump());
}
});
pc->onLocalCandidate([ws, id](rtc::Candidate candidate) {
nlohmann::json message = {{"id", id},
{"type", "candidate"},
{"candidate", std::string(candidate)},
{"sdpMid", candidate.mid()}};
auto socket = ws.lock();
if (socket)
{
socket->send(message.dump());
}
});
peerConnectionMap.emplace(id, pc);
return pc;
}
ws->onOpen([&]() {
std::cout << "WebSocket connected, signaling ready"
<< "\n"; /// THIS PRINTS
auto pc = createPeerConnection(config, ws, localID); /// BUT THIS FAILS
auto dc = pc->createDataChannel(localID);
dc->onOpen([dc](){
std::cout << "Data Channel is ready" << "\n";
dc->send("Heyyyyyyy from Client");
});
The call to createPeerConnection function in same class fails!
from datachannel-wasm.
What do you mean by "this fails"?
from datachannel-wasm.
Note you have the same problem as before, pc
needs to be stored somewhere otherwise it will be destroyed immediately when leaving the scope.
from datachannel-wasm.
Duh!
WebWorkers only support QUIC based Data Channel
paullouisageneau/libdatachannel#111
but your lib has not added that yet
from datachannel-wasm.
The problem is there is virtually no browser support for WebRTC with QUIC for now.
RTCQuicTransport
is actually a whole different stack and a whole new API replacing RTCPeerConnection
and RTCDataChannel
. As of today it's only available on recent Chromium with a developper flag enabled, and documentation is really lacking, I have only seen an ORTC draft published last month.
Don't expect this to be available soon, sadly it'll take some time.
from datachannel-wasm.
I made a global var called std::shared_ptr<rtc::PeerConnection> pc;
and the code now looks like this,
ws->onOpen([&]() {
std::cout << "WebSocket connected, signaling ready"
<< "\n"; /// THIS PRINTS
pc = createPeerConnection(config, ws, localID); /// BUT THIS FAILS
auto dc = pc->createDataChannel(localID);
dc->onOpen([dc](){
std::cout << "Data Channel is ready" << "\n";
dc->send("Heyyyyyyy from Client");
});
But the call to function fails. JS console output again a numeric type value Uncaught 5281056
from datachannel-wasm.
It means there is an uncaught exception, you should add a try/catch block inside the onOpen callback to display it. Also, you should also store the DataChannel somewhere.
from datachannel-wasm.
But why store DC somewhere since WS already stored somewhere?
In my non-wasm code, I didn't do that.
from datachannel-wasm.
Here it will work by chance because the DataChannel onOpen callback will keep a reference. In practice, it's better to pass a weak pointer to allow the DataChannel destruction and prevent a possible memory leak if you forget to close the DataChannel manually.
from datachannel-wasm.
I printed out the error.
Error: allocator::allocate(size_t n) 'n' exceeds maximum supported size
from datachannel-wasm.
Some argument is probably corrupt. How is config
allocated?
from datachannel-wasm.
Like this
void RTCTransport::initialize(std::string &WebSocketEndpoint, std::vector<std::string> &iceServers)
{
//"stun:stun.services.mozilla.com:3478"
for (const auto &i : iceServers)
{
config.iceServers.emplace_back(i);
}
config is equals to rtc::Configuration config;
in RTCTransport class
from datachannel-wasm.
OK, and is the RTCTransport
instance a global variable?
from datachannel-wasm.
No.
int main() {
RTCTransport network;
std::string endpoint = "ws://whatever.com";
std::vector<std::string> ICEServers;
ICEServers.push_back("stun:stun.services.mozilla.com:3478");
network.initialize(endpoint, ICEServers);
}
from datachannel-wasm.
Well that's your problem, and it's always the same problem. At the end of main, network
will be destroyed, so when the onOpen callback is called, it does not exist anymore, and references on it become invalid.
You must not use things allocated in the main function scope in callbacks, you have to allocate them globally.
from datachannel-wasm.
That seems fixed but now getting this error
Error: WebSocket string messages are not supported
from datachannel-wasm.
Oh yes, this is something I need to add to the wrapper, I only use binary messages in my game. For now you can send the messages as rtc::binary
.
from datachannel-wasm.
How to convert string to rtc::binary type?
from datachannel-wasm.
Perhaps from nlohman directly
from datachannel-wasm.
You can do something like:
std::string str = json.dump();
auto *data = reinterpret_cast<rtc::byte*>(str.data());
socket->send(rtc::binary(data, data+str.size()));
and the other way around:
auto *data = reinterpret_cast<char*>(bin.data());
std::string str(data, data + bin.size());
I'll add string message support when I get the time, it shouldn't be too complex.
from datachannel-wasm.
@jeffRTC I added support for string messages in 90fdaaa
from datachannel-wasm.
Related Issues (20)
- suggestion about removing libdatachannel as a submodule HOT 2
- Usage of IceServer as a struct in Configuration HOT 1
- Concerns about Async operations HOT 4
- About using stringToUTF8 instead of allocUTF8FromString in webrtc.js and websocket.js HOT 2
- AS option? HOT 19
- onBufferedAmountLow is annoying HOT 11
- Missing rtc* functions during linking HOT 5
- how to use? can i use this in some embed v8 env to support wrtc? HOT 3
- Copy and Paste troubles HOT 5
- Failed to execute 'createDataChannel' on 'RTCPeerConnection': RTCDataChannel cannot have both max retransmits and max lifetime HOT 10
- RuntimeError: Aborted(free() called but not included in the build - add '_free' to EXPORTED_FUNCTIONS) HOT 6
- ServiceWorker datachannel-wasm <=> window native datachannel HOT 3
- usecase HOT 3
- Nodejs support HOT 3
- datachannel-wasm with C based code HOT 4
- send Bytes over DataChannel HOT 3
- Align reliability API with the new API in libdatachannel
- Using Multithreading HOT 2
- support media transport HOT 1
- Match libdatachannel's reliability.hpp HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from datachannel-wasm.