Example #1
0
        /// <summary>
        /// 現在のチャンネルとPeerCastの状態からHostパケットを作ります
        /// </summary>
        /// <returns>作ったPCP_HOSTパケット</returns>
        public virtual Atom CreateHostPacket()
        {
            var host = new AtomCollection();

            host.SetHostChannelID(Channel.ChannelID);
            host.SetHostSessionID(PeerCast.SessionID);
            var globalendpoint =
                PeerCast.GetGlobalEndPoint(
                    RemoteEndPoint.AddressFamily,
                    OutputStreamType.Relay);

            if (globalendpoint != null)
            {
                host.AddHostIP(globalendpoint.Address);
                host.AddHostPort(globalendpoint.Port);
            }
            var localendpoint =
                PeerCast.GetLocalEndPoint(
                    RemoteEndPoint.AddressFamily,
                    OutputStreamType.Relay);

            if (localendpoint != null)
            {
                host.AddHostIP(localendpoint.Address);
                host.AddHostPort(localendpoint.Port);
            }
            host.SetHostNumListeners(Channel.LocalDirects);
            host.SetHostNumRelays(Channel.LocalRelays);
            host.SetHostUptime(Channel.Uptime);
            if (Channel.Contents.Count > 0)
            {
                host.SetHostOldPos((uint)(Channel.Contents.Oldest.Position & 0xFFFFFFFFU));
                host.SetHostNewPos((uint)(Channel.Contents.Newest.Position & 0xFFFFFFFFU));
            }
            host.SetHostVersion(PCP_VERSION);
            host.SetHostVersionVP(PCP_VERSION_VP);
            host.SetHostFlags1(
                (PeerCast.AccessController.IsChannelRelayable(Channel) ? PCPHostFlags1.Relay : 0) |
                (PeerCast.AccessController.IsChannelPlayable(Channel) ? PCPHostFlags1.Direct : 0) |
                ((!PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value) ? PCPHostFlags1.Firewalled : 0) |
                (RecvRate > 0 ? PCPHostFlags1.Receiving : 0));
            host.SetHostUphostIP(RemoteEndPoint.Address);
            host.SetHostUphostPort(RemoteEndPoint.Port);
            return(new Atom(Atom.PCP_HOST, host));
        }
        /// <summary>
        /// 現在のチャンネルとPeerCastの状態からHostパケットを作ります
        /// </summary>
        /// <returns>作ったPCP_HOSTパケット</returns>
        private Atom CreatePCPHOST()
        {
            var host = new AtomCollection();

            host.SetHostChannelID(Channel.ChannelID);
            host.SetHostSessionID(PeerCast.SessionID);
            var globalendpoint =
                PeerCast.GetGlobalEndPoint(
                    connection.RemoteEndPoint.AddressFamily,
                    OutputStreamType.Relay);

            if (globalendpoint != null)
            {
                host.AddHostIP(globalendpoint.Address);
                host.AddHostPort(globalendpoint.Port);
            }
            var localendpoint =
                PeerCast.GetLocalEndPoint(
                    connection.RemoteEndPoint.AddressFamily,
                    OutputStreamType.Relay);

            if (localendpoint != null)
            {
                host.AddHostIP(localendpoint.Address);
                host.AddHostPort(localendpoint.Port);
            }
            host.SetHostNumListeners(Channel.LocalDirects);
            host.SetHostNumRelays(Channel.LocalRelays);
            host.SetHostUptime(Channel.Uptime);
            if (Channel.Contents.Count > 0)
            {
                host.SetHostOldPos((uint)(Channel.Contents.Oldest.Position & 0xFFFFFFFFU));
                host.SetHostNewPos((uint)(Channel.Contents.Newest.Position & 0xFFFFFFFFU));
            }
            PCPVersion.SetHostVersion(host);
            host.SetHostFlags1(
                (PeerCast.AccessController.IsChannelRelayable(Channel) ? PCPHostFlags1.Relay : 0) |
                (PeerCast.AccessController.IsChannelPlayable(Channel) ? PCPHostFlags1.Direct : 0) |
                ((PeerCast.GetPortStatus(connection.RemoteEndPoint.AddressFamily) != PortStatus.Open) ? PCPHostFlags1.Firewalled : 0) |
                (RecvRate > 0 ? PCPHostFlags1.Receiving : 0));
            host.SetHostUphostIP(connection.RemoteEndPoint.Address);
            host.SetHostUphostPort(connection.RemoteEndPoint.Port);
            return(new Atom(Atom.PCP_HOST, host));
        }
        private void PostHostInfo(AtomCollection parent, Channel channel, bool playing)
        {
            var hostinfo = new AtomCollection();

            hostinfo.SetHostChannelID(channel.ChannelID);
            hostinfo.SetHostSessionID(PeerCast.SessionID);
            var globalendpoint = PeerCast.GetGlobalEndPoint(AddressFamily.InterNetwork, OutputStreamType.Relay);

            if (globalendpoint != null)
            {
                hostinfo.AddHostIP(globalendpoint.Address);
                hostinfo.AddHostPort(globalendpoint.Port);
            }
            var localendpoint = PeerCast.GetLocalEndPoint(AddressFamily.InterNetwork, OutputStreamType.Relay);

            if (localendpoint != null)
            {
                hostinfo.AddHostIP(localendpoint.Address);
                hostinfo.AddHostPort(localendpoint.Port);
            }
            hostinfo.SetHostNumListeners(channel.TotalDirects);
            hostinfo.SetHostNumRelays(channel.TotalRelays);
            hostinfo.SetHostUptime(channel.Uptime);
            if (channel.Contents.Count > 0)
            {
                hostinfo.SetHostOldPos((uint)(channel.Contents.Oldest.Position & 0xFFFFFFFFU));
                hostinfo.SetHostNewPos((uint)(channel.Contents.Newest.Position & 0xFFFFFFFFU));
            }
            PCPVersion.SetHostVersion(hostinfo);
            var relayable  = PeerCast.AccessController.IsChannelRelayable(channel);
            var playable   = PeerCast.AccessController.IsChannelPlayable(channel) && PeerCast.FindListener(remoteEndPoint.Address, OutputStreamType.Play) != null;
            var firewalled = !PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value || PeerCast.FindListener(remoteEndPoint.Address, OutputStreamType.Relay) == null;
            var receiving  = playing && channel.Status == SourceStreamStatus.Receiving;

            hostinfo.SetHostFlags1(
                (relayable  ? PCPHostFlags1.Relay      : 0) |
                (playable   ? PCPHostFlags1.Direct     : 0) |
                (firewalled ? PCPHostFlags1.Firewalled : 0) |
                PCPHostFlags1.Tracker |
                (receiving ? PCPHostFlags1.Receiving : PCPHostFlags1.None));
            parent.SetHost(hostinfo);
        }
        private void PostHostInfo(AtomCollection parent, Channel channel, bool playing)
        {
            var host     = channel.SelfNode;
            var hostinfo = new AtomCollection();

            hostinfo.SetHostChannelID(channel.ChannelID);
            hostinfo.SetHostSessionID(PeerCast.SessionID);
            var globalendpoint = host.GlobalEndPoint;

            if (globalendpoint != null)
            {
                hostinfo.AddHostIP(globalendpoint.Address);
                hostinfo.AddHostPort(globalendpoint.Port);
            }
            var localendpoint = host.LocalEndPoint;

            if (localendpoint != null)
            {
                hostinfo.AddHostIP(localendpoint.Address);
                hostinfo.AddHostPort(localendpoint.Port);
            }
            hostinfo.SetHostNumListeners(channel.TotalDirects);
            hostinfo.SetHostNumRelays(channel.TotalRelays);
            hostinfo.SetHostUptime(channel.Uptime);
            if (channel.Contents.Count > 0)
            {
                hostinfo.SetHostOldPos((uint)(channel.Contents.Oldest.Position & 0xFFFFFFFFU));
                hostinfo.SetHostNewPos((uint)(channel.Contents.Newest.Position & 0xFFFFFFFFU));
            }
            hostinfo.SetHostVersion(PCP_VERSION);
            hostinfo.SetHostVersionVP(PCP_VERSION_VP);
            hostinfo.SetHostFlags1(
                (PeerCast.AccessController.IsChannelRelayable(channel) ? PCPHostFlags1.Relay : 0) |
                (PeerCast.AccessController.IsChannelPlayable(channel) ? PCPHostFlags1.Direct : 0) |
                ((!PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value) ? PCPHostFlags1.Firewalled : 0) |
                PCPHostFlags1.Tracker |
                (playing ? PCPHostFlags1.Receiving : PCPHostFlags1.None));
            parent.SetHost(hostinfo);
        }
 /// <summary>
 /// 現在のチャンネルとPeerCastの状態からHostパケットを作ります
 /// </summary>
 /// <returns>作ったPCP_HOSTパケット</returns>
 private Atom CreateHostPacket()
 {
     var host = new AtomCollection();
       host.SetHostChannelID(Channel.ChannelID);
       host.SetHostSessionID(PeerCast.SessionID);
       var globalendpoint =
     PeerCast.GetGlobalEndPoint(
       RemoteEndPoint.AddressFamily,
       OutputStreamType.Relay);
       if (globalendpoint!=null) {
     host.AddHostIP(globalendpoint.Address);
     host.AddHostPort(globalendpoint.Port);
       }
       var localendpoint =
     PeerCast.GetLocalEndPoint(
       RemoteEndPoint.AddressFamily,
       OutputStreamType.Relay);
       if (localendpoint!=null) {
     host.AddHostIP(localendpoint.Address);
     host.AddHostPort(localendpoint.Port);
       }
       host.SetHostNumListeners(Channel.LocalDirects);
       host.SetHostNumRelays(Channel.LocalRelays);
       host.SetHostUptime(Channel.Uptime);
       if (Channel.Contents.Count > 0) {
     host.SetHostOldPos((uint)(Channel.Contents.Oldest.Position & 0xFFFFFFFFU));
     host.SetHostNewPos((uint)(Channel.Contents.Newest.Position & 0xFFFFFFFFU));
       }
       PCPVersion.SetHostVersion(host);
       host.SetHostFlags1(
     (PeerCast.AccessController.IsChannelRelayable(Channel) ? PCPHostFlags1.Relay : 0) |
     (PeerCast.AccessController.IsChannelPlayable(Channel) ? PCPHostFlags1.Direct : 0) |
     ((!PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value) ? PCPHostFlags1.Firewalled : 0) |
     (RecvRate>0 ? PCPHostFlags1.Receiving : 0));
       host.SetHostUphostIP(RemoteEndPoint.Address);
       host.SetHostUphostPort(RemoteEndPoint.Port);
       return new Atom(Atom.PCP_HOST, host);
 }
