Ejemplo n.º 1
0
        public virtual void SendPCPHelo()
        {
            Logger.Debug("Handshake Started");
            var helo = new AtomCollection();

            helo.SetHeloAgent(PeerCast.AgentName);
            helo.SetHeloSessionID(PeerCast.SessionID);
            if (PeerCast.IsFirewalled.HasValue)
            {
                if (PeerCast.IsFirewalled.Value)
                {
                    //Do nothing
                }
                else
                {
                    var listener = PeerCast.FindListener(
                        RemoteEndPoint.Address,
                        OutputStreamType.Relay | OutputStreamType.Metadata);
                    helo.SetHeloPort(listener.LocalEndPoint.Port);
                }
            }
            else
            {
                var listener = PeerCast.FindListener(
                    RemoteEndPoint.Address,
                    OutputStreamType.Relay | OutputStreamType.Metadata);
                if (listener != null)
                {
                    helo.SetHeloPing(listener.LocalEndPoint.Port);
                }
            }
            helo.SetHeloVersion(PCP_VERSION);
            Send(new Atom(Atom.PCP_HELO, helo));
        }
Ejemplo n.º 2
0
        private void AnnounceThreadProc()
        {
            Logger.Debug("Thread started");
            var host = Uri.DnsSafeHost;
            var port = Uri.Port;

            if (port < 0)
            {
                port = DefaultPort;
            }
            while (!IsStopped)
            {
                int next_update = Environment.TickCount;
                posts.Clear();
                try {
                    Logger.Debug("Connecting to YP");
                    AnnouncingStatus = AnnouncingStatus.Connecting;
                    using (var client = new TcpClient(host, port)) {
                        using (var stream = client.GetStream()) {
                            AtomWriter.Write(stream, new Atom(new ID4("pcp\n"), (int)1));
                            var helo = new AtomCollection();
                            Logger.Debug("Sending Handshake");
                            helo.SetHeloAgent(PeerCast.AgentName);
                            helo.SetHeloVersion(1218);
                            helo.SetHeloSessionID(PeerCast.SessionID);
                            helo.SetHeloBCID(PeerCast.BroadcastID);
                            if (PeerCast.IsFirewalled.HasValue)
                            {
                                if (PeerCast.IsFirewalled.Value)
                                {
                                    //Do nothing
                                }
                                else
                                {
                                    var listener = PeerCast.FindListener(
                                        ((IPEndPoint)client.Client.RemoteEndPoint).Address,
                                        OutputStreamType.Relay | OutputStreamType.Metadata);
                                    if (listener != null)
                                    {
                                        helo.SetHeloPort(listener.LocalEndPoint.Port);
                                    }
                                }
                            }
                            else
                            {
                                var listener = PeerCast.FindListener(
                                    ((IPEndPoint)client.Client.RemoteEndPoint).Address,
                                    OutputStreamType.Relay | OutputStreamType.Metadata);
                                if (listener != null)
                                {
                                    helo.SetHeloPing(listener.LocalEndPoint.Port);
                                }
                            }
                            AtomWriter.Write(stream, new Atom(Atom.PCP_HELO, helo));
                            while (!IsStopped)
                            {
                                var atom = AtomReader.Read(stream);
                                if (atom.Name == Atom.PCP_OLEH)
                                {
                                    OnPCPOleh(atom);
                                    break;
                                }
                                else if (atom.Name == Atom.PCP_QUIT)
                                {
                                    Logger.Debug("Handshake aborted by PCP_QUIT ({0})", atom.GetInt32());
                                    throw new QuitException();
                                }
                                if (restartEvent.WaitOne(10))
                                {
                                    throw new RestartException();
                                }
                            }
                            Logger.Debug("Handshake succeeded");
                            AnnouncingStatus = AnnouncingStatus.Connected;
                            while (!IsStopped)
                            {
                                if (next_update - Environment.TickCount <= 0)
                                {
                                    Logger.Debug("Sending channel info");
                                    lock (announcingChannels) {
                                        foreach (var announcing in announcingChannels)
                                        {
                                            PostChannelBcst(announcing.Channel, true);
                                        }
                                    }
                                    next_update = Environment.TickCount + 30000;
                                }
                                if (stream.DataAvailable)
                                {
                                    Atom atom = AtomReader.Read(stream);
                                    ProcessAtom(atom);
                                }
                                lock (posts) {
                                    foreach (var atom in posts)
                                    {
                                        AtomWriter.Write(stream, atom);
                                    }
                                    posts.Clear();
                                }
                                if (restartEvent.WaitOne(10))
                                {
                                    throw new RestartException();
                                }
                            }
                            lock (posts) {
                                foreach (var atom in posts)
                                {
                                    AtomWriter.Write(stream, atom);
                                }
                                posts.Clear();
                            }
                            Logger.Debug("Closing connection");
                            AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
                        }
                    }
                }
                catch (RestartException) {
                    Logger.Debug("Connection retrying");
                    AnnouncingStatus = AnnouncingStatus.Connecting;
                }
                catch (BannedException) {
                    AnnouncingStatus = AnnouncingStatus.Error;
                    Logger.Error("Your BCID is banned");
                    break;
                }
                catch (QuitException) {
                    AnnouncingStatus = AnnouncingStatus.Error;
                }
                catch (SocketException e) {
                    AnnouncingStatus = AnnouncingStatus.Error;
                    Logger.Info(e);
                }
                catch (IOException e) {
                    AnnouncingStatus = AnnouncingStatus.Error;
                    Logger.Info(e);
                }
                Logger.Debug("Connection closed");
                if (!IsStopped)
                {
                    restartEvent.WaitOne(10000);
                }
                else
                {
                    AnnouncingStatus = AnnouncingStatus.Idle;
                }
            }
            Logger.Debug("Thread finished");
        }
