MySql - fixed problem where socket was not getting closed properly (thanks Steve!)
[mono.git] / mcs / class / ByteFX.Data / mysqlclient / MySqlStream.cs
1 // ByteFX.Data data access components for .Net
2 // Copyright (C) 2002-2003  ByteFX, Inc.
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 // 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 // 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18 using System;
19 using System.IO;
20 using System.Net;
21 using System.Net.Sockets;
22 using ByteFX.Data.Common;
23
24 namespace ByteFX.Data.MySqlClient
25 {
26         /// <summary>
27         /// Summary description for API.
28         /// </summary>
29         internal class MySqlStream : Stream
30         {
31                 Stream  stream;
32                 Socket  socket;
33                 int             timeOut;
34
35                 public MySqlStream( string host, int port, int timeout )
36                 {
37                         if (port == -1)
38                                 Create( host );
39                         else
40                                 Create( host, port );
41                         timeOut = timeout;
42                 }
43
44                 public bool IsClosed
45                 {
46                         get 
47                         {
48                                 if (stream is NetworkStream) 
49                                 {
50                                         bool poll = socket.Poll(-1, SelectMode.SelectWrite );
51                                         poll = socket.Poll(-1, SelectMode.SelectRead );
52                                         poll = socket.Poll(-1, SelectMode.SelectError );
53                                         return ! poll;
54                                 }
55                                 return false;
56                         }
57                 }
58
59                 private void Create( string host, int port )
60                 {
61                         socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
62                         IPHostEntry he = Dns.GetHostByName( host );
63                         IPEndPoint serverAddr = new IPEndPoint(he.AddressList[0], port);
64
65                         socket.Connect(serverAddr);
66                         stream = new NetworkStream(socket, true);
67                 }
68
69                 private void Create( string host )
70                 {
71                         string pipeName;
72
73                         if (host.ToLower().Equals("localhost"))
74                                 pipeName = @"\\.\pipe\MySql";
75                         else
76                                 pipeName = String.Format(@"\\{0}\pipe\MySql", host);
77
78                         stream = new ByteFX.Data.Common.NamedPipeStream(pipeName, FileAccess.ReadWrite);
79                 }
80
81                 public bool DataAvailable
82                 {
83                         get 
84                         {
85                                 if (stream is NetworkStream)
86                                         return ((NetworkStream)stream).DataAvailable;
87                                 else return (stream as NamedPipeStream).DataAvailable;
88                         }
89         }
90
91                 public override bool CanRead
92                 {
93                         get { return stream.CanRead; }
94                 }
95
96                 public override bool CanWrite
97                 {
98                         get { return stream.CanWrite; }
99                 }
100
101                 public override bool CanSeek
102                 {
103                         get { return stream.CanSeek; }
104                 }
105
106                 public override long Length
107                 {
108                         get { return stream.Length; }
109                 }
110
111                 public override long Position 
112                 {
113                         get { return stream.Position; }
114                         set { stream.Position = value; }
115                 }
116
117                 public override void Flush() 
118                 {
119                         stream.Flush();
120                 }
121
122                 public override int ReadByte()
123                 {
124                         long start = Environment.TickCount;
125                         long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
126
127                         while (((Environment.TickCount - start) < timeout_ticks))
128                         {
129                                 if (DataAvailable)
130                                 {
131                                         int b = stream.ReadByte();
132                                         return b;
133                                 }
134                         }
135                         throw new Exception("Timeout waiting for response from server");
136                 }
137
138                 public override int Read(byte[] buffer, int offset, int count)
139                 {
140                         long start = Environment.TickCount;
141                         int  numToRead = count;
142                         long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
143
144                         while (numToRead > 0 && ((Environment.TickCount - start) < timeout_ticks))
145                         {
146                                 if (DataAvailable)
147                                 {
148                                         int bytes_read = stream.Read(buffer, offset, numToRead);
149                                         offset += bytes_read;
150                                         numToRead -= bytes_read;
151                                 }
152                         }
153                         if (numToRead > 0)
154                                 throw new Exception("Timeout waiting for response from server");
155                         return count;
156                 }
157
158                 public int ReadInt24()
159                 {
160                         byte[] bytes = new byte[3];
161                         Read( bytes, 0, 3 );
162                         return (bytes[0] + (bytes[1]*256) + (bytes[2]*256*256));
163                 }
164
165                 public override void Close()
166                 {
167                         stream.Close();
168                 }
169
170                 public override void SetLength(long length)
171                 {
172                         stream.SetLength( length );
173                 }
174
175                 public override void Write(byte[] buffer, int offset, int count)
176                 {
177                         stream.Write( buffer, offset, count );
178                 }
179
180                 public override long Seek( long offset, SeekOrigin origin )
181                 {
182                         return stream.Seek( offset, origin );
183                 }
184         }
185 }
186
187