AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Status: Tethering - noch Probleme mit MacOS und iOS

Status: Tethering - noch Probleme mit MacOS und iOS

Ein Thema von philipp.hofmann · begonnen am 28. Mai 2021 · letzter Beitrag vom 11. Jun 2021
Antwort Antwort
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#1

Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 28. Mai 2021, 17:48
Status: Tethering

Da das Thema deutlich aufwändiger ist, als erwartet, hier mal mein aktueller Status mit ein paar Handlungsempfehlungen.
In meinem Fall habe ich eine Haupt-App und eine Fernsteuerung. Die Fernsteuerung sucht und verbindet sich mit der Hauptapp und beide können jetzt der jeweils anderen Daten und somit Handlungs-/Anzeige-Anweisungen schicken.

- die Windows-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen
- hier ist wichtig, dass das eigene WLAN als "Privat" und nicht als "Öffentlich" gekennzeichnet wird, teilweise muss man die App auch in der Firewall nochmals bewusst erlauben.

- die Android-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen
- Permission Internet muss auf "true" gesetzt sein

- die MacOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber nicht gefunden werden.
Ursache: DoOnReceiveData wird nie errreicht

Folgende Entitlements wurden gesetzt (Entitlement.TemplateOSX.xml):
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>

- die iOS-App kann beides nicht, weder suchen und finden (discover) noch gefunden werden.
Ursache: Beim BroadcastData wird die Exception "Socket-Fehler # 65Keine Route zum Host." bzw. "Socket-Fehler # 9Falsche Dateinummer." geworfen

Ich frage mich jetzt:
a) Welche Capabitlities müssen für den Identifier auf developer.apple.com für iOS gesetzt werden?
b) Welche Capabitlities müssen für den Identifier auf developer.apple.com für MacOS gesetzt werden?
c) Welche Entitlements müssen für iOS gesetzt werden (Entitlement.TemplateiOS.xml)?
d) Welche Entitlements müssen für MacOS gesetzt werden (Entitlement.TemplateOSX.xml)?
e) Welche Properties müssen für iOS gesetzt werden (info.plist.TemplateiOS.xml)?
Muss hier z.B. com.apple.developer.networking.multicast gesetzt werden, wo man vorab auch per "Multicast Networking Entitlement Request" nachfragen muss
(und dort schon eine AppStore-URL angeben muss, obwohl die App noch gar nicht mit iOS funktioniert)
f) Welche Properties müssen für MacOS gesetzt werden (info.plist.TemplateOSX.xml)?

Tipp 1: Formulardesigner: das Profile auf Enabled setzen und den Manager aus Disabled und dem Profile keinen Manager zuweisen.
Im Programm-Code den Manager auf Enabled setzen und direkt davor dem Profile den Manager zuweisen.
Sonst wird schon sehr viel initialisert (z.B. der Netzwerk-Adapter) bevor man erstmalig Zugriff im Code auf die Komponenten hat.

Delphi-Quellcode:
  CommandApp.Manager := CommandManager;
  CommandManager.Enabled := True;
Tipp 2: IP-Adresse des eigenen Adapters nicht automatisch setzen lassen, sondern selbst per Indy auswählen:

[DELPHI]
uses IdStack, IdGlobal;

function getIPv4Address():String;
var
AAddresses: TIdStackLocalAddressList;
LAddr: TIdStackLocalAddress;
I: Integer;
prefNetwork,IP: String;
begin
AAddresses:=TIdStackLocalAddressList.Create();
prefNetwork:='192.';//can be set also outside this functionality before the manager is enabled or the manager-attribute of the profile is set
Result:='';
try
GStack.GetLocalAddressList(AAddresses);
for I := 0 to AAddresses.Count-1 do
begin
LAddr:=AAddresses[I];
IP:=LAddr.IPAddress;
if ((IP<>'127.0.0.1') and ((Result='') or ((prefNetwork>'') and (pos(prefNetwork,IP)=1) and (pos(prefNetwork,Result)<>1)))) then
begin
case LAddr.IPVersion of
Id_IPv4:
begin
mlog.info('Found IP-address*: '+IP);
Result:=IP;
end;
Id_IPv6:
begin
mlog.info('Found IP-address: '+IP);
end;
end;
end else
mlog.info('Found IP-address: '+IP);
end;
finally
AAddresses.Free;
end;
end;
[DELPHI]

