Commit 67407991 authored by Jeffrey I. Schiller's avatar Jeffrey I. Schiller Committed by Jeffrey Schiller

Add support for a “secondary” Rendezvous Server

The primary rendezvous server is used for the initial rendezvous,
whether using WebRTC or not (Legacy Mode). This change provides the
location for a secondary rendezvous server to use for the WebRTC
negotiation. This is only done if the Companion indicates that it
supports this feature (sets “r2” to true in the JSON object it
posts). Any information provided by the Companion can be used by the
primary rendezvous server to determine which secondary server to use.

Change-Id: I8706c4f0fe66a0e902595689896003feff9cdff7
parent 4f284367
......@@ -6,7 +6,7 @@ $Source $Yail
(require <com.google.youngandroid.runtime>)
(def (p$badversion ) (set-and-coerce-property! 'ErrorLabel 'Text "The version of App Inventor you are using is not compatible with this Companion app. " 'text))
(def (p$callrendezvous $code) (set-and-coerce-property! 'Web1 'Url (call-yail-primitive string-append (*list-for-runtime* "http://" (get-var g$rendezvousServer) "/rendezvous/" ) '(text text text ) "join") 'text)(call-component-method 'Web1 'PostText (*list-for-runtime* (call-component-method 'Web1 'BuildRequestData (*list-for-runtime* (call-yail-primitive make-yail-list (*list-for-runtime* (call-yail-primitive make-yail-list (*list-for-runtime* "key" (lexical-value $code) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "ipaddr" (call-component-method 'PhoneStatus1 'GetWifiIpAddress (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "port" "9987" ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "webrtc" (call-yail-primitive yail-not (*list-for-runtime* (get-property 'CheckBox1 'Checked)) '(boolean) "not") ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "version" (call-component-method 'PhoneStatus1 'GetVersionName (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "api" (call-component-method 'PhoneStatus1 'SdkLevel (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "installer" (call-component-method 'PhoneStatus1 'GetInstaller (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "aid" (call-component-method 'PhoneStatus1 'InstallationId (*list-for-runtime*) '()) ) '(any any ) "make a list") ) '(any any any any any any any any ) "make a list")) '(list))) '(text)))
(def (p$callrendezvous $code) (set-and-coerce-property! 'Web1 'Url (call-yail-primitive string-append (*list-for-runtime* "http://" (get-var g$rendezvousServer) "/rendezvous/" ) '(text text text ) "join") 'text)(call-component-method 'Web1 'PostText (*list-for-runtime* (call-component-method 'Web1 'BuildRequestData (*list-for-runtime* (call-yail-primitive make-yail-list (*list-for-runtime* (call-yail-primitive make-yail-list (*list-for-runtime* "key" (lexical-value $code) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "ipaddr" (call-component-method 'PhoneStatus1 'GetWifiIpAddress (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "port" "9987" ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "webrtc" (call-yail-primitive yail-not (*list-for-runtime* (get-property 'CheckBox1 'Checked)) '(boolean) "not") ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "version" (call-component-method 'PhoneStatus1 'GetVersionName (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "api" (call-component-method 'PhoneStatus1 'SdkLevel (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "installer" (call-component-method 'PhoneStatus1 'GetInstaller (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "aid" (call-component-method 'PhoneStatus1 'InstallationId (*list-for-runtime*) '()) ) '(any any ) "make a list") (call-yail-primitive make-yail-list (*list-for-runtime* "r2" #t ) '(any any ) "make a list") ) '(any any any any any any any any any ) "make a list")) '(list))) '(text)))
(def (p$checkWiFi ) (if (call-yail-primitive yail-equal? (*list-for-runtime* 1 (call-yail-primitive string-starts-at (*list-for-runtime* (call-component-method 'PhoneStatus1 'GetWifiIpAddress (*list-for-runtime*) '()) "Error") '(text text) "starts at")) '(any any) "=") (begin (call-component-method 'Notifier1 'ShowChooseDialog (*list-for-runtime* "Your Device does not appear to have a WiFi Connection" "No WiFi" "Continue without WiFi" "Exit" #f) '(text text text text boolean)))))
(def (p$getRendezvousServer ) (call-component-method 'TinyDB1 'GetValue (*list-for-runtime* "rendezvousServer" (get-var g$rendezvousServer)) '(text any)))
(def (p$isAPK $input) (call-yail-primitive yail-equal? (*list-for-runtime* (call-yail-primitive string-starts-at (*list-for-runtime* (lexical-value $input) "http://") '(text text) "starts at") 1) '(any any) "="))
......@@ -372,9 +372,13 @@ $Source $Yail
(add-component MainPanel com.google.appinventor.components.runtime.Web Web1
)
(define-event Web1 GotText($url $responseCode $responseType $responseContent)(set-this-form)
(call-component-method 'PhoneStatus1 'startWebRTC (*list-for-runtime* (get-var g$rendezvousServer) (lexical-value $responseContent)) '(text text)))
;;; BarcodeScanner1
(add-component MainPanel com.google.appinventor.components.runtime.BarcodeScanner BarcodeScanner1 (set-and-coerce-property! 'BarcodeScanner1 'UseExternalScanner #f 'boolean)
(add-component MainPanel com.google.appinventor.components.runtime.BarcodeScanner BarcodeScanner1
(set-and-coerce-property! 'BarcodeScanner1 'UseExternalScanner #f 'boolean)
)
(define-event BarcodeScanner1 AfterScan($result)(set-this-form)
......
......@@ -806,9 +806,9 @@ public class Ode implements EntryPoint {
}
if (result.getRendezvousServer() != null) {
setRendezvousServer(result.getRendezvousServer());
setRendezvousServer(result.getRendezvousServer(), true);
} else {
setRendezvousServer(YaVersion.RENDEZVOUS_SERVER);
setRendezvousServer(YaVersion.RENDEZVOUS_SERVER, false);
}
userSettings = new UserSettings(user);
......@@ -2474,10 +2474,28 @@ public class Ode implements EntryPoint {
}
}
// Native code to set the top level rendezvousServer variable
// where blockly code can easily find it.
private native void setRendezvousServer(String server) /*-{
/**
* setRendezvousServer
*
* Setup the Rendezvous server location.
*
* There are two places where the rendezvous servers is setup. The
* "compiled in" version is in YaVersion.RENDEZVOUS_SERVER. The
* runtime version is in appengine-web.xml. If they differ, we set
* "top.includeQRcode" to true so that when we display the
* QRCode, we include the name of the Rendezvous server. Note: What
* is important here is what version of the rendezvous server is
* compiled into the Companion itself. The Companion does *not* get
* the default version from YaVersion, but from the blocks that are
* used to build the Companion.
*
* @param server the domain name of the Rendezvous servers
* @param inclQRcode true to indicate that the rendezvous server domain name should be included in the QR Code
*
*/
private native void setRendezvousServer(String server, boolean inclQRcode) /*-{
top.rendezvousServer = server;
top.includeQRcode = inclQRcode;
}-*/;
// Native code to open a new window (or tab) to display the
......
......@@ -78,7 +78,11 @@ Blockly.ReplStateObj.prototype = {
'rendezvouscode' : null, // Code used for Rendezvous (hash of replcode)
'dialog' : null, // The Dialog Box with the code and QR Code
'count' : 0, // Count of number of reads from rendezvous server
'didversioncheck' : false
'didversioncheck' : false,
'rendezvous2' : 'http://rendezvous.appinventor.mit.edu/rendezvous2/',
'iceservers' : { 'iceServers' : [ { 'urls' : ['turn:turn.appinventor.mit.edu:3478'],
'username' : 'oh',
'credential' : 'boy' }]}
};
// Blockly is only loaded once now, so we can init this here.
......@@ -263,11 +267,6 @@ Blockly.ReplMgr.putYail = (function() {
var webrtcpeer;
var webrtcisopen = false;
var webrtcforcestop = false;
// var iceservers = { 'iceServers' : [ { 'urls' : ['stun:stun.l.google.com:19302']}]};
var iceservers = { 'iceServers' : [ { 'urls' : ['turn:turn.appinventor.mit.edu:3478'],
'username' : 'oh',
'credential' : 'boy' }]};
var webrtcrendezvous = 'http://rendezvous.appinventor.mit.edu/rendezvous2/';
var webrtcdata;
var seennonce = {};
var engine = {
......@@ -340,7 +339,7 @@ Blockly.ReplMgr.putYail = (function() {
top.ConnectProgressBar_setProgress(20, Blockly.Msg.DIALOG_SECURE_ESTABLISHING);
var poll = function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', webrtcrendezvous + key + '-r', true);
xhr.open('GET', top.ReplState.rendezvous2 + key + '-r', true);
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.response[0] == '[') {
......@@ -373,7 +372,7 @@ Blockly.ReplMgr.putYail = (function() {
};
xhr.send();
};
webrtcpeer = new RTCPeerConnection(iceservers);
webrtcpeer = new RTCPeerConnection(top.ReplState.iceservers);
webrtcpeer.oniceconnectionstatechange = function(evt) {
console.log("oniceconnectionstatechange: evt.type = " + evt.type);
if (this.iceConnectionState == "disconnected" ||
......@@ -391,7 +390,7 @@ Blockly.ReplMgr.putYail = (function() {
webrtcpeer.onicecandidate = function(evt) {
if (evt.type == 'icecandidate') {
var xhr = new XMLHttpRequest();
xhr.open('POST', webrtcrendezvous, true);
xhr.open('POST', top.ReplState.rendezvous2, true);
xhr.send(JSON.stringify({'key' : key + '-s',
'webrtc' : true,
'nonce' : Math.floor(Math.random() * 10000) + 1,
......@@ -435,7 +434,7 @@ Blockly.ReplMgr.putYail = (function() {
webrtcpeer.createOffer().then(function(desc) {
offer = desc;
var xhr = new XMLHttpRequest();
xhr.open('POST', webrtcrendezvous, true);
xhr.open('POST', top.ReplState.rendezvous2, true);
xhr.send(JSON.stringify({'key' : key + '-s',
'webrtc' : true,
'offer' : desc}));
......@@ -1369,6 +1368,22 @@ Blockly.ReplMgr.getFromRendezvous = function() {
// via HTTP because we may be using webrtc and there is no
// HTTP
// Let's see if the Rendezvous server gave us a second level to contact
// as well as a list of ice servers to override our defaults
if (json.rendezvous2) {
rs.rendezvous2 = json.rendezvous2;
}
if (json.iceservers) {
var serverlist = [];
for (var i = 0; i < json.iceservers.length; i++) {
serverlist.push({ 'urls' : [json.iceservers[i].server],
'username' : json.iceservers[i].username,
'credential' : json.iceservers[i].password });
}
rs.iceservers = { 'iceServers' : serverlist };
}
// The code below really gets things going. We will
// either call it shortly, if the Companion version is acceptable
// or in the dialog response handler below if the Companion
......@@ -1496,7 +1511,7 @@ Blockly.ReplMgr.rendPoll = function() {
Blockly.ReplMgr.makeDialogMessage = function(code) {
var scancode;
if (top.rendezvousServer != 'rendezvous.appinventor.mit.edu') { // Should really get this from YAV
if (top.includeQRcode) { // Should we include the Rendezvous server name in the QR Code?
scancode = top.rendezvousServer + ";" + code;
} else {
scancode = code;
......
......@@ -160,14 +160,18 @@ public class PhoneStatus extends AndroidNonvisibleComponent implements Component
firstSeed = seed;
/* Setup communications via WebRTC */
if (useWebRTC) {
WebRTCNativeMgr webRTCNativeMgr = new WebRTCNativeMgr(rendezvousServer);
webRTCNativeMgr.initiate((ReplForm) form, (Context)activity, seed);
((ReplForm)form).setWebRTCMgr(webRTCNativeMgr);
} else {
/*
* Set the HMAC seed, but only if we are doing the legacy HTTP
* thing. Note: Currently we *always* start the HTTP Daemon, even
* in WebRTC mode By not setting the seed, we ensure that the HTTP
* Daemon cannot accept any blocks
*
*/
if (!useWebRTC) {
AppInvHTTPD.setHmacKey(seed);
}
MessageDigest Sha1;
try {
Sha1 = MessageDigest.getInstance("SHA1");
......@@ -202,6 +206,13 @@ public class PhoneStatus extends AndroidNonvisibleComponent implements Component
}
}
@SimpleFunction(description = "Start the WebRTC engine")
public void startWebRTC(String rendezvousServer, String iceServers) {
WebRTCNativeMgr webRTCNativeMgr = new WebRTCNativeMgr(rendezvousServer, iceServers);
webRTCNativeMgr.initiate((ReplForm) form, (Context)activity, firstSeed);
((ReplForm)form).setWebRTCMgr(webRTCNativeMgr);
}
@SimpleFunction(description = "Start the internal AppInvHTTPD to listen for incoming forms. FOR REPL USE ONLY!")
public void startHTTPD(boolean secure) {
ReplForm.topform.startHTTPD(secure);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment