lukeweber / webrtc-jingle-client

Webrtc audio + jingle protocol brought to IOS and Android.
https://groups.google.com/forum/?fromgroups#!forum/webrtc-jingle
BSD 3-Clause "New" or "Revised" License
335 stars 137 forks source link

IOS VoIP integration, special sockets and timeout handlers for keepalive #53

Open lukeweber opened 11 years ago

lukeweber commented 11 years ago

IOS recommends a few things for VoIP, specifically special sockets and timeout handlers.

http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW12

There are several requirements for implementing a VoIP app:

Socket that would need to change to the IPhone recommended version is used here: ./third_party/libjingle/talk/xmpp/xmppengineimpl.cc

In terms of timeouts, we would need a handler that wakes up and calls the white space keepalive method located in clientsignalingthread.cc.

lukeweber commented 11 years ago

A bit more about specifics, we use TxmppSocket in xmppclient for our xmpp conneciton. When creating the thread, we may simple be able to pass macsocketserver to the thread() method in voiceclient.cc.

@https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/UsingSocketsandSocketStreams.html "Note: POSIX networking does not activate the cellular radio on iOS. For this reason, the POSIX networking API is generally discouraged in iOS."

We can't use posix it seems, shit, looks pretty tangled, but maybe not.

It seems we should need to do something like this: http://stackoverflow.com/questions/12057151/voip-socket-on-ios-no-notifications-received

MacAsyncSocket uses CFSocket, which is a c bsd socket. I assume we would need to create a new socket, IOSAsyncSocket that uses the correct interfaces, but will have to confirm further. Otherwise if we can reuse MacAsyncSocket then we would have to reuse CFSocket with CFSocketNativeHandle CFSocketGetNative (CFSocketRef s) to plug into the code from the stackoverflow example above and use the read/write streams from the example. Don't think/am not sure that would work, as I think CFSocket is an underlying POSIX socket that won't work well on IOS.

Current code flow of using posix sockets: ............... Based on current thread get socket server and create a socket.

void TXmppSocket::CreateCricketSocket(int family) { talk_base::Thread* pth = talk_base::Thread::Current(); if (family == AF_UNSPEC) { family = AF_INET; } talk_base::AsyncSocket* socket = pth->socketserver()->CreateAsyncSocket(

............... Based on socket server that's passed in, construct message queue

libjingle/talk/base/thread.cc -> Thread::Thread(SocketServer* ss) : MessageQueue(ss), ...

....... if no socket server, create the default PhysicalSocketServer()

MessageQueue::MessageQueue(SocketServer* ss) : ss(ss), fStop(false), fPeekKeep(false), active(false), dmsgq_nextnum(0) { if (!ss_) { // Currently, MessageQueue holds a socket server, and is the base class for // Thread. It seems like it makes more sense for Thread to hold the socket // server, and provide it to the MessageQueue, since the Thread controls // the I/O model, and MQ is agnostic to those details. Anyway, this causes // messagequeue_unittest to depend on network libraries... yuck. defaultss.reset(new PhysicalSocketServer()); ss_ = defaultss.get(); }
ss_->SetMessageQueue(this); }

......

// Creates the underlying OS socket (same as the "socket" function). virtual bool Create(int family, int type) { Close(); s = ::socket(family, type, 0); udp = (SOCKDGRAM == type); UpdateLastError(); if (udp) enabledevents = DE_READ | DEWRITE; return s != INVALID_SOCKET; }

seankovacs commented 11 years ago

Trying to work on this (backgrounding on iOS), but having some difficulties switching to the MacCFSocketServer. I got it working in the libjingle call client example, but can't seem to get it going here. I switched the pss_ var from Physical to MacCF, though it's getting an assertion failure.

seankovacs commented 11 years ago

This is the exact error I get: Error(common.cc:67): /Users/seankovacs/Documents/webrtcjingleproject/trunk/third_party/libjingle/talk/base/macsocketserver.cc(146): ASSERT FAILED: CFRunLoopGetCurrent() == runloop @ Wait

lukeweber commented 11 years ago

I worked on this a bit but lost track of my unwprking patch. I think in the end what I was trying was to pass the native posix socket back to a cfsocket and then try to manipulate that. Anyhow hailg was working on an xmpp framework branch. I've updated his patch to trunk and its in the branch ios-xmppframework. It has a different deps file so make sure you just manually download the xmppframework that's referenced in deps. The advantage of this is that webrtcjingle uses the iOS socket provided by xmppframework. Branch didn't seem to be working for me but was for hailg and didn't have time yet to debug why I couldn't make a call.

If you want to mess around with it you'll also need to uncomment the constant XMPP_FRAMEWORK in libjingle.gyp in third_party/libjingle as well. On May 2, 2013 4:01 PM, "Sean Kovacs" notifications@github.com wrote:

This is the exact error I get: Error(common.cc:67): /Users/seankovacs/Documents/webrtcjingleproject/trunk/third_party/libjingle/talk/base/macsocketserver.cc(146): ASSERT FAILED: CFRunLoopGetCurrent() == runloop @ Wait

— Reply to this email directly or view it on GitHubhttps://github.com/lukeweber/webrtc-jingle-client/issues/53#issuecomment-17339477 .

hailg commented 11 years ago

Hi guy, you may want to try my work at: https://mega.co.nz/#!v1JwlCIT!BVNtzzCb3HAyi91mHyY-0FCvjNZcIjnlOA2tLT4C3zE Hoping Luke can debug why it cannot run on his side and merge the code to the current branch.

On Fri, May 3, 2013 at 4:00 AM, Luke Weber notifications@github.com wrote:

I worked on this a bit but lost track of my unwprking patch. I think in the end what I was trying was to pass the native posix socket back to a cfsocket and then try to manipulate that. Anyhow hailg was working on an xmpp framework branch. I've updated his patch to trunk and its in the branch ios-xmppframework. It has a different deps file so make sure you just manually download the xmppframework that's referenced in deps. The advantage of this is that webrtcjingle uses the iOS socket provided by xmppframework. Branch didn't seem to be working for me but was for hailg and didn't have time yet to debug why I couldn't make a call.

If you want to mess around with it you'll also need to uncomment the constant XMPP_FRAMEWORK in libjingle.gyp in third_party/libjingle as well. On May 2, 2013 4:01 PM, "Sean Kovacs" notifications@github.com wrote:

This is the exact error I get: Error(common.cc:67):

/Users/seankovacs/Documents/webrtcjingleproject/trunk/third_party/libjingle/talk/base/macsocketserver.cc(146):

ASSERT FAILED: CFRunLoopGetCurrent() == runloop @ Wait

— Reply to this email directly or view it on GitHub< https://github.com/lukeweber/webrtc-jingle-client/issues/53#issuecomment-17339477>

.

— Reply to this email directly or view it on GitHubhttps://github.com/lukeweber/webrtc-jingle-client/issues/53#issuecomment-17364407 .

seankovacs commented 11 years ago

Yeah I was able to get the voip in the background thing working. Just this occasional ssl write error. I'll try hailg's version using the ios xmppframework and see if that helps.

lukeweber commented 11 years ago

Do you mind sharing, others might find the code useful?

What are your thoughts on xmppframework vs just using libjingle?