Dies passiert an zwei Stellen:

System.Tether.Manager.pas
Delphi-Quellcode:
constructor TTetheringAdapter.Create;
var ip:String;
begin
  inherited;
  FRemoteManagers := TTetheringManagerInfoList.Create;
  ip:=getIPv4Address();
  if (ip>'') then
    FAdapterConnectionString := ip
  else
    FAdapterConnectionString := TTetheringManagerCommunicationThread.EMPTYTOKEN;
end;
System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkManagerCommunicationThread.Execute;
...
        if not LListening then
          raise ETetheringException.Create(SManagerNetworkCreation);

        var ip:String;
        ip:=TStringUtils.getIPv4Address();
        if (ip>'') then
          LRemoteConnectionString := ip + TetheringConnectionSeparator + FTarget
        else
          LRemoteConnectionString := EMPTYTOKEN + TetheringConnectionSeparator + FTarget;
Zur Sicherheit habe ich es noch hier eingebaut, da wird es aber höchstwahrscheinlich nicht gebraucht:

System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkAdapterCommon.DoDiscoverManagers(Timeout: Cardinal;
  const ATargetList: TTetheringTargetHosts; const AProfileGroups, AProfileTexts: TArray<string>);
...
    LCommand := TTetheringManagerCommand.Create(TTetheringNetworkManagerCommunicationThread.TetheringDiscoverManagers,
      FAdapterConnectionString, Manager.Version, [FCommunicationThread.FTarget, LGroups, LTexts]);
  end else begin
    if (pos(TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,FAdapterConnectionString)>0) then
    begin
      var ip:String;
      ip:=TStringUtils.getIPv4Address();
      if (ip>'') then
        FAdapterConnectionString:=StringReplace(FAdapterConnectionString,TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,ip,[]);
    end;
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 7. Jun 2021, 16:46
Kleines Update des Status, da ich mittlerweile raus habe, dass es ab iOS 14.x und MacOS 11.x Probleme gibt. Davor als iOS 13.x und MacOS 10.x ging es problemlos.
In Teilen geht es auch mit der neuen Version, aber leider werden iOS-14.x- und Mac-11.x-Apps mit Disover nicht gefunden, weil die Methode
procedure TTetheringNetworkManagerCommunicationThread.DoOnReceiveData nie erreicht wird.

Geändert von philipp.hofmann ( 7. Jun 2021 um 16:54 Uhr)
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 7. Jun 2021, 16:47
Status: Tethering

- die Windows-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen

- die Android-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen
- Permission Internet muss auf "true" gesetzt sein

- die iOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter iOS 14.x nicht gefunden werden (<iOS 14 funktioniert).
Ursache: DoOnReceiveData wird unter iOS 14.x nie errreicht (gleiches gilt für MacOS 11.x)
- Es muss via https://developer.apple.com/contact/...king-multicast die Berechtigung erfragt werden, das Entitlement Multicast zu setzen,
damit iOS 14.x funktioniert; im Projekt ist das Entitlement aber nicht zu setzen, dies passiert über das Provision Profile automatisch (außer man erzeugt
die Entitlement-Datei manuell);

Delphi-Quellcode:
  <key>com.apple.developer.networking.multicast</key>
  <true/>
- die MacOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter MacOS 11.x nicht gefunden werden (<MacOS 11.x funktioniert).
Ursache: DoOnReceiveData wird unter MacOS 11.x nie errreicht (gleiches gilt für iOS 14.x)

Folgende Entitlements wurden gesetzt (Entitlement.TemplateOSX.xml oder via Projekt-Optionen):
Delphi-Quellcode:
  <key>com.apple.security.network.client</key>
  <true/>
  <key>com.apple.security.network.server</key>
  <true/>
Tipp 1: Formulardesigner: das Profile auf Enabled setzen und den Manager aus Disabled und dem Profile keinen Manager zuweisen.
Im Programm-Code den Manager auf Enabled setzen und direkt davor dem Profile den Manager zuweisen.
Sonst wird schon sehr viel initialisert (z.B. der Netzwerk-Adapter) bevor man erstmalig Zugriff im Code auf die Komponenten hat.

