These are chat archives for IndySockets/Indy

12th
Jul 2017
Remy Lebeau
@rlebeau
Jul 12 2017 00:00
@DelphiWorlds IPV6_ADD_MEMBERSHIP specifies the group to join and the network interface to join with
DelphiWorlds
@DelphiWorlds
Jul 12 2017 00:00
it's when it calls setsockopt() with IPV6_ADD_MEMBERSHIP that it fails
yes, I have worked that out
the interface index being used is 0, which coincides with other examples I've seen in my searching
Remy Lebeau
@rlebeau
Jul 12 2017 00:03
@DelphiWorlds like I said, that just tells the OS to use the default multicast interface, whatever it happens to be, instead of having to specify a specific interface. You could always try stepping into the code with the debugger and play around with the indexes. But I think the first thing you should try is setting the TIdSocketHandle.IP property to the device's local IP when setting up the Bindings collection so TIdIPMCastClient has something specific to bind to locally before joining the group.
DelphiWorlds
@DelphiWorlds
Jul 12 2017 00:09
I'm away from my Mac, so I'll check tonight (in about 8 hours from now).. thanks
DelphiWorlds
@DelphiWorlds
Jul 12 2017 09:34
I've modified the code to set the only Binding to the first IPv6 address:
procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  LIP: string;
begin
  FLocalAddresses := TIdStackLocalAddressList.Create;
  GStack.GetLocalAddressList(FLocalAddresses);

  for I := 0 to FLocalAddresses.Count - 1 do
  begin
    if FLocalAddresses[I].IPVersion = TIdIPVersion.Id_IPv6 then
    begin
      LIP := FLocalAddresses[I].IPAddress;
      Break;
    end;
  end;

  if LIP.IsEmpty then
    Exit; // <======

  BroadcastServerIPv6.Port := 6000;
  BroadcastServerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
  BroadcastServerIPv6.Active := True;

  BroadcastListenerIPv6.DefaultPort := 6000;
  for I := 0 to BroadcastListenerIPv6.Bindings.Count - 1 do
  begin
    BroadcastListenerIPv6.Bindings.Items[I].Port := BroadcastListenerIPv6.DefaultPort;
    BroadcastListenerIPv6.Bindings.Items[I].IP := LIP;
  end;
  BroadcastListenerIPv6.MulticastGroup := 'FF02:0:0:0:0:0:0:1';
  BroadcastListenerIPv6.Active := True;
end;
when I say "only" I mean that BroadcastListenerIPv6.Bindings.Count = 1
I've been through iterations of this before, one where I've created Bindings for each IPv6 address that the device has.. always results the same: error 49
I'm about to resort to using:
https://github.com/robbiehanson/CocoaAsyncSocket
at least for iOS
DelphiWorlds
@DelphiWorlds
Jul 12 2017 09:40
I'd rather not though.. having single source has advantages, however when I've fought with this as much as I have, it might be time to move on
Remy Lebeau
@rlebeau
Jul 12 2017 18:11
@DelphiWorlds Are you setting either BroadcastListenerrIPv6.IPVersion := Id_IPv6 or BroadcastListenerIPv6.Bindings.Items[I].IPVersion := Id_IPv6 to match the IP you are assigning? Why do you have a Binding created at design-time if you are just going to overwrite it at runtime? You may as well just use Bindings.Add() at runtime instead.
DelphiWorlds
@DelphiWorlds
Jul 12 2017 23:41
Revised code:
const
  cMulticastGroupIPv6 = 'FF02:0:0:0:0:0:0:1';

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  LBinding: TIdSocketHandle;
begin
  FLocalAddresses := TIdStackLocalAddressList.Create;
  GStack.GetLocalAddressList(FLocalAddresses);

  BroadcastServerIPv6.Port := 6000;
  BroadcastServerIPv6.MulticastGroup := cMulticastGroupIPv6;
  BroadcastServerIPv6.Active := True;

  BroadcastListenerIPv6.DefaultPort := 6000;
  BroadcastListenerIPv6.IPVersion := TIdIPVersion.Id_IPv6;
  BroadcastListenerIPv6.MulticastGroup := cMulticastGroupIPv6;
  BroadcastListenerIPv6.Bindings.Clear;
  for I := 0 to FLocalAddresses.Count - 1 do
  begin
    if FLocalAddresses[I].IPVersion = TIdIPVersion.Id_IPv6 then
    begin
      LBinding := BroadcastListenerIPv6.Bindings.Add;
      LBinding.IP := FLocalAddresses[I].IPAddress;
      LBinding.IPVersion := TIdIPVersion.Id_IPv6;
      LBinding.Port := BroadcastListenerIPv6.DefaultPort;
    end;
  end;
  BroadcastListenerIPv6.Active := True;
end;
Just so that it's clear what is and is not being set
Remy Lebeau
@rlebeau
Jul 12 2017 23:51
@DelphiWorlds and? what happens with it? If it is still not working, I don't know what else to tell you. I've only worked with multicast once before, but it was on Windows using IPv4, and I didn't use Indy for it, I used straight Winsock calls. But TIdIPMCastClient basically makes the same Winsock calls I did. The only difference being that I also enabled the SO_REUSEADDR option (the ReuseSocket property in Indy), but I don't think that is a factor in your situation. Try talking to Apple about your error.