Ejemplo n.º 3
0
        public Uri FindTracker(Guid channel_id)
        {
            Logger.Debug("Finding tracker {0} from {1}", channel_id.ToString("N"), Uri);
            var host = Uri.DnsSafeHost;
            var port = Uri.Port;
            Uri res  = null;

            if (port < 0)
            {
                port = DefaultPort;
            }
            try {
                var client  = new TcpClient(host, port);
                var stream  = client.GetStream();
                var request = System.Text.Encoding.UTF8.GetBytes(
                    String.Format("GET /channel/{0} HTTP/1.0\r\n", channel_id.ToString("N")) +
                    "x-peercast-pcp:1\r\n" +
                    "\r\n");
                stream.Write(request, 0, request.Length);
                var response = ReadResponse(stream);
                var md       = System.Text.RegularExpressions.Regex.Match(response, @"^HTTP/1.\d (\d+) ");
                if (md.Success)
                {
                    var status = md.Groups[1].Value;
                    switch (status)
                    {
                    case "503":
                        var helo = new AtomCollection();
                        helo.SetHeloAgent(PeerCast.AgentName);
                        helo.SetHeloVersion(1218);
                        helo.SetHeloSessionID(PeerCast.SessionID);
                        helo.SetHeloPort(0);
                        AtomWriter.Write(stream, new Atom(Atom.PCP_HELO, helo));
                        var hosts = ReadHosts(stream, channel_id);
                        res = HostToUri(hosts.FirstOrDefault(h => h.IsTracker), channel_id);
                        break;

                    case "200":
                        //なぜかリレー可能だったのでYP自体をトラッカーとみなしてしまうことにする
                        AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
                        res = Uri;
                        break;

                    default:
                        //エラーだったのでトラッカーのアドレスを貰えず終了
                        break;
                    }
                }
                AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
                client.Close();
            }
            catch (SocketException)
            {
            }
            catch (IOException)
            {
            }
            if (res != null)
            {
                Logger.Debug("Tracker found: {0}", res);
            }
            else
            {
                Logger.Debug("Tracker no found");
            }
            return(res);
        }
Ejemplo n.º 4
0
 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));
       }
 }
Ejemplo n.º 5
0
 private void AnnounceThreadProc()
 {
     Logger.Debug("Thread started");
       var host = Uri.DnsSafeHost;
       var port = Uri.Port;
       if (port<0) port = PCPVersion.DefaultPort;
       while (!IsStopped) {
     int next_update = Environment.TickCount;
     posts.Clear();
     try {
       Logger.Debug("Connecting to YP");
       AnnouncingStatus = AnnouncingStatus.Connecting;
       using (var client = new TcpClient(host, port)) {
     remoteEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
     using (var stream = client.GetStream()) {
       AtomWriter.Write(stream, new Atom(new ID4("pcp\n"), (int)1));
       var helo = new AtomCollection();
       Logger.Debug("Sending Handshake");
       helo.SetHeloAgent(PeerCast.AgentName);
       helo.SetHeloVersion(1218);
       helo.SetHeloSessionID(PeerCast.SessionID);
       helo.SetHeloBCID(PeerCast.BroadcastID);
       if (PeerCast.IsFirewalled.HasValue) {
         if (PeerCast.IsFirewalled.Value) {
           //Do nothing
         }
         else {
           var listener = PeerCast.FindListener(
             ((IPEndPoint)client.Client.RemoteEndPoint).Address,
             OutputStreamType.Relay | OutputStreamType.Metadata);
           if (listener!=null) {
             helo.SetHeloPort(listener.LocalEndPoint.Port);
           }
         }
       }
       else {
         var listener = PeerCast.FindListener(
           ((IPEndPoint)client.Client.RemoteEndPoint).Address,
           OutputStreamType.Relay | OutputStreamType.Metadata);
         if (listener!=null) {
           helo.SetHeloPing(listener.LocalEndPoint.Port);
         }
       }
       AtomWriter.Write(stream, new Atom(Atom.PCP_HELO, helo));
       while (!IsStopped) {
         var atom = AtomReader.Read(stream);
         if (atom.Name==Atom.PCP_OLEH) {
           OnPCPOleh(atom);
           break;
         }
         else if (atom.Name==Atom.PCP_QUIT) {
           Logger.Debug("Handshake aborted by PCP_QUIT ({0})", atom.GetInt32());
           throw new QuitException();
         }
         if (restartEvent.WaitOne(10)) throw new RestartException();
       }
       Logger.Debug("Handshake succeeded");
       AnnouncingStatus = AnnouncingStatus.Connected;
       while (!IsStopped) {
         if (next_update-Environment.TickCount<=0) {
           Logger.Debug("Sending channel info");
           lock (announcingChannels) {
             foreach (var announcing in announcingChannels) {
               PostChannelBcst(announcing.Channel, true);
             }
           }
           next_update = Environment.TickCount+30000;
         }
         if (stream.DataAvailable) {
           Atom atom = AtomReader.Read(stream);
           ProcessAtom(atom);
         }
         lock (posts) {
           foreach (var atom in posts) {
             AtomWriter.Write(stream, atom);
           }
           posts.Clear();
         }
         if (restartEvent.WaitOne(10)) throw new RestartException();
       }
       lock (posts) {
         foreach (var atom in posts) {
           AtomWriter.Write(stream, atom);
         }
         posts.Clear();
       }
       Logger.Debug("Closing connection");
       AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
     }
       }
     }
     catch (RestartException) {
       Logger.Debug("Connection retrying");
       AnnouncingStatus = AnnouncingStatus.Connecting;
     }
     catch (BannedException) {
       AnnouncingStatus = AnnouncingStatus.Error;
       Logger.Error("Your BCID is banned");
       break;
     }
     catch (QuitException) {
       AnnouncingStatus = AnnouncingStatus.Error;
     }
     catch (SocketException e) {
       AnnouncingStatus = AnnouncingStatus.Error;
       Logger.Info(e);
     }
     catch (IOException e) {
       AnnouncingStatus = AnnouncingStatus.Error;
       Logger.Info(e);
     }
     finally {
       remoteEndPoint = null;
     }
     Logger.Debug("Connection closed");
     if (!IsStopped) {
       restartEvent.WaitOne(10000);
     }
     else {
       AnnouncingStatus = AnnouncingStatus.Idle;
     }
       }
       Logger.Debug("Thread finished");
 }
Ejemplo n.º 6
0
 public Uri FindTracker(Guid channel_id)
 {
     Logger.Debug("Finding tracker {0} from {1}", channel_id.ToString("N"), Uri);
       var host = Uri.DnsSafeHost;
       var port = Uri.Port;
       Uri res = null;
       if (port<0) port = PCPVersion.DefaultPort;
       try {
     var client = new TcpClient(host, port);
     var stream = client.GetStream();
     var request = System.Text.Encoding.UTF8.GetBytes(
       String.Format("GET /channel/{0} HTTP/1.0\r\n", channel_id.ToString("N")) +
       "x-peercast-pcp:1\r\n" +
       "\r\n");
     stream.Write(request, 0, request.Length);
     var response = ReadResponse(stream);
     var md = System.Text.RegularExpressions.Regex.Match(response, @"^HTTP/1.\d (\d+) ");
     if (md.Success) {
       var status = md.Groups[1].Value;
       switch (status) {
       case "503":
     var helo = new AtomCollection();
     helo.SetHeloAgent(PeerCast.AgentName);
     helo.SetHeloVersion(1218);
     helo.SetHeloSessionID(PeerCast.SessionID);
     helo.SetHeloPort(0);
     AtomWriter.Write(stream, new Atom(Atom.PCP_HELO, helo));
     var hosts = ReadHosts(stream, channel_id);
     res = HostToUri(hosts.FirstOrDefault(h => h.IsTracker), channel_id);
     break;
       case "200":
     //なぜかリレー可能だったのでYP自体をトラッカーとみなしてしまうことにする
     AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
     res = Uri;
     break;
       default:
     //エラーだったのでトラッカーのアドレスを貰えず終了
     break;
       }
     }
     AtomWriter.Write(stream, new Atom(Atom.PCP_QUIT, Atom.PCP_ERROR_QUIT));
     client.Close();
       }
       catch (SocketException)
       {
       }
       catch (IOException)
       {
       }
       if (res!=null) {
     Logger.Debug("Tracker found: {0}", res);
       }
       else {
     Logger.Debug("Tracker no found");
       }
       return res;
 }
Ejemplo n.º 7
0
        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));
            }
        }