Delphi-Quellcode:
  CommandApp.Manager := CommandManager;
  CommandManager.Enabled := True;
Tipp 2: für iOS müssen eventuell alle Exception gefangen werden, weil ansonsten das nicht erfolgreiche binden eines Sockets zum Abbruch führen kann
Socket-Fehler # 48Adresse wird bereits verwendet:
$0000000100BCFDD0 _ZN7Idstack8TIdStack16RaiseSocketErrorEi + 316
$0000000100BD0B74 _ZN7Idstack8TIdStack20RaiseLastSocketErrorEv + 72
$0000000100BD0A18 _ZN7Idstack8TIdStack19CheckForSocketErrorEi + 44
$0000000100BCBD00 _ZN15Idstackvclposix16TIdStackVCLPosix4BindEiN6Sys tem13UnicodeStringEtN8Idglobal12TIdIPVersionE + 344
$0000000100BD99E8 _ZN14Idsockethandle15TIdSocketHandle4BindEv + 316
$0000000100BF84F8 _ZN17Idcustomtcpserver18TIdCustomTCPServer14StartL isteningEv + 188

Delphi-Quellcode:
  Application.OnException:=TgoExceptionReporter.ExceptionHandler;
  TMessageManager.DefaultManager.SubscribeToMessage(TgoExceptionReportMessage, HandleExceptionReport);
Tipp 3: IP-Adresse des eigenen Adapters nicht automatisch setzen lassen, sondern selbst per Indy auswählen:

Delphi-Quellcode:
uses IdStack, IdGlobal;

   function getIPv4Address():String;
   var
     AAddresses: TIdStackLocalAddressList;
     LAddr: TIdStackLocalAddress;
     I: Integer;
     prefNetwork,IP: String;
   begin
     AAddresses:=TIdStackLocalAddressList.Create();
     prefNetwork:='192.';//can be set also outside this functionality before the manager is enabled or the manager-attribute of the profile is set
     Result:='';
     try
      GStack.GetLocalAddressList(AAddresses);
      for I := 0 to AAddresses.Count-1 do
      begin
        LAddr:=AAddresses[I];
        IP:=LAddr.IPAddress;
        if ((IP<>'127.0.0.1') and ((Result='') or ((prefNetwork>'') and (pos(prefNetwork,IP)=1) and (pos(prefNetwork,Result)<>1)))) then
        begin
         case LAddr.IPVersion of
           Id_IPv4:
           begin
            mlog.info('Found IP-address*: '+IP);
            Result:=IP;
           end;
           Id_IPv6:
           begin
            mlog.info('Found IP-address: '+IP);
           end;
         end;
        end else
         mlog.info('Found IP-address: '+IP);
      end;
     finally
      AAddresses.Free;
     end;
   end;
Dies passiert an zwei Stellen:

System.Tether.Manager.pas
Delphi-Quellcode:
constructor TTetheringAdapter.Create;
var ip:String;
begin
  inherited;
  FRemoteManagers := TTetheringManagerInfoList.Create;
  ip:=getIPv4Address();
  if (ip>'') then
    FAdapterConnectionString := ip
  else
    FAdapterConnectionString := TTetheringManagerCommunicationThread.EMPTYTOKEN;
end;
System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkManagerCommunicationThread.Execute;
...
        if not LListening then
          raise ETetheringException.Create(SManagerNetworkCreation);

        var ip:String;
        ip:=TStringUtils.getIPv4Address();
        if (ip>'') then
          LRemoteConnectionString := ip + TetheringConnectionSeparator + FTarget
        else
          LRemoteConnectionString := EMPTYTOKEN + TetheringConnectionSeparator + FTarget;
Zur Sicherheit habe ich es noch hier eingebaut, da wird es aber höchstwahrscheinlich nicht gebraucht:

System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkAdapterCommon.DoDiscoverManagers(Timeout: Cardinal;
  const ATargetList: TTetheringTargetHosts; const AProfileGroups, AProfileTexts: TArray<string>);