Example #6
0
        protected override Task OnStopped(CancellationToken cancel_token)
        {
            switch (StoppedReason)
            {
            case StopReason.None:
                break;

            case StopReason.Any:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
                break;

            case StopReason.SendTimeoutError:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_SKIP));
                break;

            case StopReason.BadAgentError:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_BADAGENT));
                break;

            case StopReason.ConnectionError:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_READ));
                break;

            case StopReason.NotIdentifiedError:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_NOTIDENTIFIED));
                break;

            case StopReason.UnavailableError:
            {
                //次に接続するホストを送ってQUIT
                foreach (var node in SelectSourceHosts((IPEndPoint)RemoteEndPoint))
                {
                    if (Downhost != null && Downhost.SessionID == node.SessionID)
                    {
                        continue;
                    }
                    var  host_atom = new AtomCollection(node.Extra);
                    Atom ip        = host_atom.FindByName(Atom.PCP_HOST_IP);
                    while (ip != null)
                    {
                        host_atom.Remove(ip);
                        ip = host_atom.FindByName(Atom.PCP_HOST_IP);
                    }
                    Atom port = host_atom.FindByName(Atom.PCP_HOST_PORT);
                    while (port != null)
                    {
                        host_atom.Remove(port);
                        port = host_atom.FindByName(Atom.PCP_HOST_PORT);
                    }
                    host_atom.SetHostSessionID(node.SessionID);
                    var globalendpoint = node.GlobalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
                    host_atom.AddHostIP(globalendpoint.Address);
                    host_atom.AddHostPort(globalendpoint.Port);
                    var localendpoint = node.LocalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
                    host_atom.AddHostIP(localendpoint.Address);
                    host_atom.AddHostPort(localendpoint.Port);
                    host_atom.SetHostNumRelays(node.RelayCount);
                    host_atom.SetHostNumListeners(node.DirectCount);
                    host_atom.SetHostChannelID(Channel.ChannelID);
                    host_atom.SetHostFlags1(
                        (node.IsFirewalled ? PCPHostFlags1.Firewalled : PCPHostFlags1.None) |
                        (node.IsTracker ? PCPHostFlags1.Tracker : PCPHostFlags1.None) |
                        (node.IsRelayFull ? PCPHostFlags1.None : PCPHostFlags1.Relay) |
                        (node.IsDirectFull ? PCPHostFlags1.None : PCPHostFlags1.Direct) |
                        (node.IsReceiving ? PCPHostFlags1.Receiving : PCPHostFlags1.None) |
                        (node.IsControlFull ? PCPHostFlags1.None : PCPHostFlags1.ControlIn));
                    Connection.WriteAsync(new Atom(Atom.PCP_HOST, host_atom));
                    Logger.Debug("Sending Node: {0}({1})", globalendpoint, node.SessionID.ToString("N"));
                }
            }
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_UNAVAILABLE));
                break;

            case StopReason.OffAir:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_OFFAIR));
                break;

            case StopReason.UserShutdown:
                Connection.WriteAsync(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_SHUTDOWN));
                break;
            }

            if (Channel != null)
            {
                Channel.ContentChanged      -= Channel_ContentChanged;
                Channel.ChannelInfoChanged  -= Channel_ChannelPropertyChanged;
                Channel.ChannelTrackChanged -= Channel_ChannelPropertyChanged;
            }
            return(base.OnStopped(cancel_token));
        }
 protected override void DoStop(StopReason reason)
 {
     switch (reason) {
       case StopReason.None:
     break;
       case StopReason.Any:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
     break;
       case StopReason.SendTimeoutError:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_SKIP));
     break;
       case StopReason.BadAgentError:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_BADAGENT));
     break;
       case StopReason.ConnectionError:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_READ));
     break;
       case StopReason.NotIdentifiedError:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_NOTIDENTIFIED));
     break;
       case StopReason.UnavailableError:
     {
       //次に接続するホストを送ってQUIT
       foreach (var node in SelectSourceHosts((IPEndPoint)RemoteEndPoint)) {
     if (Downhost!=null && Downhost.SessionID==node.SessionID) continue;
     var host_atom = new AtomCollection(node.Extra);
     Atom ip = host_atom.FindByName(Atom.PCP_HOST_IP);
     while (ip!=null) {
       host_atom.Remove(ip);
       ip = host_atom.FindByName(Atom.PCP_HOST_IP);
     }
     Atom port = host_atom.FindByName(Atom.PCP_HOST_PORT);
     while (port!=null) {
       host_atom.Remove(port);
       port = host_atom.FindByName(Atom.PCP_HOST_PORT);
     }
     host_atom.SetHostSessionID(node.SessionID);
     var globalendpoint = node.GlobalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
     host_atom.AddHostIP(globalendpoint.Address);
     host_atom.AddHostPort(globalendpoint.Port);
     var localendpoint  = node.LocalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
     host_atom.AddHostIP(localendpoint.Address);
     host_atom.AddHostPort(localendpoint.Port);
     host_atom.SetHostNumRelays(node.RelayCount);
     host_atom.SetHostNumListeners(node.DirectCount);
     host_atom.SetHostChannelID(Channel.ChannelID);
     host_atom.SetHostFlags1(
       (node.IsFirewalled ? PCPHostFlags1.Firewalled : PCPHostFlags1.None) |
       (node.IsTracker ? PCPHostFlags1.Tracker : PCPHostFlags1.None) |
       (node.IsRelayFull ? PCPHostFlags1.None : PCPHostFlags1.Relay) |
       (node.IsDirectFull ? PCPHostFlags1.None : PCPHostFlags1.Direct) |
       (node.IsReceiving ? PCPHostFlags1.Receiving : PCPHostFlags1.None) |
       (node.IsControlFull ? PCPHostFlags1.None : PCPHostFlags1.ControlIn));
     Send(new Atom(Atom.PCP_HOST, host_atom));
     Logger.Debug("Sending Node: {0}({1})", globalendpoint, node.SessionID.ToString("N"));
       }
     }
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_UNAVAILABLE));
     break;
       case StopReason.OffAir:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_OFFAIR));
     break;
       case StopReason.UserShutdown:
     Send(new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT + Atom.PCP_ERROR_SHUTDOWN));
     break;
       }
       base.DoStop(reason);
 }
 protected virtual void OnPCPHelo(Atom atom)
 {
     if (Downhost!=null) return;
       Logger.Debug("Helo received");
       var session_id = atom.Children.GetHeloSessionID();
       int remote_port = 0;
       if (session_id!=null) {
     var host = new HostBuilder();
     host.SessionID = session_id.Value;
     var port = atom.Children.GetHeloPort();
     var ping = atom.Children.GetHeloPing();
     if (port!=null) {
       remote_port = port.Value;
     }
     else if (ping!=null) {
       if (IsPingTarget(((IPEndPoint)RemoteEndPoint).Address) &&
       PingHost(new IPEndPoint(((IPEndPoint)RemoteEndPoint).Address, ping.Value), session_id.Value)) {
     remote_port = ping.Value;
       }
       else {
     remote_port = 0;
       }
     }
     else {
       remote_port = 0;
     }
     if (remote_port!=0)  {
       var ip = new IPEndPoint(((IPEndPoint)RemoteEndPoint).Address, remote_port);
       if (host.GlobalEndPoint==null || !host.GlobalEndPoint.Equals(ip)) {
     host.GlobalEndPoint = ip;
       }
     }
     host.IsFirewalled = remote_port==0;
     host.Extra.Update(atom.Children);
     Downhost = host.ToHost();
       }
       var oleh = new AtomCollection();
       if (RemoteEndPoint!=null && RemoteEndPoint.AddressFamily==System.Net.Sockets.AddressFamily.InterNetwork) {
     oleh.SetHeloRemoteIP(((IPEndPoint)RemoteEndPoint).Address);
       }
       oleh.SetHeloAgent(PeerCast.AgentName);
       oleh.SetHeloSessionID(PeerCast.SessionID);
       oleh.SetHeloRemotePort(remote_port);
       oleh.SetHeloVersion(PCP_VERSION);
       Send(new Atom(Atom.PCP_OLEH, oleh));
       if (Downhost==null) {
     Logger.Info("Helo has no SessionID");
     //セッションIDが無かった
     Stop(StopReason.NotIdentifiedError);
       }
       else if ((Downhost.Extra.GetHeloVersion() ?? 0)<1200) {
     Logger.Info("Helo version {0} is too old", Downhost.Extra.GetHeloVersion() ?? 0);
     //クライアントバージョンが無かった、もしくは古すぎ
     Stop(StopReason.BadAgentError);
       }
       else if (IsRelayFull) {
     Logger.Debug("Handshake succeeded {0}({1}) but relay is full", Downhost.GlobalEndPoint, Downhost.SessionID.ToString("N"));
     //次に接続するホストを送ってQUIT
     foreach (var node in SelectSourceHosts((IPEndPoint)RemoteEndPoint)) {
       var host_atom = new AtomCollection(node.Extra);
       Atom ip = host_atom.FindByName(Atom.PCP_HOST_IP);
       while (ip!=null) {
     host_atom.Remove(ip);
     ip = host_atom.FindByName(Atom.PCP_HOST_IP);
       }
       Atom port = host_atom.FindByName(Atom.PCP_HOST_PORT);
       while (port!=null) {
     host_atom.Remove(port);
     port = host_atom.FindByName(Atom.PCP_HOST_PORT);
       }
       host_atom.SetHostSessionID(node.SessionID);
       var globalendpoint = node.GlobalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
       host_atom.AddHostIP(globalendpoint.Address);
       host_atom.AddHostPort(globalendpoint.Port);
       var localendpoint  = node.LocalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
       host_atom.AddHostIP(localendpoint.Address);
       host_atom.AddHostPort(localendpoint.Port);
       host_atom.SetHostNumRelays(node.RelayCount);
       host_atom.SetHostNumListeners(node.DirectCount);
       host_atom.SetHostChannelID(Channel.ChannelID);
       host_atom.SetHostFlags1(
     (node.IsFirewalled ? PCPHostFlags1.Firewalled : PCPHostFlags1.None) |
     (node.IsTracker ? PCPHostFlags1.Tracker : PCPHostFlags1.None) |
     (node.IsRelayFull ? PCPHostFlags1.None : PCPHostFlags1.Relay) |
     (node.IsDirectFull ? PCPHostFlags1.None : PCPHostFlags1.Direct) |
     (node.IsReceiving ? PCPHostFlags1.Receiving : PCPHostFlags1.None) |
     (node.IsControlFull ? PCPHostFlags1.None : PCPHostFlags1.ControlIn));
       Send(new Atom(Atom.PCP_HOST, host_atom));
       Logger.Debug("Sending Node: {0}({1})", globalendpoint, node.SessionID.ToString("N"));
     }
     Stop(StopReason.UnavailableError);
       }
       else {
     Logger.Debug("Handshake succeeded {0}({1})", Downhost.GlobalEndPoint, Downhost.SessionID.ToString("N"));
     Send(new Atom(Atom.PCP_OK, (int)1));
       }
 }
 private void PostHostInfo(AtomCollection parent, Channel channel, bool playing)
 {
     var host = channel.SelfNode;
       var hostinfo = new AtomCollection();
       hostinfo.SetHostChannelID(channel.ChannelID);
       hostinfo.SetHostSessionID(PeerCast.SessionID);
       var globalendpoint = host.GlobalEndPoint;
       if (globalendpoint!=null) {
     hostinfo.AddHostIP(globalendpoint.Address);
     hostinfo.AddHostPort(globalendpoint.Port);
       }
       var localendpoint = host.LocalEndPoint;
       if (localendpoint!=null) {
     hostinfo.AddHostIP(localendpoint.Address);
     hostinfo.AddHostPort(localendpoint.Port);
       }
       hostinfo.SetHostNumListeners(channel.TotalDirects);
       hostinfo.SetHostNumRelays(channel.TotalRelays);
       hostinfo.SetHostUptime(channel.Uptime);
       if (channel.Contents.Count > 0) {
     hostinfo.SetHostOldPos((uint)(channel.Contents.Oldest.Position & 0xFFFFFFFFU));
     hostinfo.SetHostNewPos((uint)(channel.Contents.Newest.Position & 0xFFFFFFFFU));
       }
       PCPVersion.SetHostVersion(hostinfo);
       hostinfo.SetHostFlags1(
     (PeerCast.AccessController.IsChannelRelayable(channel) ? PCPHostFlags1.Relay : 0) |
     (PeerCast.AccessController.IsChannelPlayable(channel) ? PCPHostFlags1.Direct : 0) |
     ((!PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value) ? PCPHostFlags1.Firewalled : 0) |
     PCPHostFlags1.Tracker |
     (playing ? PCPHostFlags1.Receiving : PCPHostFlags1.None));
       parent.SetHost(hostinfo);
 }
        protected virtual void OnPCPHelo(Atom atom)
        {
            if (Downhost != null)
            {
                return;
            }
            Logger.Debug("Helo received");
            var session_id  = atom.Children.GetHeloSessionID();
            int remote_port = 0;

            if (session_id != null)
            {
                var host = new HostBuilder();
                host.SessionID = session_id.Value;
                var port = atom.Children.GetHeloPort();
                var ping = atom.Children.GetHeloPing();
                if (port != null)
                {
                    remote_port = port.Value;
                }
                else if (ping != null)
                {
                    if (IsPingTarget(((IPEndPoint)RemoteEndPoint).Address) &&
                        PingHost(new IPEndPoint(((IPEndPoint)RemoteEndPoint).Address, ping.Value), session_id.Value))
                    {
                        remote_port = ping.Value;
                    }
                    else
                    {
                        remote_port = 0;
                    }
                }
                else
                {
                    remote_port = 0;
                }
                if (remote_port != 0)
                {
                    var ip = new IPEndPoint(((IPEndPoint)RemoteEndPoint).Address, remote_port);
                    if (host.GlobalEndPoint == null || !host.GlobalEndPoint.Equals(ip))
                    {
                        host.GlobalEndPoint = ip;
                    }
                }
                host.IsFirewalled = remote_port == 0;
                host.Extra.Update(atom.Children);
                Downhost = host.ToHost();
            }
            var oleh = new AtomCollection();

            if (RemoteEndPoint != null && RemoteEndPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                oleh.SetHeloRemoteIP(((IPEndPoint)RemoteEndPoint).Address);
            }
            oleh.SetHeloAgent(PeerCast.AgentName);
            oleh.SetHeloSessionID(PeerCast.SessionID);
            oleh.SetHeloRemotePort(remote_port);
            oleh.SetHeloVersion(PCP_VERSION);
            Send(new Atom(Atom.PCP_OLEH, oleh));
            if (Downhost == null)
            {
                Logger.Info("Helo has no SessionID");
                //セッションIDが無かった
                Stop(StopReason.NotIdentifiedError);
            }
            else if ((Downhost.Extra.GetHeloVersion() ?? 0) < 1200)
            {
                Logger.Info("Helo version {0} is too old", Downhost.Extra.GetHeloVersion() ?? 0);
                //クライアントバージョンが無かった、もしくは古すぎ
                Stop(StopReason.BadAgentError);
            }
            else if (IsRelayFull)
            {
                Logger.Debug("Handshake succeeded {0}({1}) but relay is full", Downhost.GlobalEndPoint, Downhost.SessionID.ToString("N"));
                //次に接続するホストを送ってQUIT
                foreach (var node in SelectSourceHosts((IPEndPoint)RemoteEndPoint))
                {
                    var  host_atom = new AtomCollection(node.Extra);
                    Atom ip        = host_atom.FindByName(Atom.PCP_HOST_IP);
                    while (ip != null)
                    {
                        host_atom.Remove(ip);
                        ip = host_atom.FindByName(Atom.PCP_HOST_IP);
                    }
                    Atom port = host_atom.FindByName(Atom.PCP_HOST_PORT);
                    while (port != null)
                    {
                        host_atom.Remove(port);
                        port = host_atom.FindByName(Atom.PCP_HOST_PORT);
                    }
                    host_atom.SetHostSessionID(node.SessionID);
                    var globalendpoint = node.GlobalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
                    host_atom.AddHostIP(globalendpoint.Address);
                    host_atom.AddHostPort(globalendpoint.Port);
                    var localendpoint = node.LocalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
                    host_atom.AddHostIP(localendpoint.Address);
                    host_atom.AddHostPort(localendpoint.Port);
                    host_atom.SetHostNumRelays(node.RelayCount);
                    host_atom.SetHostNumListeners(node.DirectCount);
                    host_atom.SetHostChannelID(Channel.ChannelID);
                    host_atom.SetHostFlags1(
                        (node.IsFirewalled ? PCPHostFlags1.Firewalled : PCPHostFlags1.None) |
                        (node.IsTracker ? PCPHostFlags1.Tracker : PCPHostFlags1.None) |
                        (node.IsRelayFull ? PCPHostFlags1.None : PCPHostFlags1.Relay) |
                        (node.IsDirectFull ? PCPHostFlags1.None : PCPHostFlags1.Direct) |
                        (node.IsReceiving ? PCPHostFlags1.Receiving : PCPHostFlags1.None) |
                        (node.IsControlFull ? PCPHostFlags1.None : PCPHostFlags1.ControlIn));
                    Send(new Atom(Atom.PCP_HOST, host_atom));
                    Logger.Debug("Sending Node: {0}({1})", globalendpoint, node.SessionID.ToString("N"));
                }
                Stop(StopReason.UnavailableError);
            }
            else
            {
                Logger.Debug("Handshake succeeded {0}({1})", Downhost.GlobalEndPoint, Downhost.SessionID.ToString("N"));
                Send(new Atom(Atom.PCP_OK, (int)1));
            }
        }
 private void PostHostInfo(AtomCollection parent, Channel channel, bool playing)
 {
     var hostinfo = new AtomCollection();
       hostinfo.SetHostChannelID(channel.ChannelID);
       hostinfo.SetHostSessionID(PeerCast.SessionID);
       var globalendpoint = PeerCast.GetGlobalEndPoint(AddressFamily.InterNetwork, OutputStreamType.Relay);
       if (globalendpoint!=null) {
     hostinfo.AddHostIP(globalendpoint.Address);
     hostinfo.AddHostPort(globalendpoint.Port);
       }
       var localendpoint = PeerCast.GetLocalEndPoint(AddressFamily.InterNetwork, OutputStreamType.Relay);
       if (localendpoint!=null) {
     hostinfo.AddHostIP(localendpoint.Address);
     hostinfo.AddHostPort(localendpoint.Port);
       }
       hostinfo.SetHostNumListeners(channel.TotalDirects);
       hostinfo.SetHostNumRelays(channel.TotalRelays);
       hostinfo.SetHostUptime(channel.Uptime);
       if (channel.Contents.Count > 0) {
     hostinfo.SetHostOldPos((uint)(channel.Contents.Oldest.Position & 0xFFFFFFFFU));
     hostinfo.SetHostNewPos((uint)(channel.Contents.Newest.Position & 0xFFFFFFFFU));
       }
       PCPVersion.SetHostVersion(hostinfo);
       var relayable = PeerCast.AccessController.IsChannelRelayable(channel);
       var playable  = PeerCast.AccessController.IsChannelPlayable(channel) && PeerCast.FindListener(remoteEndPoint.Address, OutputStreamType.Play)!=null;
       var firewalled = !PeerCast.IsFirewalled.HasValue || PeerCast.IsFirewalled.Value || PeerCast.FindListener(remoteEndPoint.Address, OutputStreamType.Relay)==null;
       hostinfo.SetHostFlags1(
     (relayable ? PCPHostFlags1.Relay : 0) |
     (playable ? PCPHostFlags1.Direct : 0) |
     (firewalled ? PCPHostFlags1.Firewalled : 0) |
     PCPHostFlags1.Tracker |
     (playing ? PCPHostFlags1.Receiving : PCPHostFlags1.None));
       parent.SetHost(hostinfo);
 }