rendered paste bodyusing System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Diagnostics;
using System.Timers;
using System.Threading;
namespace NzbLibrary.NNTP
{
public enum NNTPConnectionStatus { Idle, Downloading };
public delegate void DownloadCompleteEvent(object sender);
public class NNTPConnection : TcpClient
{
private static List<NNTPConnection> m_Connections = new List<NNTPConnection>();
public static NNTPConnection[] Connections { get { return m_Connections.ToArray(); } }
private const long PacketSize = 8192;
private const long SpeedHistoryDuration = 120;
private const string CacheDirectory = @"D:\Projects\NzbDownloader\Articles\";
#region Speed Monitoring
private Dictionary<long, long> m_SpeedHistory = new Dictionary<long, long>();
private System.Timers.Timer m_SpeedTimer = null;
private long m_BytesLastSecond = 0;
private long m_Second = 0;
private long m_StartTime;
public Dictionary<long, long> SpeedHistory { get { return m_SpeedHistory; } }
public long Second { get { return m_Second; } }
private void SpeedTimer_Elapsed(object sender, EventArgs e)
{
if (m_BytesLastSecond > 0)
{
m_SpeedHistory.Add(m_Second, m_BytesLastSecond);
m_BytesLastSecond = 0;
}
m_Second++;
if (m_SpeedHistory.Count > 0)
{
foreach (KeyValuePair<long, long> kvp in m_SpeedHistory)
{
if (kvp.Key < m_Second - SpeedHistoryDuration)
{
m_SpeedHistory.Remove(kvp.Key);
}
}
}
}
#endregion
private string m_CurrentGroup = "";
private string m_CurrentArticle = "";
private Stream Stream { get { return GetStream(); } }
private NNTPConnectionStatus m_Status = NNTPConnectionStatus.Idle;
private StreamReader Reader { get { return new StreamReader(Stream); } }
private StreamWriter Writer { get { return new StreamWriter(Stream); } }
private string Response { get { return ReadLine(); } }
private int ResponseCode
{
get
{
string[] Parts = Response.Split(' ');
int Code = 0;
if (int.TryParse(Parts[0], out Code))
{
Code = int.Parse(Parts[0]);
}
else
{
Code = -1;
}
return Code;
}
}
public string CurrentGroup { get { return m_CurrentGroup; } }
public NNTPConnectionStatus Status { get { return m_Status; } }
public event DownloadCompleteEvent DownloadComplete;
public NNTPConnection()
: base()
{
#region Speed Monitoring
m_SpeedTimer = new System.Timers.Timer();
m_StartTime = DateTime.Now.Ticks;
m_SpeedTimer.Interval = 1000;
m_SpeedTimer.Elapsed += new ElapsedEventHandler(SpeedTimer_Elapsed);
m_SpeedTimer.Start();
#endregion
m_Connections.Add(this);
}
~NNTPConnection()
{
#region Speed Monitoring
m_SpeedTimer.Stop();
#endregion
m_Connections.Remove(this);
}
private string ReadLine()
{
try
{
string Data = Reader.ReadLine();
Debug.WriteLine("< " + Data);
return Data;
}
catch (IOException io)
{
if (io.InnerException is SocketException)
{
SocketException se = (SocketException)io.InnerException;
if (se.ErrorCode == 10060)
Disconnect();
throw se;
}
else
{
throw io;
}
}
}
private void WriteLine(string Data)
{
Debug.WriteLine("> " + Data);
Stream.Write(ASCIIEncoding.ASCII.GetBytes(Data), 0, Data.Length);
Stream.Write(ASCIIEncoding.ASCII.GetBytes(Environment.NewLine), 0, Environment.NewLine.Length);
}
private void ClearBuffer()
{
Reader.ReadToEnd();
}
public new bool Connect(string HostName, int Port)
{
Debug.WriteLine("? Connecting...");
base.Connect(HostName, Port);
switch (ResponseCode)
{
case 200:
case 201:
Debug.WriteLine("? Connected.");
return true;
}
m_CurrentGroup = "";
Debug.WriteLine("? Connection Failed.");
Disconnect();
return false;
}
public void Disconnect()
{
Debug.WriteLine("? Disconnecting...");
if (base.Connected)
{
WriteLine("QUIT");
}
base.Close();
Debug.WriteLine("? Disconnected.");
}
public bool Authenticate(string UserName, string Password)
{
Debug.WriteLine("? Authenticating...");
WriteLine("AUTHINFO USER " + UserName);
if (ResponseCode == 381)
{
WriteLine("AUTHINFO PASS " + Password);
if (ResponseCode == 281)
{
Debug.WriteLine("? Authenticated.");
return true;
}
}
Debug.WriteLine("? Authentication Failed.");
return false;
}
public bool SelectGroup(string Group)
{
if (Group == CurrentGroup) { return true; }
Debug.WriteLine("? Selecting Group: '" + Group + "'");
WriteLine("GROUP " + Group);
if (ResponseCode == 211)
{
Debug.WriteLine("? Group '" + Group + "' Selected.");
m_CurrentGroup = Group;
return true;
}
return false;
}
public bool DownloadArticle(string MessageId)
{
string FileName = CacheDirectory + MessageId;
Debug.WriteLine("? Downloading Article: '" + MessageId);
WriteLine("BODY <" + MessageId + ">");
switch (ResponseCode)
{
case 220:
case 221:
case 222:
m_Status = NNTPConnectionStatus.Downloading;
Thread TransferThread = new Thread(Transfer);
TransferThread.Start();
return true;
}
return false;
}
private void Transfer()
{
StringBuilder Data = new StringBuilder();
while (true)
{
byte[] Section = new byte[PacketSize];
int Read = Stream.Read(Section, 0, Section.Length);
m_BytesLastSecond += Read;
for (int i = 0; i < Read; i++)
{
Data.Append((char)Section[i]);
}
if (Data[Data.Length - 3] == '.' && Data[Data.Length - 2] == '\r' && Data[Data.Length - 1] == '\n') { break; }
if (Read == 0) { break; }
}
Data = Data.Replace("\r\n..", "\r\n.");
FileStream Output = new FileStream(CacheDirectory + m_CurrentArticle, FileMode.Create, FileAccess.Write, FileShare.None);
StreamWriter Writer = new StreamWriter(Output, Encoding.GetEncoding("iso-8859-1"));
Writer.Write(Data.ToString());
Writer.Close();
Output.Close();
m_CurrentArticle = "";
if (DownloadComplete != null) { DownloadComplete(this); }
m_Status = NNTPConnectionStatus.Idle;
}
}
}