4 using System.Collections;
\r
5 using System.Threading;
\r
7 namespace ByteFX.Data.Common
\r
9 internal enum MultiHostStreamErrorType
\r
17 /// Summary description for MultiHostStream.
\r
19 internal abstract class MultiHostStream : Stream
\r
21 protected Stream stream;
\r
22 protected int readTimeOut;
\r
23 protected Exception baseException;
\r
26 /// Constructs a new MultiHostStream object with the given parameters
\r
28 /// <param name="hostList"></param>
\r
29 /// <param name="port"></param>
\r
30 /// <param name="readTimeOut"></param>
\r
31 /// <param name="connectTimeOut"></param>
\r
32 public MultiHostStream(string hostList, int port, int readTimeOut, int connectTimeOut)
\r
34 this.readTimeOut = readTimeOut;
\r
35 ProcessHosts( hostList, port, connectTimeOut );
\r
39 protected abstract void TimeOut(MultiHostStreamErrorType error);
\r
40 protected abstract void Error(string msg);
\r
41 protected abstract bool CreateStream( IPAddress ip, string host, int port );
\r
42 protected abstract bool CreateStream (string fileName);
\r
43 protected abstract bool DataAvailable
\r
48 private void ProcessHosts( string hostList, int port, int connectTimeOut )
\r
50 int startTime = Environment.TickCount;
\r
52 int toTicks = connectTimeOut * 1000;
\r
54 // support Unix sockets
\r
55 if (hostList.StartsWith ("/"))
\r
57 CreateStream (hostList);
\r
62 // Host name can contain multiple hosts, seperated by &.
\r
63 string [] dnsHosts = hostList.Split('&');
\r
64 Hashtable ips = new Hashtable();
\r
67 // Each host name specified may contain multiple IP addresses
\r
68 // Lets look at the DNS entries for each host name
\r
69 foreach(string h in dnsHosts)
\r
71 IPHostEntry hostAddress = Dns.GetHostByName(h);
\r
72 foreach (IPAddress addr in hostAddress.AddressList)
\r
73 ips.Add( addr, hostAddress.HostName );
\r
75 IPAddress[] keys = new IPAddress[ ips.Count ];
\r
76 ips.Keys.CopyTo( keys, 0 );
\r
78 if ((Environment.TickCount - startTime) > toTicks)
\r
80 TimeOut(MultiHostStreamErrorType.Connecting);
\r
84 // make sure they gave us at least one host
\r
87 Error("You must specify at least one host");
\r
92 // now choose a random server if there are more than one
\r
95 System.Random random = new Random((int)DateTime.Now.Ticks);
\r
96 index = random.Next(ips.Count-1);
\r
100 // Lets step through our hosts until we get a connection
\r
101 for (int i=0; i < ips.Count; i++)
\r
103 if ((Environment.TickCount - startTime) > toTicks)
\r
105 TimeOut(MultiHostStreamErrorType.Connecting);
\r
108 if (CreateStream( (IPAddress)keys[i], (string)ips[keys[i]], port ))
\r
113 public override int ReadByte()
\r
115 int start = Environment.TickCount;
\r
116 int ticks = readTimeOut * 1000;
\r
118 while ((Environment.TickCount - start) < ticks)
\r
122 int b = stream.ReadByte();
\r
129 TimeOut(MultiHostStreamErrorType.Reading);
\r
133 public override int Read(byte[] buffer, int offset, int count)
\r
135 int numToRead = count;
\r
136 int start = Environment.TickCount;
\r
137 int ticks = readTimeOut * 1000;
\r
141 while (numToRead > 0 && (Environment.TickCount - start) < ticks)
\r
143 if (DataAvailable)
\r
145 int bytes_read = stream.Read( buffer, offset, numToRead);
\r
146 if (bytes_read == 0)
\r
147 return (count - numToRead);
\r
148 offset += bytes_read;
\r
149 numToRead -= bytes_read;
\r
155 catch (Exception ex)
\r
157 Console.WriteLine(ex.Message);
\r
161 TimeOut(MultiHostStreamErrorType.Reading);
\r
165 public override bool CanRead
\r
167 get { return stream.CanRead; }
\r
170 public override bool CanWrite
\r
172 get { return stream.CanWrite; }
\r
175 public override bool CanSeek
\r
177 get { return stream.CanSeek; }
\r
180 public override long Length
\r
182 get { return stream.Length; }
\r
185 public override long Position
\r
187 get { return stream.Position; }
\r
188 set { stream.Position = value; }
\r
191 public override void Flush()
\r
196 public override void SetLength(long length)
\r
198 stream.SetLength( length );
\r
201 public override void Write(byte[] buffer, int offset, int count)
\r
203 stream.Write( buffer, offset, count );
\r
206 public override long Seek( long offset, SeekOrigin origin )
\r
208 return stream.Seek( offset, origin );
\r