...
    LCommand := TTetheringManagerCommand.Create(TTetheringNetworkManagerCommunicationThread.TetheringDiscoverManagers,
      FAdapterConnectionString, Manager.Version, [FCommunicationThread.FTarget, LGroups, LTexts]);
  end else begin
    if (pos(TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,FAdapterConnectionString)>0) then
    begin
      var ip:String;
      ip:=TStringUtils.getIPv4Address();
      if (ip>'') then
        FAdapterConnectionString:=StringReplace(FAdapterConnectionString,TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,ip,[]);
    end;

Geändert von philipp.hofmann ( 7. Jun 2021 um 16:50 Uhr)
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 7. Jun 2021, 17:06
Noch ein Tipp zum Beantragen des Multicast-Entitlement, da dies bei mir in Summe 10 Tage und 3 Rückfragen seitens Apple benötigt hat:
- sich die Mühe geben, den Applikationsflow zu beschreiben
- angeben, dass die MacOS/iOS-App sich mit einer Android/Windows/iOS/MacOS-App verbinden kann und man die Embacadero Delphi Tethering Implementierung nutzt; sonst empfiehlt Apple Bonjour zu nutzen;
- als technisches Verfahren IP based Broadcast UDP (Ports 2020-2040) angeben
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 7. Jun 2021, 19:44
Falls jemand für den Issue voten möchte:

RSP-34147 Tethering: MacOS 11.x/iOS 14.x devices are not found with TTetheringManager.DiscoverManagers
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 9. Jun 2021, 17:08
Ich habe ein Bugfix für das Thema iOS und Tethering bei aktivierten Mobilen Daten gebaut und eingestellt. Damit ergibt sich ein neuer Status für dieses Thema:
- weiterhin findet man iOS 14.x und MacOS 11.x Devices mit der Discover-Funktion nicht
Alles andere funktioniert nun.
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 9. Jun 2021, 17:12
Status: Tethering

- die Windows-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen

- die Android-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen
- Permission Internet muss auf "true" gesetzt sein

- die iOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter iOS 14.x nicht gefunden werden (<iOS 14 funktioniert).
Ursache: DoOnReceiveData wird unter iOS 14.x nie errreicht (gleiches gilt für MacOS 11.x)
- Es muss via https://developer.apple.com/contact/...king-multicast die Berechtigung erfragt werden, das Entitlement Multicast zu setzen,
damit iOS 14.x funktioniert; im Projekt ist das Entitlement aber nicht zu setzen, dies passiert über das Provision Profile automatisch (außer man erzeugt
die Entitlement-Datei manuell);

Delphi-Quellcode:
  <key>com.apple.developer.networking.multicast</key>
  <true/>
- die MacOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter MacOS 11.x nicht gefunden werden (<MacOS 11.x funktioniert).
Ursache: DoOnReceiveData wird unter MacOS 11.x nie errreicht (gleiches gilt für iOS 14.x)

Folgende Entitlements wurden gesetzt (Entitlement.TemplateOSX.xml oder via Projekt-Optionen):

Delphi-Quellcode:
  <key>com.apple.security.network.client</key>
  <true/>
  <key>com.apple.security.network.server</key>
  <true/>
Das Ticket für das iOS 14.x und MacOS 11.x-Problem ist unter https://quality.embarcadero.com/browse/RSP-34147 eingestellt.

Tipp 1: Formulardesigner: das Profile auf Enabled setzen und den Manager aus Disabled und dem Profile keinen Manager zuweisen.
Im Programm-Code den Manager auf Enabled setzen und direkt davor dem Profile den Manager zuweisen.
Sonst wird schon sehr viel initialisert (z.B. der Netzwerk-Adapter) bevor man erstmalig Zugriff im Code auf die Komponenten hat.

Delphi-Quellcode:
  CommandApp.Manager := CommandManager;
  CommandManager.Enabled := True;
