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
......@@ -15,7 +15,7 @@
</statement>
</block>
<block type="component_event" id="4" x="0" y="92">
<mutation component_type="BarcodeScanner" instance_name="BarcodeScanner1" event_name="AfterScan"></mutation>
<mutation component_type="BarcodeScanner" is_generic="false" instance_name="BarcodeScanner1" event_name="AfterScan"></mutation>
<field name="COMPONENT_SELECTOR">BarcodeScanner1</field>
<statement name="DO">
<block type="component_set_get" id="5" inline="false">
......@@ -90,7 +90,7 @@
<field name="COMPONENT_SELECTOR">Web1</field>
<value name="ARG0">
<block type="lists_create_with" id="17" inline="false">
<mutation items="8"></mutation>
<mutation items="9"></mutation>
<value name="ADD0">
<block type="lists_create_with" id="18" inline="false">
<mutation items="2"></mutation>
......@@ -222,6 +222,22 @@
</value>
</block>
</value>
<value name="ADD8">
<block type="lists_create_with" id="}V;[y55Tf$v{NV$fLE!%">
<mutation items="2"></mutation>
<comment pinned="true" h="64" w="315">Indicates that we can accept iceServers from the Rendezvous server</comment>
<value name="ADD0">
<block type="text" id="M;4c#e*(tb{AT6CJfQ4x">
<field name="TEXT">r2</field>
</block>
</value>
<value name="ADD1">
<block type="logic_boolean" id="{H$VZh}SskYpnmxy(Agi">
<field name="BOOL">TRUE</field>
</block>
</value>
</block>
</value>
</block>
</value>
</block>
......@@ -231,8 +247,8 @@
</block>
</statement>
</block>
<block type="component_event" id="27" x="0" y="870">
<mutation component_type="PhoneStatus" instance_name="PhoneStatus1" event_name="OnSettings"></mutation>
<block type="component_event" id="27" x="0" y="922">
<mutation component_type="PhoneStatus" is_generic="false" instance_name="PhoneStatus1" event_name="OnSettings"></mutation>
<field name="COMPONENT_SELECTOR">PhoneStatus1</field>
<statement name="DO">
<block type="component_set_get" id="28" inline="false">
......@@ -285,8 +301,31 @@
</block>
</statement>
</block>
<block type="component_event" id="47" x="0" y="1040">
<mutation component_type="Button" instance_name="ConnectButton" event_name="Click"></mutation>
<block type="component_event" id="MZu,PO29Xk,X*T8^%E-l" x="0" y="1092">
<mutation component_type="Web" is_generic="false" instance_name="Web1" event_name="GotText"></mutation>
<field name="COMPONENT_SELECTOR">Web1</field>
<statement name="DO">
<block type="component_method" id="O2X`f#Wz_J`eO/x}lCuS">
<mutation component_type="PhoneStatus" method_name="startWebRTC" is_generic="false" instance_name="PhoneStatus1"></mutation>
<field name="COMPONENT_SELECTOR">PhoneStatus1</field>
<value name="ARG0">
<block type="lexical_variable_get" id=",NBfs@h|1H[?vLp8E3A%">
<field name="VAR">global rendezvousServer</field>
</block>
</value>
<value name="ARG1">
<block type="lexical_variable_get" id="IIXLNV.IIZ^bR1.7-0}h">
<mutation>
<eventparam name="responseContent"></eventparam>
</mutation>
<field name="VAR">responseContent</field>
</block>
</value>
</block>
</statement>
</block>
<block type="component_event" id="47" x="0" y="1259">
<mutation component_type="Button" is_generic="false" instance_name="ConnectButton" event_name="Click"></mutation>
<field name="COMPONENT_SELECTOR">ConnectButton</field>
<statement name="DO">
<block type="component_method" id="48">
......@@ -310,7 +349,7 @@
</block>
</statement>
</block>
<block type="procedures_defnoreturn" id="34" x="0" y="1183">
<block type="procedures_defnoreturn" id="34" x="0" y="1402">
<field name="NAME">checkWiFi</field>
<statement name="STACK">
<block type="controls_if" id="35" inline="false">
......@@ -373,7 +412,7 @@
</block>
</statement>
</block>
<block type="procedures_defreturn" id="51" inline="false" x="0" y="1480">
<block type="procedures_defreturn" id="51" inline="false" x="0" y="1699">
<field name="NAME">getRendezvousServer</field>
<value name="RETURN">
<block type="component_method" id="52" inline="false">
......@@ -392,7 +431,7 @@
</block>
</value>
</block>
<block type="procedures_defreturn" id="55" inline="false" x="0" y="1620">
<block type="procedures_defreturn" id="55" inline="false" x="0" y="1839">
<mutation>
<arg name="input"></arg>
</mutation>
......@@ -423,8 +462,8 @@
</block>
</value>
</block>
<block type="component_event" id="61" x="0" y="1746">
<mutation component_type="Notifier" instance_name="Notifier1" event_name="AfterChoosing"></mutation>
<block type="component_event" id="61" x="0" y="1965">
<mutation component_type="Notifier" is_generic="false" instance_name="Notifier1" event_name="AfterChoosing"></mutation>
<field name="COMPONENT_SELECTOR">Notifier1</field>
<statement name="DO">
<block type="controls_if" id="62" inline="false">
......@@ -455,7 +494,7 @@
</block>
</statement>
</block>
<block type="procedures_defnoreturn" id="67" x="0" y="1913">
<block type="procedures_defnoreturn" id="67" x="0" y="2132">
<mutation>
<arg name="x"></arg>
</mutation>
......@@ -552,8 +591,8 @@
</block>
</statement>
</block>
<block type="component_event" id="S~hQs_KH8?5y90Ie^-Ok" x="0" y="2312">
<mutation component_type="CheckBox" instance_name="CheckBox1" event_name="Changed"></mutation>
<block type="component_event" id="S~hQs_KH8?5y90Ie^-Ok" x="0" y="2531">
<mutation component_type="CheckBox" is_generic="false" instance_name="CheckBox1" event_name="Changed"></mutation>
<field name="COMPONENT_SELECTOR">CheckBox1</field>
<statement name="DO">
<block type="component_set_get" id="|6eRa(NKdy44ozm2s[6k">
......@@ -574,7 +613,7 @@
</block>
</statement>
</block>
<block type="procedures_defreturn" id="79" inline="false" x="0" y="2404">
<block type="procedures_defreturn" id="79" inline="false" x="0" y="2623">
<mutation>
<arg name="code"></arg>
</mutation>
......@@ -674,7 +713,7 @@
</block>
</value>
</block>
<block type="procedures_defnoreturn" id="98" x="0" y="2777">
<block type="procedures_defnoreturn" id="98" x="0" y="2996">
<field name="NAME">resetRendezvousServer</field>
<statement name="STACK">
<block type="lexical_variable_set" id="99" inline="false">
......@@ -698,8 +737,8 @@
</block>
</statement>
</block>
<block type="component_event" id="103" x="0" y="2920">
<mutation component_type="Button" instance_name="ResetRendezvousServer" event_name="Click"></mutation>
<block type="component_event" id="103" x="0" y="3139">
<mutation component_type="Button" is_generic="false" instance_name="ResetRendezvousServer" event_name="Click"></mutation>
<field name="COMPONENT_SELECTOR">ResetRendezvousServer</field>
<statement name="DO">
<block type="procedures_callnoreturn" id="104">
......@@ -732,8 +771,8 @@
</block>
</statement>
</block>
<block type="component_event" id="109" x="0" y="3064">
<mutation component_type="Button" instance_name="ScanButton" event_name="Click"></mutation>
<block type="component_event" id="109" x="0" y="3283">
<mutation component_type="Button" is_generic="false" instance_name="ScanButton" event_name="Click"></mutation>
<field name="COMPONENT_SELECTOR">ScanButton</field>
<statement name="DO">
<block type="component_method" id="110">
......@@ -742,8 +781,8 @@
</block>
</statement>
</block>
<block type="component_event" id="111" x="0" y="3156">
<mutation component_type="Form" instance_name="Screen1" event_name="Initialize"></mutation>
<block type="component_event" id="111" x="0" y="3375">
<mutation component_type="Form" is_generic="false" instance_name="Screen1" event_name="Initialize"></mutation>
<field name="COMPONENT_SELECTOR">Screen1</field>
<statement name="DO">
<block type="lexical_variable_set" id="112" inline="false">
......@@ -922,7 +961,7 @@
</block>
</statement>
</block>
<block type="procedures_defnoreturn" id="139" x="0" y="3665">
<block type="procedures_defnoreturn" id="139" x="0" y="3884">
<mutation>
<arg name="value"></arg>
<arg name="permanent"></arg>
......@@ -966,8 +1005,8 @@
</block>
</statement>
</block>
<block type="component_event" id="147" x="0" y="3873">
<mutation component_type="Button" instance_name="SetRenzvousServer" event_name="Click"></mutation>
<block type="component_event" id="147" x="0" y="4092">
<mutation component_type="Button" is_generic="false" instance_name="SetRenzvousServer" event_name="Click"></mutation>
<field name="COMPONENT_SELECTOR">SetRenzvousServer</field>
<statement name="DO">
<block type="procedures_callnoreturn" id="148" inline="false">
......@@ -1021,7 +1060,7 @@
</block>
</statement>
</block>
<block type="procedures_defnoreturn" id="156" x="0" y="4094">
<block type="procedures_defnoreturn" id="156" x="0" y="4313">
<field name="NAME">startdirectconnect</field>
<statement name="STACK">
<block type="local_declaration_statement" id="157" inline="false">
......@@ -1069,7 +1108,7 @@
</block>
</statement>
</block>
<block type="global_declaration" id="164" inline="false" x="0" y="4327">
<block type="global_declaration" id="164" inline="false" x="0" y="4546">
<field name="NAME">rendezvousServer</field>
<value name="VALUE">
<block type="text" id="165">
......@@ -1077,5 +1116,5 @@
</block>
</value>
</block>
<yacodeblocks ya-version="176" language-version="23"></yacodeblocks>
<yacodeblocks ya-version="184" language-version="26"></yacodeblocks>
</xml>
\ No newline at end of file
#|
$JSON
{"authURL":["*UNKNOWN*","jis.qyv.net"],"YaVersion":"176","Source":"Form","Properties":{"$Name":"Screen1","$Type":"Form","$Version":"24","AccentColor":"&HFF128BA8","AlignHorizontal":"3","AppName":"repl","BackgroundColor":"&H00FFFFFF","BackgroundImage":"mooning.png","Icon":"AI2Companion-Icon.png","PrimaryColor":"&HFFA5CF47","PrimaryColorDark":"&HFF516623","Scrollable":"True","Title":"MIT App Inventor 2","Uuid":"0","$Components":[{"$Name":"SettingsPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"850149444","Visible":"False","$Components":[{"$Name":"settingsintro","$Type":"Label","$Version":"4","HasMargins":"False","Text":"App Inventor Companion Settings","Uuid":"1903510378"},{"$Name":"HorizontalArrangement4","$Type":"HorizontalArrangement","$Version":"3","Uuid":"289079952","$Components":[{"$Name":"Label12","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Set Rendezvous Server: ","Uuid":"-321156745"},{"$Name":"rendezvoustextbox","$Type":"TextBox","$Version":"5","Hint":"Hint for TextBox1","Uuid":"-1218562375"}]},{"$Name":"HorizontalArrangement5","$Type":"HorizontalArrangement","$Version":"3","Uuid":"808500704","$Components":[{"$Name":"SetRenzvousServer","$Type":"Button","$Version":"6","Text":"Set Rendezvous Server","Uuid":"1282830233"},{"$Name":"ResetRendezvousServer","$Type":"Button","$Version":"6","Text":"Reset to Default","Uuid":"-2110364096"}]},{"$Name":"aidLabel","$Type":"Label","$Version":"4","Uuid":"-1496954497"}]},{"$Name":"MainPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-1725916419","$Components":[{"$Name":"EmulatorPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"2041308688","$Components":[{"$Name":"Label5","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Running using the emulator or USB,\nwaiting to get blocks...","Uuid":"-962295936"}]},{"$Name":"ErrorLabel","$Type":"Label","$Version":"4","HasMargins":"False","Width":"-2","TextAlignment":"1","TextColor":"&HFFFF0000","Uuid":"-799466554"},{"$Name":"PhonePanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"1543111896","$Components":[{"$Name":"Spacer1","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-1762047873","Visible":"False"},{"$Name":"instructionContainer","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-775134396","$Components":[{"$Name":"Spacer2","$Type":"Label","$Version":"4","HasMargins":"False","Width":"8","Uuid":"567138142"},{"$Name":"Image2","$Type":"Image","$Version":"3","Picture":"Instructions.png","Uuid":"1124037216"},{"$Name":"Spacer3","$Type":"Label","$Version":"4","HasMargins":"False","Width":"8","Uuid":"-825438138"}]},{"$Name":"Label10","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-1942717984"},{"$Name":"HorizontalArrangement2","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"1345116128","$Components":[{"$Name":"Label7","$Type":"Label","$Version":"4","HasMargins":"False","Width":"16","Uuid":"-1172148075"},{"$Name":"CodeBox","$Type":"TextBox","$Version":"5","BackgroundColor":"&HFFFFFFFF","FontTypeface":"1","Width":"-2","Hint":"Six Character Code","MultiLine":"True","TextAlignment":"1","Uuid":"933834161"},{"$Name":"Label8","$Type":"Label","$Version":"4","HasMargins":"False","Width":"16","Uuid":"-198600942"}]},{"$Name":"Label9","$Type":"Label","$Version":"4","HasMargins":"False","Height":"4","Uuid":"-2012312374"},{"$Name":"ConnectButton","$Type":"Button","$Version":"6","BackgroundColor":"&HFFFFFF00","FontSize":"18","Image":"connectwCode.png","TextColor":"&HFF000000","Uuid":"-942061234"},{"$Name":"Spacer","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-882888941"},{"$Name":"ScanButton","$Type":"Button","$Version":"6","BackgroundColor":"&HFF00FF00","FontSize":"18","Image":"connectwQR.png","TextColor":"&HFFFFFFFF","Uuid":"875036558"}]},{"$Name":"IPContainer","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-907976471","$Components":[{"$Name":"Label4","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Your IP Address is: ","Uuid":"-955739485"},{"$Name":"ipaddrlabel","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Unknown","Uuid":"-1112644181"}]},{"$Name":"HorizontalArrangement3","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-2066763735","$Components":[{"$Name":"Label11","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Version: ","Uuid":"-905541901"},{"$Name":"versionlabel","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Unknown","Uuid":"1289286712"}]},{"$Name":"CheckBox1","$Type":"CheckBox","$Version":"2","Text":"Use Legacy Connection","Uuid":"-1087572524"},{"$Name":"PhoneStatus1","$Type":"PhoneStatus","$Version":"1","Uuid":"849809400"},{"$Name":"Web1","$Type":"Web","$Version":"5","Uuid":"-1876664126"},{"$Name":"BarcodeScanner1","$Type":"BarcodeScanner","$Version":"2","Uuid":"1874783275"},{"$Name":"Notifier1","$Type":"Notifier","$Version":"5","Uuid":"-30695151"}]},{"$Name":"TinyDB1","$Type":"TinyDB","$Version":"2","Uuid":"288495309"}]}}
{"authURL":["*UNKNOWN*","jis.qyv.net"],"YaVersion":"184","Source":"Form","Properties":{"$Name":"Screen1","$Type":"Form","$Version":"24","AccentColor":"&HFF128BA8","AlignHorizontal":"3","AppName":"repl","BackgroundColor":"&H00FFFFFF","BackgroundImage":"mooning.png","Icon":"AI2Companion-Icon.png","PrimaryColor":"&HFFA5CF47","PrimaryColorDark":"&HFF516623","Scrollable":"True","Title":"MIT App Inventor 2","Uuid":"0","$Components":[{"$Name":"SettingsPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"850149444","Visible":"False","$Components":[{"$Name":"settingsintro","$Type":"Label","$Version":"4","HasMargins":"False","Text":"App Inventor Companion Settings","Uuid":"1903510378"},{"$Name":"HorizontalArrangement4","$Type":"HorizontalArrangement","$Version":"3","Uuid":"289079952","$Components":[{"$Name":"Label12","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Set Rendezvous Server: ","Uuid":"-321156745"},{"$Name":"rendezvoustextbox","$Type":"TextBox","$Version":"5","Hint":"Hint for TextBox1","Uuid":"-1218562375"}]},{"$Name":"HorizontalArrangement5","$Type":"HorizontalArrangement","$Version":"3","Uuid":"808500704","$Components":[{"$Name":"SetRenzvousServer","$Type":"Button","$Version":"6","Text":"Set Rendezvous Server","Uuid":"1282830233"},{"$Name":"ResetRendezvousServer","$Type":"Button","$Version":"6","Text":"Reset to Default","Uuid":"-2110364096"}]},{"$Name":"aidLabel","$Type":"Label","$Version":"4","Uuid":"-1496954497"}]},{"$Name":"MainPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-1725916419","$Components":[{"$Name":"EmulatorPanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"2041308688","$Components":[{"$Name":"Label5","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Running using the emulator or USB,\nwaiting to get blocks...","Uuid":"-962295936"}]},{"$Name":"ErrorLabel","$Type":"Label","$Version":"4","HasMargins":"False","Width":"-2","TextAlignment":"1","TextColor":"&HFFFF0000","Uuid":"-799466554"},{"$Name":"PhonePanel","$Type":"VerticalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"1543111896","$Components":[{"$Name":"Spacer1","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-1762047873","Visible":"False"},{"$Name":"instructionContainer","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-775134396","$Components":[{"$Name":"Spacer2","$Type":"Label","$Version":"4","HasMargins":"False","Width":"8","Uuid":"567138142"},{"$Name":"Image2","$Type":"Image","$Version":"3","Picture":"Instructions.png","Uuid":"1124037216"},{"$Name":"Spacer3","$Type":"Label","$Version":"4","HasMargins":"False","Width":"8","Uuid":"-825438138"}]},{"$Name":"Label10","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-1942717984"},{"$Name":"HorizontalArrangement2","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"1345116128","$Components":[{"$Name":"Label7","$Type":"Label","$Version":"4","HasMargins":"False","Width":"16","Uuid":"-1172148075"},{"$Name":"CodeBox","$Type":"TextBox","$Version":"5","BackgroundColor":"&HFFFFFFFF","FontTypeface":"1","Width":"-2","Hint":"Six Character Code","MultiLine":"True","TextAlignment":"1","Uuid":"933834161"},{"$Name":"Label8","$Type":"Label","$Version":"4","HasMargins":"False","Width":"16","Uuid":"-198600942"}]},{"$Name":"Label9","$Type":"Label","$Version":"4","HasMargins":"False","Height":"4","Uuid":"-2012312374"},{"$Name":"ConnectButton","$Type":"Button","$Version":"6","BackgroundColor":"&HFFFFFF00","FontSize":"18","Image":"connectwCode.png","TextColor":"&HFF000000","Uuid":"-942061234"},{"$Name":"Spacer","$Type":"Label","$Version":"4","HasMargins":"False","Height":"8","Uuid":"-882888941"},{"$Name":"ScanButton","$Type":"Button","$Version":"6","BackgroundColor":"&HFF00FF00","FontSize":"18","Image":"connectwQR.png","TextColor":"&HFFFFFFFF","Uuid":"875036558"}]},{"$Name":"IPContainer","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-907976471","$Components":[{"$Name":"Label4","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Your IP Address is: ","Uuid":"-955739485"},{"$Name":"ipaddrlabel","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Unknown","Uuid":"-1112644181"}]},{"$Name":"HorizontalArrangement3","$Type":"HorizontalArrangement","$Version":"3","AlignHorizontal":"3","Width":"-2","Uuid":"-2066763735","$Components":[{"$Name":"Label11","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Version: ","Uuid":"-905541901"},{"$Name":"versionlabel","$Type":"Label","$Version":"4","HasMargins":"False","Text":"Unknown","Uuid":"1289286712"}]},{"$Name":"CheckBox1","$Type":"CheckBox","$Version":"2","Text":"Use Legacy Connection","Uuid":"-1087572524"},{"$Name":"PhoneStatus1","$Type":"PhoneStatus","$Version":"1","Uuid":"849809400"},{"$Name":"Web1","$Type":"Web","$Version":"5","Uuid":"-1876664126"},{"$Name":"BarcodeScanner1","$Type":"BarcodeScanner","$Version":"2","UseExternalScanner":"False","Uuid":"1874783275"},{"$Name":"Notifier1","$Type":"Notifier","$Version":"6","Uuid":"-30695151"}]},{"$Name":"TinyDB1","$Type":"TinyDB","$Version":"2","Uuid":"288495309"}]}}
|#
\ No newline at end of file
......@@ -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);
......
......@@ -9,6 +9,7 @@ import android.content.Context;
import android.util.Log;
import com.google.appinventor.components.common.YaVersion;
import com.google.appinventor.components.runtime.ReplForm;
import java.io.BufferedReader;
......@@ -21,7 +22,8 @@ import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
......@@ -59,6 +61,8 @@ import org.webrtc.SessionDescription;
public class WebRTCNativeMgr {
private static final boolean DEBUG = true;
private static final String LOG_TAG = "AppInvWebRTC";
private static final CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
......@@ -74,7 +78,9 @@ public class WebRTCNativeMgr {
private boolean first = true; // This is used for logging in the Rendezvous server
private Random random = new Random();
private DataChannel dataChannel = null;
private String rendezvousServer = "rendezvous.appinventor.mit.edu"; // This should always be over-written
private String rendezvousServer = null; // Primary (first level) Rendezvous server
private String rendezvousServer2 = null; // Second level (webrtc rendezvous) Rendezvous server
private List<PeerConnection.IceServer> iceServers = new ArrayList();
Timer timer = new Timer();
......@@ -85,8 +91,10 @@ public class WebRTCNativeMgr {
public void onCreateSuccess(SessionDescription sessionDescription) {
try {
Log.d(LOG_TAG, "sdp.type = " + sessionDescription.type.canonicalForm());
Log.d(LOG_TAG, "sdp.description = " + sessionDescription.description);
if (DEBUG) {
Log.d(LOG_TAG, "sdp.type = " + sessionDescription.type.canonicalForm());
Log.d(LOG_TAG, "sdp.description = " + sessionDescription.description);
}
DataChannel.Init init = new DataChannel.Init();
if (sessionDescription.type == SessionDescription.Type.OFFER) {
peerConnection.setRemoteDescription(sdpObserver, sessionDescription);
......@@ -100,9 +108,6 @@ public class WebRTCNativeMgr {
response.put("offer", offer);
sendRendezvous(response);
}
// Log.d(LOG_TAG, "About to call create data connection");
// peerConnection.createDataChannel("data", init);
// Log.d(LOG_TAG, "createDataChannel returned");
} catch (Exception e) {
Log.e(LOG_TAG, "Exception during onCreateSuccess", e);
}
......@@ -124,19 +129,25 @@ public class WebRTCNativeMgr {
}
public void onDataChannel(DataChannel dataChannel) {
Log.d(LOG_TAG, "Have Data Channel!");
Log.d(LOG_TAG, "v5");
if (DEBUG) {
Log.d(LOG_TAG, "Have Data Channel!");
Log.d(LOG_TAG, "v5");
}
WebRTCNativeMgr.this.dataChannel = dataChannel;
dataChannel.registerObserver(dataObserver);
keepPolling = false; // Turn off talking to the rendezvous server
timer.cancel();
Log.d(LOG_TAG, "Poller() Canceled");
if (DEBUG) {
Log.d(LOG_TAG, "Poller() Canceled");
}
seenNonces.clear();
}
public void onIceCandidate(IceCandidate iceCandidate) {
try {
Log.d(LOG_TAG, "IceCandidate = " + iceCandidate.toString());
if (DEBUG) {
Log.d(LOG_TAG, "IceCandidate = " + iceCandidate.toString());
}
/* Send to Peer */
JSONObject response = new JSONObject();
response.put("nonce", random.nextInt(100000));
......@@ -186,7 +197,9 @@ public class WebRTCNativeMgr {
Log.e(LOG_TAG, "onMessage decoder error", e);
return;
}
Log.d(LOG_TAG, "onMessage: received: " + input);
if (DEBUG) {
Log.d(LOG_TAG, "onMessage: received: " + input);
}
form.evalScheme(input);
}
......@@ -194,8 +207,38 @@ public class WebRTCNativeMgr {
}
};
public WebRTCNativeMgr(String rendezvousServer) {
public WebRTCNativeMgr(String rendezvousServer, String rendezvousResult) {
this.rendezvousServer = rendezvousServer;
if (rendezvousResult.isEmpty() || rendezvousResult.startsWith("OK")) {
/* Provide a default when the rendezvous server doesn't provide one */
rendezvousResult = "{\"rendezvous2\" : \"" + YaVersion.RENDEZVOUS_SERVER + "\"," +
"\"iceservers\" : " +
"[{ \"server\" : \"turn:turn.appinventor.mit.edu:3478\"," +
"\"username\" : \"oh\"," +
"\"password\" : \"boy\"}]}";
}
try {
JSONObject resultJson = new JSONObject(rendezvousResult);
this.rendezvousServer2 = resultJson.getString("rendezvous2");
JSONArray iceServerArray = resultJson.getJSONArray("iceservers");
this.iceServers = new ArrayList(iceServerArray.length());
for (int i = 0; i < iceServerArray.length(); i++) {
JSONObject jsonServer = iceServerArray.getJSONObject(i);
PeerConnection.IceServer.Builder builder = PeerConnection.IceServer.builder(jsonServer.getString("server"));
if (DEBUG) {
Log.d(LOG_TAG, "Adding iceServer = " + jsonServer.getString("server"));
}
if (jsonServer.has("username")) {
builder.setUsername(jsonServer.getString("username"));
}
if (jsonServer.has("password")) {
builder.setPassword(jsonServer.getString("password"));
}
this.iceServers.add(builder.createIceServer());
}
} catch (JSONException e) {
Log.e(LOG_TAG, "parsing iceServers:", e);
}
}
public void initiate(ReplForm form, Context context, String code) {
......@@ -208,16 +251,9 @@ public class WebRTCNativeMgr {
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
/* Create the factory */
PeerConnectionFactory factory = new PeerConnectionFactory(options);
/* Create our list of iceServers (only one for now, note this information is secret!) */
PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("turn:turn.appinventor.mit.edu:3478")
.setUsername("oh")
.setPassword("boy")
.createIceServer();
/* Create the Observer which will be called when events heppen */
peerConnection = factory.createPeerConnection(Collections.singletonList(iceServer), new MediaConstraints(),
observer);
// peerConnection.createOffer(sdpObserver, new MediaConstraints()); // Let's see what happens :-)
/* Create the peer connection using the iceServers we received in the constructor */
peerConnection = factory.createPeerConnection(iceServers, new MediaConstraints(),
observer);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
......@@ -237,9 +273,12 @@ public class WebRTCNativeMgr {
return;
}
Log.d(LOG_TAG, "Poller() Called");
if (DEBUG) {
Log.d(LOG_TAG, "Poller() Called");
Log.d(LOG_TAG, "Poller: rendezvousServer2 = " + rendezvousServer2);
}
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://" + rendezvousServer + "/rendezvous2/" + rCode + "-s");
HttpGet request = new HttpGet("http://" + rendezvousServer2 + "/rendezvous2/" + rCode + "-s");
HttpResponse response = client.execute(request);
StringBuilder sb = new StringBuilder();
......@@ -259,26 +298,36 @@ public class WebRTCNativeMgr {
}
if (!keepPolling) {
Log.d(LOG_TAG, "keepPolling is false, we're done!");
if (DEBUG) {
Log.d(LOG_TAG, "keepPolling is false, we're done!");
}
return;
}
String responseText = sb.toString();
Log.d(LOG_TAG, "response = " + responseText);
if (DEBUG) {
Log.d(LOG_TAG, "response = " + responseText);
}
if (responseText.equals("")) {
Log.d(LOG_TAG, "Received an empty response");
if (DEBUG) {
Log.d(LOG_TAG, "Received an empty response");
}
// Empty Response
return;
}
JSONArray jsonArray = new JSONArray(responseText);
Log.d(LOG_TAG, "jsonArray.length() = " + jsonArray.length());
if (DEBUG) {
Log.d(LOG_TAG, "jsonArray.length() = " + jsonArray.length());
}
int i = 0;
while (i < jsonArray.length()) {
Log.d(LOG_TAG, "i = " + i);
Log.d(LOG_TAG, "element = " + jsonArray.optString(i));
if (DEBUG) {
Log.d(LOG_TAG, "i = " + i);
Log.d(LOG_TAG, "element = " + jsonArray.optString(i));
}
JSONObject element = (JSONObject) jsonArray.get(i);
if (!haveOffer) {
if (!element.has("offer")) {
......@@ -288,18 +337,24 @@ public class WebRTCNativeMgr {
JSONObject offer = (JSONObject) element.get("offer");
String sdp = offer.optString("sdp");
String type = offer.optString("type");
Log.d(LOG_TAG, "sdb = " + sdp);
Log.d(LOG_TAG, "type = " + type);
haveOffer = true;
Log.d(LOG_TAG, "About to set remote offer");
if (DEBUG) {
Log.d(LOG_TAG, "sdb = " + sdp);
Log.d(LOG_TAG, "type = " + type);
Log.d(LOG_TAG, "About to set remote offer");
}
peerConnection.setRemoteDescription(sdpObserver,
new SessionDescription(SessionDescription.Type.OFFER, sdp));
peerConnection.createAnswer(sdpObserver, new MediaConstraints());
Log.d(LOG_TAG, "createAnswer returned");
if (DEBUG) {
Log.d(LOG_TAG, "createAnswer returned");
}
i = -1;
} else if (element.has("nonce")) {
if (element.isNull("candidate")) {
Log.d(LOG_TAG, "Received a null candidate, skipping...");
if (DEBUG) {
Log.d(LOG_TAG, "Received a null candidate, skipping...");
}
i++;
continue;
}
......@@ -308,18 +363,26 @@ public class WebRTCNativeMgr {
String sdpcandidate = candidate.optString("candidate");
String sdpMid = candidate.optString("sdpMid");
int sdpMLineIndex = candidate.optInt("sdpMLineIndex");
Log.d(LOG_TAG, "candidate = " + sdpcandidate);
if (DEBUG) {
Log.d(LOG_TAG, "candidate = " + sdpcandidate);
}
if (!seenNonces.contains(nonce)) {
seenNonces.add(nonce);
Log.d(LOG_TAG, "new nonce, about to add candidate!");
if (DEBUG) {
Log.d(LOG_TAG, "new nonce, about to add candidate!");
}
IceCandidate iceCandidate = new IceCandidate(sdpMid, sdpMLineIndex, sdpcandidate);
peerConnection.addIceCandidate(iceCandidate);
Log.d(LOG_TAG, "addIceCandidate returned");
if (DEBUG) {
Log.d(LOG_TAG, "addIceCandidate returned");
}
}
}
i++;
}
Log.d(LOG_TAG, "exited loop");
if (DEBUG) {
Log.d(LOG_TAG, "exited loop");
}
} catch (IOException e) {
Log.e(LOG_TAG, "Caught IOException: " + e.toString(), e);
} catch (JSONException e) {
......@@ -339,13 +402,15 @@ public class WebRTCNativeMgr {
data.put("apiversion", SdkLevel.getLevel());
}
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://" + rendezvousServer + "/rendezvous2/");
HttpPost post = new HttpPost("http://" + rendezvousServer2 + "/rendezvous2/");
try {
Log.d(LOG_TAG, "About to send = " + data.toString());
if (DEBUG) {
Log.d(LOG_TAG, "About to send = " + data.toString());
}
post.setEntity(new StringEntity(data.toString()));
client.execute(post);
} catch (IOException e) {
Log.d(LOG_TAG, "sendRedezvous IOException = " + e.toString());
Log.e(LOG_TAG, "sendRedezvous IOException", e);
}
} catch (Exception e) {
Log.e(LOG_TAG, "Exception in sendRendezvous", e);
......
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