| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- using System;
- using System.Net;
- using System.IO;
- using System.Collections;
- using System.Threading;
- namespace ByteFX.Data.Common
- {
- internal enum MultiHostStreamErrorType
- {
- Connecting,
- Reading,
- Writing
- }
- /// <summary>
- /// Summary description for MultiHostStream.
- /// </summary>
- internal abstract class MultiHostStream : Stream
- {
- protected Stream stream;
- protected int readTimeOut;
- protected Exception baseException;
- /// <summary>
- /// Constructs a new MultiHostStream object with the given parameters
- /// </summary>
- /// <param name="hostList"></param>
- /// <param name="port"></param>
- /// <param name="readTimeOut"></param>
- /// <param name="connectTimeOut"></param>
- public MultiHostStream(string hostList, int port, int readTimeOut, int connectTimeOut)
- {
- this.readTimeOut = readTimeOut;
- ProcessHosts( hostList, port, connectTimeOut );
- }
- // abstract members
- protected abstract void TimeOut(MultiHostStreamErrorType error);
- protected abstract void Error(string msg);
- protected abstract bool CreateStream( IPAddress ip, string host, int port );
- protected abstract bool CreateStream (string fileName);
- protected abstract bool DataAvailable
- {
- get;
- }
- private void ProcessHosts( string hostList, int port, int connectTimeOut )
- {
- int startTime = Environment.TickCount;
- int toTicks = connectTimeOut * 1000;
- // support Unix sockets
- if (hostList.StartsWith ("/"))
- {
- CreateStream (hostList);
- return;
- }
- //
- // Host name can contain multiple hosts, seperated by &.
- string [] dnsHosts = hostList.Split('&');
- Hashtable ips = new Hashtable();
- //
- // Each host name specified may contain multiple IP addresses
- // Lets look at the DNS entries for each host name
- foreach(string h in dnsHosts)
- {
- IPHostEntry hostAddress = Dns.GetHostByName(h);
- foreach (IPAddress addr in hostAddress.AddressList)
- ips.Add( addr, hostAddress.HostName );
- }
- IPAddress[] keys = new IPAddress[ ips.Count ];
- ips.Keys.CopyTo( keys, 0 );
- if ((Environment.TickCount - startTime) > toTicks)
- {
- TimeOut(MultiHostStreamErrorType.Connecting);
- return;
- }
- // make sure they gave us at least one host
- if (ips.Count == 0)
- {
- Error("You must specify at least one host");
- return;
- }
- int index = 0;
- // now choose a random server if there are more than one
- if (ips.Count > 1)
- {
- System.Random random = new Random((int)DateTime.Now.Ticks);
- index = random.Next(ips.Count-1);
- }
- //
- // Lets step through our hosts until we get a connection
- for (int i=0; i < ips.Count; i++)
- {
- if ((Environment.TickCount - startTime) > toTicks)
- {
- TimeOut(MultiHostStreamErrorType.Connecting);
- return;
- }
- if (CreateStream( (IPAddress)keys[i], (string)ips[keys[i]], port ))
- return;
- }
- }
- public override int ReadByte()
- {
- int start = Environment.TickCount;
- int ticks = readTimeOut * 1000;
- while ((Environment.TickCount - start) < ticks)
- {
- if (DataAvailable)
- {
- int b = stream.ReadByte();
- return b;
- }
- else
- Thread.Sleep(0);
- }
- TimeOut(MultiHostStreamErrorType.Reading);
- return -1;
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- int numToRead = count;
- int start = Environment.TickCount;
- int ticks = readTimeOut * 1000;
- try
- {
- while (numToRead > 0 && (Environment.TickCount - start) < ticks)
- {
- if (DataAvailable)
- {
- int bytes_read = stream.Read( buffer, offset, numToRead);
- if (bytes_read == 0)
- return (count - numToRead);
- offset += bytes_read;
- numToRead -= bytes_read;
- }
- else
- Thread.Sleep(0);
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- if (numToRead > 0)
- TimeOut(MultiHostStreamErrorType.Reading);
- return count;
- }
- public override bool CanRead
- {
- get { return stream.CanRead; }
- }
- public override bool CanWrite
- {
- get { return stream.CanWrite; }
- }
- public override bool CanSeek
- {
- get { return stream.CanSeek; }
- }
- public override long Length
- {
- get { return stream.Length; }
- }
- public override long Position
- {
- get { return stream.Position; }
- set { stream.Position = value; }
- }
- public override void Flush()
- {
- stream.Flush();
- }
- public override void SetLength(long length)
- {
- stream.SetLength( length );
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- stream.Write( buffer, offset, count );
- }
- public override long Seek( long offset, SeekOrigin origin )
- {
- return stream.Seek( offset, origin );
- }
- }
- }
|