Tipp 2: für iOS müssen eventuell alle Exception gefangen werden, weil ansonsten das nicht erfolgreiche binden eines Sockets zum Abbruch führen kann
Socket-Fehler # 48Adresse wird bereits verwendet:
$0000000100BCFDD0 _ZN7Idstack8TIdStack16RaiseSocketErrorEi + 316
$0000000100BD0B74 _ZN7Idstack8TIdStack20RaiseLastSocketErrorEv + 72
$0000000100BD0A18 _ZN7Idstack8TIdStack19CheckForSocketErrorEi + 44
$0000000100BCBD00 _ZN15Idstackvclposix16TIdStackVCLPosix4BindEiN6Sys tem13UnicodeStringEtN8Idglobal12TIdIPVersionE + 344
$0000000100BD99E8 _ZN14Idsockethandle15TIdSocketHandle4BindEv + 316
$0000000100BF84F8 _ZN17Idcustomtcpserver18TIdCustomTCPServer14StartL isteningEv + 188

Delphi-Quellcode:
  Application.OnException:=TgoExceptionReporter.ExceptionHandler;
  TMessageManager.DefaultManager.SubscribeToMessage(TgoExceptionReportMessage, HandleExceptionReport);
Tipp 3: IP-Adresse des eigenen Adapters nicht automatisch setzen lassen, sondern selbst per Indy auswählen:

Delphi-Quellcode:
uses IdStack, IdGlobal, System.Classes;
class var prefNetworkList:TStringList;

class function getIPv4Address():String;

function checkForPrefNetwork(value:String):boolean;
var i:integer;
begin
  Result:=false;
  for i:=0 to prefNetworkList.Count-1 do
  begin
    if (pos(prefNetworkList[i],value)=1) then
    begin
      Result:=true;
      exit;
    end;
  end;
end;

var
  AAddresses: TIdStackLocalAddressList;
  LAddr: TIdStackLocalAddress;
  I: Integer;
  IP: String;
begin
  AAddresses:=TIdStackLocalAddressList.Create();
  Result:='';
  if (prefNetworkList=nil) then
  begin
    prefNetworkList:=TStringList.Create();
    prefNetworkList.Add('192.168.');
  end;
  try
    GStack.GetLocalAddressList(AAddresses);
    for I := 0 to AAddresses.Count-1 do
    begin
      LAddr:=AAddresses[I];
      IP:=LAddr.IPAddress;
      if ((IP<>'127.0.0.1') and ((Result='') or ((prefNetworkList.Count>0) and (checkForPrefNetwork(IP)) and (not checkForPrefNetwork(result))))) then
      begin
        case LAddr.IPVersion of
          Id_IPv4:
          begin
            log.d('Found IP-address*: '+IP);
            Result:=IP;
          end;
          Id_IPv6:
          begin
            log.d('Found IP-address: '+IP);
          end;
        end;
      end else
        log.d('Found IP-address: '+IP);
    end;
  finally
    AAddresses.Free;
  end;
end;
Dies passiert an zwei Stellen:

System.Tether.Manager.pas
Delphi-Quellcode:
constructor TTetheringAdapter.Create;
var ip:String;
begin
  inherited;
  FRemoteManagers := TTetheringManagerInfoList.Create;
  ip:=getIPv4Address();
  if (ip>'') then
    FAdapterConnectionString := ip
  else
    FAdapterConnectionString := TTetheringManagerCommunicationThread.EMPTYTOKEN;
end;
System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkManagerCommunicationThread.Execute;
...
        if not LListening then
          raise ETetheringException.Create(SManagerNetworkCreation);

        var ip:String;
        ip:=TStringUtils.getIPv4Address();
        if (ip>'') then
          LRemoteConnectionString := ip + TetheringConnectionSeparator + FTarget
        else
          LRemoteConnectionString := EMPTYTOKEN + TetheringConnectionSeparator + FTarget;
Zur Sicherheit habe ich es noch hier eingebaut, da wird es aber höchstwahrscheinlich nicht gebraucht:

System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkAdapterCommon.DoDiscoverManagers(Timeout: Cardinal;
  const ATargetList: TTetheringTargetHosts; const AProfileGroups, AProfileTexts: TArray<string>);
...
    LCommand := TTetheringManagerCommand.Create(TTetheringNetworkManagerCommunicationThread.TetheringDiscoverManagers,
      FAdapterConnectionString, Manager.Version, [FCommunicationThread.FTarget, LGroups, LTexts]);
  end else begin
    if (pos(TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,FAdapterConnectionString)>0) then
    begin
      var ip:String;
      ip:=TStringUtils.getIPv4Address();
      if (ip>'') then
        FAdapterConnectionString:=StringReplace(FAdapterConnectionString,TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,ip,[]);
    end;
