Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sip streaming api #88

Merged
merged 3 commits into from
Aug 1, 2019
Merged

feat: sip streaming api #88

merged 3 commits into from
Aug 1, 2019

Conversation

dgreif
Copy link
Owner

@dgreif dgreif commented Jul 31, 2019

@bourdakos1 I did a fair bit of cleanup and performance tweaking:

  • videoStream and audioStream both have the following format:
 {
    socket: Socket,
    port: number,
    onRtpPacket: Observable<{ message: Buffer, info: { address: string, port: number }>
  }
  • invite can take a new set of RtpOptions if you want to redirect the call to different ports. I'm not using this yet, but I might do this for homebridge. Haven't tested if re-invite actually works
  • vod request is immediately followed by a check for active dings (even if polling isn't enabled). I did a lot of testing and the ding was always sitting there waiting immediately, so this should work without any need for waiting or polling. It also means we start the stream as fast as possible. In my testing, I'm getting a live stream in < 2 seconds 🐎
  • Lots of other misc cleanup and parallelizing of promises for speed

If you don't have any objections, I'll get this merged and released as v5.0.0

@bourdakos1
Copy link
Contributor

hmm, it seems like the polling isn't working for me. I get stuck at "Creating SIP Session..." whether I have cameraDingsPollingSeconds: 2 set or not. this.onActiveDings.getValue() always returns an empty array

@bourdakos1
Copy link
Contributor

Just kidding I think there's something up with the camera and it just happened to be working when running with the old code, but not the new code. I'll keep you posted

@dgreif
Copy link
Owner Author

dgreif commented Aug 1, 2019

@bourdakos1 any luck? It's working perfectly for me..

Any thoughts on the api?

@bourdakos1
Copy link
Contributor

I can confirm it's just the camera's (the ring iOS app isn't loading either).

I think everything looks good, the only thing is that you only supply a tls_port to sip, but no port. When I initially tested it seemed that homebridge used the tls_port, but when doing the stream-example it just used the normal port

@dgreif
Copy link
Owner Author

dgreif commented Aug 1, 2019

Sorry @bourdakos1, I should have asked what your intentions were with the port vs tlsPort split. I can definitely see not wanting to use SRTP since you need to generate the AES key/salt and then decrypt the packets before your streamer pipes them out to a file. However, the TLS piece of this is only related to the SIP messages. The SIP url that we get back from Ring ends with ;transport=tls, which the sip module recognizes and automatically switches from UDP over to TLS. This is basically free encryption for us for all of the SIP messages so at least that part of the exchange is secure. I want to make sure I'm not missing something so I'd appreciate if you can verify my logic, but I do think we want to always be using TLS for the SIP portion.

Thanks for checking everything else over, I can't wait for the improved stream start times that this will have in homebridge. Nice work on the initial refactor!

@bourdakos1
Copy link
Contributor

That's what I was thinking as well, but I believe the sip module always creates a udp transport on port 5060 no matter what AND a tls transport on port 5061 (only if we give tls options, which we do)

@bourdakos1
Copy link
Contributor

There could be a problem running await getPort() twice without binding them first. Since, the first port will still be free when we call await getPort() again. So maybe at least change it to:

const port = await getPort({port: 5060})
const tls_port = await getPort({port: 5061})

@bourdakos1
Copy link
Contributor

bourdakos1 commented Aug 1, 2019

Yea, here's the code in https://github.com/kirm/sip.js/blob/master/sip.js to back it up:

if(options.udp === undefined || options.udp)
  protocols.UDP = makeUdpTransport(options, callbackAndLog); 
if(options.tcp === undefined || options.tcp)
  protocols.TCP = makeTcpTransport(options, callbackAndLog);
if(options.tls)
  protocols.TLS = makeTlsTransport(options, callbackAndLog);
if(options.ws_port && WebSocket)
  protocols.WS = makeWsTransport(options, callbackAndLog);

makeUdpTransport:

var address = options.address || '0.0.0.0';
var port = options.port || 5060;

var socket = dgram.createSocket(net.isIPv6(address) ? 'udp6' : 'udp4', onMessage); 
socket.bind(port, address);

makeTlsTransport:

var server = tls.createServer(options.tls, callback);
server.listen(options.tls_port || 5061, options.address);

We would have to pass udp: false to disable it

@dgreif
Copy link
Owner Author

dgreif commented Aug 1, 2019

I'm up for udp: false if you think that would work. If we always use TLS, no need to create the extra transports...thoughts?

@dgreif
Copy link
Owner Author

dgreif commented Aug 1, 2019

Just pushed a commit disable the upd and tcp transports. Does that look like a good solution to you?

@bourdakos1
Copy link
Contributor

I’m okay with it, does it work?

@bourdakos1
Copy link
Contributor

When I was using the linphone python client disabling udp always broke it for me, but I didn’t have everything nailed down properly at the time

@dgreif
Copy link
Owner Author

dgreif commented Aug 1, 2019

Works perfectly 😄. I'll push out a release in a few minutes

@dgreif dgreif merged commit a00fe31 into master Aug 1, 2019
@dgreif dgreif deleted the sip-api branch August 1, 2019 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants