private void AnnounceThreadProc()
{
Logger.Debug("Thread started");
var host = AnnounceUri.DnsSafeHost;
var port = AnnounceUri.Port;
if (port<0) port = PCPVersion.DefaultPort;
while (!IsStopped) {
int next_update = Environment.TickCount;
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) {
UpdateChannelInfo(announcing.Channel, true);
}
}
next_update = Environment.TickCount+30000;
}
if (stream.DataAvailable) {
Atom atom = AtomReader.Read(stream);
ProcessAtom(atom);
}
lock (updatedChannels) {
foreach (var updated in updatedChannels) {
AtomWriter.Write(stream, CreateChannelBcst(updated.Channel, updated.Playing));
}
updatedChannels.Clear();
}
if (restartEvent.WaitOne(10)) throw new RestartException();
}
lock (updatedChannels) {
foreach (var updated in updatedChannels) {
AtomWriter.Write(stream, CreateChannelBcst(updated.Channel, updated.Playing));
}
updatedChannels.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 (InvalidDataException e) {
AnnouncingStatus = AnnouncingStatus.Error;
Logger.Error(e);
break;
}
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");
}