Tipp 4: Tethering mit iOS bei aktivierten Mobilen Daten:

Damit bei aktivierten Mobilen Daten unter iOS das Tethering funktioniert, muss die Funktion BroadcastData in System.Tether.Comm gefixt werden.
Dies ist auch als Issue bei EMBT eingestellt (https://quality.embarcadero.com/browse/RSP-31191).
Delphi-Quellcode:

procedure TTetheringNetworkServerCommUDP.BroadcastData(const AData: TBytes; const AHost: string;
  InitialPort, FinalPort: Integer);
var
  I, J: Integer;
  LHost: string;
  LData: TBytes;
  allWithException:boolean;
  toRaise:Exception;
begin
  if TTetheringAdapter.IsLoggingItem(TTetheringAdapter.TTetheringLogItem.Comm) then
      TLogAdapter.Log('** UDP ** BroadcastData to "' + AHost + '": "' + TEncoding.UTF8.GetString(AData) + '"');
    if AHost = 'then
    begin
      if FIPVersion = TCommIPVersion.IP_IPv4 then
        LHost := '255.255.255.255'
      else
        LHost := '0:0:0:0:0:0:255.255.255.255';
 
      allWithException:=true;
      toRaise:=nil;
      for J := 0 to FUDPServer.Bindings.Count - 1 do
      begin
        try
          LData := TEncoding.UTF8.GetBytes(StringReplace(
            TEncoding.UTF8.GetString(AData),
            '|' + TetheringMULTIHOMED + '$',
            '|' + FUDPServer.Bindings.Sockets[J].IP + '$',
            []));
          for I := InitialPort to FinalPort do
            FUDPServer.Bindings.Sockets[J].Broadcast(LData, I, LHost);
          allWithException:=false;
        except on E: Exception do
          begin
            if (toRaise=nil) then
              toRaise:=e;
          end;
        end;
      end;
      if (allWithException and (toRaise<>nil)) then
        raise(toRaise);
    end else
      for I := InitialPort to FinalPort do
        FUDPServer.SendBuffer(AHost, I, AData);
end;

Geändert von philipp.hofmann ( 9. Jun 2021 um 19:48 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.119 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 10. Jun 2021, 09:48
Dankesehr für die Updates.
Ich komme im Moment leider nicht zum Testen.
Für die ganze Bürokratie muss man wohl noch zwei Leute einstellen.
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
523 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Status: Tethering - noch Probleme mit MacOS und iOS

  Alt 11. Jun 2021, 13:52
Und wieder ein ganz kleines Code-Update, da die IP-Adressen-Ermittlung nur funktionierte, wenn man eine Indy-Net-Komponente schon irgendwo im Projekt eingebunden hatte:

Status: Tethering

- die Windows-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen

- die Android-App kann sowohl andere Manager und Profiles im Netzwerk suchen und finden (discover) als auch gefunden werden und dann zwischen beiden Apps Daten austauschen
- Permission Internet muss auf "true" gesetzt sein

- die iOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter iOS 14.x nicht gefunden werden (<iOS 14 funktioniert).
Ursache: DoOnReceiveData wird unter iOS 14.x nie errreicht (gleiches gilt für MacOS 11.x)
- Es muss via https://developer.apple.com/contact/...king-multicast die Berechtigung erfragt werden, das Entitlement Multicast zu setzen,
damit iOS 14.x funktioniert; im Projekt ist das Entitlement aber nicht zu setzen, dies passiert über das Provision Profile automatisch (außer man erzeugt
die Entitlement-Datei manuell);

Delphi-Quellcode:
  <key>com.apple.developer.networking.multicast</key>
  <true/>
- die MacOS-App kann andere Manager und Profiles im Netzwerk suchen und finden (discover), diesem auch Daten schicken und Antworten empfangen, kann aber unter MacOS 11.x nicht gefunden werden (<MacOS 11.x funktioniert).
Ursache: DoOnReceiveData wird unter MacOS 11.x nie errreicht (gleiches gilt für iOS 14.x)

Folgende Entitlements wurden gesetzt (Entitlement.TemplateOSX.xml oder via Projekt-Optionen):

Delphi-Quellcode:
  <key>com.apple.security.network.client</key>
  <true/>
  <key>com.apple.security.network.server</key>
  <true/>
Das Ticket für das iOS 14.x und MacOS 11.x-Problem ist unter https://quality.embarcadero.com/browse/RSP-34147 eingestellt.

Tipp 1: Formulardesigner: das Profile auf Enabled setzen und den Manager aus Disabled und dem Profile keinen Manager zuweisen.
Im Programm-Code den Manager auf Enabled setzen und direkt davor dem Profile den Manager zuweisen.
Sonst wird schon sehr viel initialisert (z.B. der Netzwerk-Adapter) bevor man erstmalig Zugriff im Code auf die Komponenten hat.

Delphi-Quellcode:
  CommandApp.Manager := CommandManager;
  CommandManager.Enabled := True;
Tipp 2: für iOS müssen eventuell alle Exception gefangen werden, weil ansonsten das nicht erfolgreiche binden eines Sockets zum Abbruch führen kann
Socket-Fehler # 48Adresse wird bereits verwendet:
$0000000100BCFDD0 _ZN7Idstack8TIdStack16RaiseSocketErrorEi + 316
$0000000100BD0B74 _ZN7Idstack8TIdStack20RaiseLastSocketErrorEv + 72
$0000000100BD0A18 _ZN7Idstack8TIdStack19CheckForSocketErrorEi + 44
$0000000100BCBD00 _ZN15Idstackvclposix16TIdStackVCLPosix4BindEiN6Sys tem13UnicodeStringEtN8Idglobal12TIdIPVersionE + 344
$0000000100BD99E8 _ZN14Idsockethandle15TIdSocketHandle4BindEv + 316
$0000000100BF84F8 _ZN17Idcustomtcpserver18TIdCustomTCPServer14StartL isteningEv + 188

Delphi-Quellcode:
  Application.OnException:=TgoExceptionReporter.ExceptionHandler;
  TMessageManager.DefaultManager.SubscribeToMessage(TgoExceptionReportMessage, HandleExceptionReport);
Tipp 3: IP-Adresse des eigenen Adapters nicht automatisch setzen lassen, sondern selbst per Indy auswählen:

Delphi-Quellcode:

uses IdStack, IdGlobal, IdSSLOpenSSL, System.Classes;
class var prefNetworkList:TStringList;

class function getIPv4Address():String;

function checkForPrefNetwork(value:String):boolean;
var i:integer;
begin
  Result:=false;
  for i:=0 to prefNetworkList.Count-1 do
  begin
    if (pos(prefNetworkList[i],value)=1) then
    begin
      Result:=true;
      exit;
    end;
  end;
end;

var
  AAddresses: TIdStackLocalAddressList;
  LAddr: TIdStackLocalAddress;
  I: Integer;
  IP: String;
begin
  AAddresses:=TIdStackLocalAddressList.Create();
  Result:='';
  if (prefNetworkList=nil) then
  begin
    prefNetworkList:=TStringList.Create();
    prefNetworkList.Add('192.168.');
  end;
  try
    if (GStack=nil) then
    begin
      var IdSSLIOHandlerSocketOpenSSL:TIdSSLIOHandlerSocketOpenSSL;
      IdSSLIOHandlerSocketOpenSSL:=TIdSSLIOHandlerSocketOpenSSL.create();
    end;
    GStack.GetLocalAddressList(AAddresses);
    for I := 0 to AAddresses.Count-1 do
    begin
      LAddr:=AAddresses[I];
      IP:=LAddr.IPAddress;
      if ((IP<>'127.0.0.1') and ((Result='') or ((prefNetworkList.Count>0) and (checkForPrefNetwork(IP)) and (not checkForPrefNetwork(result))))) then
      begin
        case LAddr.IPVersion of
          Id_IPv4:
          begin
            log.d('Found IP-address*: '+IP);
            Result:=IP;
          end;
          Id_IPv6:
          begin
            log.d('Found IP-address: '+IP);
          end;
        end;
      end else
        log.d('Found IP-address: '+IP);
    end;
  finally
    AAddresses.Free;
  end;
end;
Dies passiert an zwei Stellen:

System.Tether.Manager.pas
Delphi-Quellcode:
constructor TTetheringAdapter.Create;
var ip:String;
begin
  inherited;
  FRemoteManagers := TTetheringManagerInfoList.Create;
  ip:=getIPv4Address();
  if (ip>'') then
    FAdapterConnectionString := ip
  else
    FAdapterConnectionString := TTetheringManagerCommunicationThread.EMPTYTOKEN;
end;
System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkManagerCommunicationThread.Execute;
...
        if not LListening then
          raise ETetheringException.Create(SManagerNetworkCreation);

        var ip:String;
        ip:=TStringUtils.getIPv4Address();
        if (ip>'') then
          LRemoteConnectionString := ip + TetheringConnectionSeparator + FTarget
        else
          LRemoteConnectionString := EMPTYTOKEN + TetheringConnectionSeparator + FTarget;
Zur Sicherheit habe ich es noch hier eingebaut, da wird es aber höchstwahrscheinlich nicht gebraucht:

System.Tether.NetworkAdapter.pas
Delphi-Quellcode:
procedure TTetheringNetworkAdapterCommon.DoDiscoverManagers(Timeout: Cardinal;
  const ATargetList: TTetheringTargetHosts; const AProfileGroups, AProfileTexts: TArray<string>);
...
    LCommand := TTetheringManagerCommand.Create(TTetheringNetworkManagerCommunicationThread.TetheringDiscoverManagers,
      FAdapterConnectionString, Manager.Version, [FCommunicationThread.FTarget, LGroups, LTexts]);
  end else begin
    if (pos(TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,FAdapterConnectionString)>0) then
    begin
      var ip:String;
      ip:=TStringUtils.getIPv4Address();
      if (ip>'') then
        FAdapterConnectionString:=StringReplace(FAdapterConnectionString,TTetheringNetworkManagerCommunicationThread.EMPTYTOKEN,ip,[]);
    end;
Tipp 4: Tethering mit iOS bei aktivierten Mobilen Daten:

Damit bei aktivierten Mobilen Daten unter iOS das Tethering funktioniert, muss die Funktion BroadcastData in System.Tether.Comm gefixt werden.
Dies ist auch als Issue bei EMBT eingestellt (https://quality.embarcadero.com/browse/RSP-31191).
Delphi-Quellcode:

procedure TTetheringNetworkServerCommUDP.BroadcastData(const AData: TBytes; const AHost: string;
  InitialPort, FinalPort: Integer);
var
  I, J: Integer;
  LHost: string;
  LData: TBytes;
  allWithException:boolean;
  toRaise:Exception;
begin
  if TTetheringAdapter.IsLoggingItem(TTetheringAdapter.TTetheringLogItem.Comm) then
      TLogAdapter.Log('** UDP ** BroadcastData to "' + AHost + '": "' + TEncoding.UTF8.GetString(AData) + '"');
    if AHost = 'then
    begin
      if FIPVersion = TCommIPVersion.IP_IPv4 then
        LHost := '255.255.255.255'
      else
        LHost := '0:0:0:0:0:0:255.255.255.255';
 
      allWithException:=true;
      toRaise:=nil;
      for J := 0 to FUDPServer.Bindings.Count - 1 do
      begin
        try
          LData := TEncoding.UTF8.GetBytes(StringReplace(
            TEncoding.UTF8.GetString(AData),
            '|' + TetheringMULTIHOMED + '$',
            '|' + FUDPServer.Bindings.Sockets[J].IP + '$',
            []));
          for I := InitialPort to FinalPort do
            FUDPServer.Bindings.Sockets[J].Broadcast(LData, I, LHost);
          allWithException:=false;
        except on E: Exception do
          begin
            if (toRaise=nil) then
              toRaise:=e;
          end;
        end;
      end;
      if (allWithException and (toRaise<>nil)) then
        raise(toRaise);
    end else
      for I := InitialPort to FinalPort do
        FUDPServer.SendBuffer(AHost, I, AData);
end;
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 04:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf