[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / Mono.Data.Tds / Mono.Data.Tds.Protocol / TdsComm.cs
blob8e19ec9af9649c6f84577ae83c41fbacb08fb64a
1 //
2 // Mono.Data.Tds.Protocol.TdsComm.cs
3 //
4 // Author:
5 // Tim Coleman (tim@timcoleman.com)
6 // Gonzalo Paniagua Javier (gonzalo@novell.com)
7 //
8 // Copyright (C) 2002 Tim Coleman
9 // Copyright (c) 2009 Novell, Inc.
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
34 using System.IO;
35 using System.Net;
36 using System.Net.Sockets;
37 using System.Text;
38 using System.Threading;
40 namespace Mono.Data.Tds.Protocol {
41 internal sealed class TdsComm
43 #region Fields
45 NetworkStream stream;
46 int packetSize;
47 TdsPacketType packetType = TdsPacketType.None;
48 bool connReset;
49 Encoding encoder;
51 string dataSource;
52 int commandTimeout;
54 byte[] outBuffer;
55 int outBufferLength;
56 int nextOutBufferIndex = 0;
57 bool lsb;
59 byte[] inBuffer;
60 int inBufferLength;
61 int inBufferIndex = 0;
63 static int headerLength = 8;
65 byte[] tmpBuf = new byte[8];
66 byte[] resBuffer = new byte[256];
68 int packetsSent;
69 int packetsReceived = 0;
71 Socket socket;
72 TdsVersion tdsVersion;
74 #endregion // Fields
76 #region Constructors
78 public TdsComm (string dataSource, int port, int packetSize, int timeout, TdsVersion tdsVersion)
80 this.packetSize = packetSize;
81 this.tdsVersion = tdsVersion;
82 this.dataSource = dataSource;
84 outBuffer = new byte[packetSize];
85 inBuffer = new byte[packetSize];
87 outBufferLength = packetSize;
88 inBufferLength = packetSize;
90 lsb = true;
92 IPEndPoint endPoint;
93 bool have_exception = false;
95 try {
96 IPAddress ip;
97 if(IPAddress.TryParse(this.dataSource, out ip)) {
98 endPoint = new IPEndPoint(ip, port);
99 } else {
100 IPHostEntry hostEntry = Dns.GetHostEntry (this.dataSource);
101 endPoint = new IPEndPoint(hostEntry.AddressList [0], port);
103 } catch (SocketException e) {
104 throw new TdsInternalException ("Server does not exist or connection refused.", e);
107 try {
108 socket = new Socket (endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
109 IAsyncResult ares = socket.BeginConnect (endPoint, null, null);
110 int timeout_ms = timeout * 1000;
111 if (timeout > 0 && !ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne (timeout_ms, false))
112 throw Tds.CreateTimeoutException (dataSource, "Open()");
113 socket.EndConnect (ares);
114 try {
115 // MS sets these socket option
116 socket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
117 } catch (SocketException) {
118 // Some platform may throw an exception, so
119 // eat all socket exception, yeaowww!
122 try {
123 socket.NoDelay = true;
124 socket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout, timeout_ms);
125 socket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, timeout_ms);
126 } catch {
127 // Ignore exceptions here for systems that do not support these options.
129 // Let the stream own the socket and take the pleasure of closing it
130 stream = new NetworkStream (socket, true);
131 } catch (SocketException e) {
132 have_exception = true;
133 throw new TdsInternalException ("Server does not exist or connection refused.", e);
134 } catch (Exception) {
135 have_exception = true;
136 throw;
137 } finally {
138 if (have_exception && socket != null) {
139 try {
140 Socket s = socket;
141 socket = null;
142 s.Close ();
143 } catch {}
146 if (!socket.Connected)
147 throw new TdsInternalException ("Server does not exist or connection refused.", null);
148 packetsSent = 1;
151 #endregion // Constructors
153 #region Properties
155 public int CommandTimeout {
156 get { return commandTimeout; }
157 set { commandTimeout = value; }
160 internal Encoding Encoder {
161 get { return encoder; }
162 set { encoder = value; }
165 public int PacketSize {
166 get { return packetSize; }
167 set { packetSize = value; }
170 public bool TdsByteOrder {
171 get { return !lsb; }
172 set { lsb = !value; }
174 #endregion // Properties
176 #region Methods
178 public byte[] Swap(byte[] toswap) {
179 byte[] ret = new byte[toswap.Length];
180 for(int i = 0; i < toswap.Length; i++)
181 ret [toswap.Length - i - 1] = toswap[i];
183 return ret;
186 public void SendIfFull ()
188 if (nextOutBufferIndex == outBufferLength) {
189 SendPhysicalPacket (false);
190 nextOutBufferIndex = headerLength;
194 public void SendIfFull (int reserve)
196 if (nextOutBufferIndex+reserve > outBufferLength) {
197 SendPhysicalPacket (false);
198 nextOutBufferIndex = headerLength;
202 public void Append (object o)
204 if (o == null || o == DBNull.Value) {
205 Append ((byte)0);
206 return ;
209 switch (Type.GetTypeCode (o.GetType ())) {
210 case TypeCode.Byte :
211 Append ((byte) o);
212 return;
213 case TypeCode.Boolean:
214 if ((bool)o == true)
215 Append ((byte)1);
216 else
217 Append ((byte)0);
218 return;
219 case TypeCode.Object :
220 if (o is byte[])
221 Append ((byte[]) o);
222 else if (o is Guid)
223 Append (((Guid) o).ToByteArray ());
224 else break;
225 return;
226 case TypeCode.Int16 :
227 Append ((short) o);
228 return;
229 case TypeCode.Int32 :
230 Append ((int) o);
231 return;
232 case TypeCode.String :
233 Append ((string) o);
234 return;
235 case TypeCode.Double :
236 Append ((double) o);
237 return;
238 case TypeCode.Single :
239 Append ((float) o);
240 return;
241 case TypeCode.Int64 :
242 Append ((long) o);
243 return;
244 case TypeCode.Decimal:
245 Append ((decimal) o, 17);
246 return;
247 case TypeCode.DateTime:
248 Append ((DateTime) o, 8);
249 return;
251 throw new InvalidOperationException (String.Format ("Object Type :{0} , not being appended", o.GetType ()));
254 public void Append (byte b)
256 SendIfFull ();
257 Store (nextOutBufferIndex, b);
258 nextOutBufferIndex++;
261 public void Append (DateTime t, int bytes)
263 DateTime epoch = new DateTime (1900,1,1);
265 TimeSpan span = t - epoch; //new TimeSpan (t.Ticks - epoch.Ticks);
266 int days, hours, minutes, secs;
267 long msecs;
268 int val = 0;
270 days = span.Days;
271 hours = span.Hours;
272 minutes = span.Minutes;
273 secs = span.Seconds;
274 msecs = span.Milliseconds;
276 if (epoch > t) {
277 // If t.Hour/Min/Sec/MSec is > 0, days points to the next day and hence,
278 // we move it back by a day - otherwise, no change
279 days = (t.Hour > 0 || t.Minute > 0 || t.Second > 0 || t.Millisecond > 0) ? days-1: days;
280 hours = t.Hour;
281 minutes = t.Minute;
282 secs = t.Second;
283 msecs = t.Millisecond;
286 SendIfFull (bytes);
287 if (bytes == 8) {
288 long ms = (hours * 3600 + minutes * 60 + secs)*1000L + (long)msecs;
289 val = (int) ((ms*300)/1000);
290 AppendInternal ((int) days);
291 AppendInternal ((int) val);
292 } else if (bytes ==4) {
293 val = span.Hours * 60 + span.Minutes;
294 AppendInternal ((short) days);
295 AppendInternal ((short) val);
296 } else {
297 throw new Exception ("Invalid No of bytes");
301 public void Append (byte[] b)
303 Append (b, b.Length, (byte) 0);
307 public void Append (byte[] b, int len, byte pad)
309 int bufBytesToCopy = System.Math.Min (b.Length, len);
310 int padBytesToCopy = len - bufBytesToCopy;
311 int bufPos = 0;
313 /* copy out of our input buffer in the largest chunks possible *
314 * at a time. limited only by the buffer size for our outgoing *
315 * packets. */
317 while (bufBytesToCopy > 0)
319 SendIfFull ();
321 int availBytes = outBufferLength - nextOutBufferIndex;
322 int bufSize = System.Math.Min (availBytes, bufBytesToCopy);
324 Buffer.BlockCopy (b, bufPos, outBuffer, nextOutBufferIndex, bufSize);
326 nextOutBufferIndex += bufSize;
327 bufBytesToCopy -= bufSize;
328 bufPos += bufSize;
331 while (padBytesToCopy > 0)
333 SendIfFull ();
335 int availBytes = outBufferLength - nextOutBufferIndex;
336 int bufSize = System.Math.Min (availBytes, padBytesToCopy);
338 for (int i = 0; i < bufSize; i++)
339 outBuffer [nextOutBufferIndex++] = pad;
341 padBytesToCopy -= bufSize;
345 private void AppendInternal (short s)
347 if (!lsb) {
348 outBuffer[nextOutBufferIndex++] = (byte) (((byte) (s >> 8)) & 0xff);
349 outBuffer[nextOutBufferIndex++] = (byte) ((byte) (s & 0xff));
350 } else {
351 outBuffer[nextOutBufferIndex++] = (byte) ((byte) (s & 0xff));
352 outBuffer[nextOutBufferIndex++] = (byte) (((byte) (s >> 8)) & 0xff);
356 public void Append (short s)
358 SendIfFull (sizeof (short));
359 AppendInternal (s);
362 public void Append (ushort s)
364 SendIfFull (sizeof (short));
365 AppendInternal ((short) s);
368 private void AppendInternal (int i)
370 if (!lsb) {
371 AppendInternal ((short) (((short) (i >> 16)) & 0xffff));
372 AppendInternal ((short) ((short) (i & 0xffff)));
373 } else {
374 AppendInternal ((short) ((short) (i & 0xffff)));
375 AppendInternal ((short) (((short) (i >> 16)) & 0xffff));
379 public void Append (int i)
381 SendIfFull (sizeof (int));
382 AppendInternal (i);
385 public void Append (string s)
387 if (tdsVersion < TdsVersion.tds70) {
388 Append (encoder.GetBytes (s));
389 } else {
390 for (int i = 0; i < s.Length; i++) {
391 SendIfFull (sizeof(short));
392 AppendInternal ((short)s[i]);
397 public void AppendNonUnicode (string s)
399 if (tdsVersion < TdsVersion.tds70) {
400 Append (encoder.GetBytes (s));
401 } else {
402 for (int i = 0; i < s.Length; i++) {
403 SendIfFull (sizeof(byte));
404 Append ((byte)s[i]);
409 // Appends with padding
410 public byte[] Append (string s, int len, byte pad)
412 if (s == null)
413 return new byte[0];
415 byte[] result = encoder.GetBytes (s);
416 Append (result, len, pad);
417 return result;
420 public void Append (double value)
422 if (!lsb)
423 Append (Swap (BitConverter.GetBytes (value)), sizeof(double), (byte)0);
424 else
425 Append (BitConverter.GetBytes (value), sizeof(double), (byte)0);
428 public void Append (float value)
430 if (!lsb)
431 Append (Swap (BitConverter.GetBytes (value)), sizeof(float), (byte)0);
432 else
433 Append (BitConverter.GetBytes (value), sizeof(float), (byte)0);
436 public void Append (long l)
438 SendIfFull (sizeof (long));
439 if (!lsb) {
440 AppendInternal ((int) (((int) (l >> 32)) & 0xffffffff));
441 AppendInternal ((int) ((int) (l & 0xffffffff)));
442 } else {
443 AppendInternal ((int) ((int) (l & 0xffffffff)));
444 AppendInternal ((int) (((int) (l >> 32)) & 0xffffffff));
448 public void Append (decimal d, int bytes)
450 int[] arr = Decimal.GetBits (d);
451 byte sign = (d > 0 ? (byte)1 : (byte)0);
452 SendIfFull (bytes);
453 Append (sign);
454 AppendInternal (arr[0]);
455 AppendInternal (arr[1]);
456 AppendInternal (arr[2]);
457 AppendInternal ((int)0);
460 public void AppendMoney (decimal d, int size)
462 // The method for this is to simply multiply by 10^4 and then stuff
463 // the value into either a int or long value depending on the size
465 SendIfFull (size);
467 decimal tmpD = Decimal.Multiply(d, 10000m);
468 if (size > 4) {
469 long longValue = Decimal.ToInt64(tmpD);
471 int significantHalf = (int) ((longValue >> 32) & 0xffffffff);
472 int lessSignificantHalf = (int)(longValue & 0xffffffff);
474 AppendInternal (significantHalf);
475 AppendInternal (lessSignificantHalf);
476 } else {
477 int intValue = Decimal.ToInt32(tmpD);
478 AppendInternal (intValue);
482 // A method for decimals that properly scales the decimal out before putting on the TDS steam
483 public void AppendDecimal (decimal d, int bytes, int scale)
485 decimal tmpD1 = Decimal.Multiply (d, (decimal)System.Math.Pow (10.0, scale));
486 decimal tmpD2 = System.Math.Abs(Decimal.Truncate (tmpD1));
488 int[] arr = Decimal.GetBits (tmpD2);
489 byte sign = (d > 0 ? (byte)1 : (byte)0);
490 SendIfFull (bytes);
491 Append (sign);
492 AppendInternal (arr[0]);
493 AppendInternal (arr[1]);
494 AppendInternal (arr[2]);
495 AppendInternal ((int)0);
498 public void Close ()
500 if (stream == null)
501 return;
503 connReset = false;
504 socket = null;
505 try {
506 stream.Close ();
507 } catch {
509 stream = null;
512 public bool IsConnected ()
514 return socket != null && socket.Connected && !(socket.Poll (0, SelectMode.SelectRead) && socket.Available == 0);
517 public byte GetByte ()
519 byte result;
521 if (inBufferIndex >= inBufferLength) {
522 // out of data, read another physical packet.
523 GetPhysicalPacket ();
525 result = inBuffer[inBufferIndex++];
526 return result;
529 public byte[] GetBytes (int len, bool exclusiveBuffer)
531 byte[] result = null;
532 int i;
534 // Do not keep an internal result buffer larger than 16k.
535 // This would unnecessarily use up memory.
536 if (exclusiveBuffer || len > 16384)
537 result = new byte[len];
538 else
540 if (resBuffer.Length < len)
541 resBuffer = new byte[len];
542 result = resBuffer;
545 for (i = 0; i<len; )
547 if (inBufferIndex >= inBufferLength)
548 GetPhysicalPacket ();
550 int avail = inBufferLength - inBufferIndex;
551 avail = avail>len-i ? len-i : avail;
553 Buffer.BlockCopy (inBuffer, inBufferIndex, result, i, avail);
554 i += avail;
555 inBufferIndex += avail;
558 return result;
561 public string GetString (int len, Encoding enc)
563 if (tdsVersion >= TdsVersion.tds70)
564 return GetString (len, true, null);
565 else
566 return GetString (len, false, null);
569 public string GetString (int len)
571 if (tdsVersion >= TdsVersion.tds70)
572 return GetString (len, true);
573 else
574 return GetString (len, false);
577 public string GetString (int len, bool wide, Encoding enc)
579 if (wide) {
580 char[] chars = new char[len];
581 for (int i = 0; i < len; ++i) {
582 int lo = ((byte) GetByte ()) & 0xFF;
583 int hi = ((byte) GetByte ()) & 0xFF;
584 chars[i] = (char) (lo | ( hi << 8));
586 return new String (chars);
588 else {
589 byte[] result = new byte[len];
590 Array.Copy (GetBytes (len, false), result, len);
591 // Use the passed encoder, if available
592 if (enc != null)
593 return (enc.GetString (result));
594 else
595 return (encoder.GetString (result));
599 public string GetString (int len, bool wide)
601 return GetString (len, wide, null);
604 public int GetNetShort ()
606 byte[] tmp = new byte[2];
607 tmp[0] = GetByte ();
608 tmp[1] = GetByte ();
609 return Ntohs (tmp, 0);
612 public short GetTdsShort ()
614 byte[] input = new byte[2];
616 for (int i = 0; i < 2; i += 1)
617 input[i] = GetByte ();
618 if(!BitConverter.IsLittleEndian)
619 return (BitConverter.ToInt16 (Swap (input), 0));
620 else
621 return (BitConverter.ToInt16 (input, 0));
625 public int GetTdsInt ()
627 byte[] input = new byte[4];
628 for (int i = 0; i < 4; i += 1) {
629 input[i] = GetByte ();
631 if(!BitConverter.IsLittleEndian)
632 return (BitConverter.ToInt32 (Swap (input), 0));
633 else
634 return (BitConverter.ToInt32 (input, 0));
637 public long GetTdsInt64 ()
639 byte[] input = new byte[8];
640 for (int i = 0; i < 8; i += 1)
641 input[i] = GetByte ();
642 if(!BitConverter.IsLittleEndian)
643 return (BitConverter.ToInt64 (Swap (input), 0));
644 else
645 return (BitConverter.ToInt64 (input, 0));
648 private void GetPhysicalPacket ()
650 int dataLength = GetPhysicalPacketHeader ();
651 GetPhysicalPacketData (dataLength);
654 int Read (byte [] buffer, int offset, int count)
656 try {
657 return stream.Read (buffer, offset, count);
658 } catch {
659 socket = null;
660 stream.Close ();
661 throw;
665 private int GetPhysicalPacketHeader ()
667 int nread = 0;
669 int n;
670 // read the header
671 while (nread < 8) {
672 n = Read (tmpBuf, nread, 8 - nread);
673 if (n <= 0) {
674 socket = null;
675 stream.Close ();
676 throw new IOException (n == 0 ? "Connection lost" : "Connection error");
678 nread += n;
681 TdsPacketType packetType = (TdsPacketType) tmpBuf[0];
682 if (packetType != TdsPacketType.Logon && packetType != TdsPacketType.Query && packetType != TdsPacketType.Reply)
684 throw new Exception (String.Format ("Unknown packet type {0}", tmpBuf[0]));
687 // figure out how many bytes are remaining in this packet.
688 int len = Ntohs (tmpBuf, 2) - 8;
689 if (len >= inBuffer.Length)
690 inBuffer = new byte[len];
692 if (len < 0) {
693 throw new Exception (String.Format ("Confused by a length of {0}", len));
696 return len;
700 private void GetPhysicalPacketData (int length)
702 // now get the data
703 int nread = 0;
704 int n;
706 while (nread < length) {
707 n = Read (inBuffer, nread, length - nread);
708 if (n <= 0) {
709 socket = null;
710 stream.Close ();
711 throw new IOException (n == 0 ? "Connection lost" : "Connection error");
713 nread += n;
716 packetsReceived++;
718 // adjust the bookkeeping info about the incoming buffer
719 inBufferLength = length;
720 inBufferIndex = 0;
724 private static int Ntohs (byte[] buf, int offset)
726 int lo = ((int) buf[offset + 1] & 0xff);
727 int hi = (((int) buf[offset] & 0xff ) << 8);
729 return hi | lo;
730 // return an int since we really want an _unsigned_
733 public byte Peek ()
735 // If out of data, read another physical packet.
736 if (inBufferIndex >= inBufferLength)
737 GetPhysicalPacket ();
739 return inBuffer[inBufferIndex];
742 public bool Poll (int seconds, SelectMode selectMode)
744 return Poll (socket, seconds, selectMode);
747 private bool Poll (Socket s, int seconds, SelectMode selectMode)
749 long uSeconds = seconds * 1000000;
750 bool bState = false;
752 while (uSeconds > (long) Int32.MaxValue) {
753 bState = s.Poll (Int32.MaxValue, selectMode);
754 if (bState)
755 return true;
756 uSeconds -= Int32.MaxValue;
758 return s.Poll ((int) uSeconds, selectMode);
761 internal void ResizeOutBuf (int newSize)
763 if (newSize != outBufferLength) {
764 byte[] newBuf = new byte [newSize];
765 Buffer.BlockCopy (outBuffer, 0, newBuf, 0, newSize);
766 outBufferLength = newSize;
767 outBuffer = newBuf;
771 public bool ResetConnection {
772 get { return connReset; }
773 set { connReset = value; }
776 public void SendPacket ()
778 // Reset connection flag is only valid for SQLBatch/RPC/DTC messages
779 if (packetType != TdsPacketType.Query && packetType != TdsPacketType.RPC)
780 connReset = false;
782 SendPhysicalPacket (true);
783 nextOutBufferIndex = 0;
784 packetType = TdsPacketType.None;
785 // Reset connection-reset flag to false - as any exception would anyway close
786 // the whole connection
787 connReset = false;
788 packetsSent = 1;
791 private void SendPhysicalPacket (bool isLastSegment)
793 if (nextOutBufferIndex > headerLength || packetType == TdsPacketType.Cancel) {
794 byte status = (byte) ((isLastSegment ? 0x01 : 0x00) | (connReset ? 0x08 : 0x00));
796 // packet type
797 Store (0, (byte) packetType);
798 Store (1, status);
799 Store (2, (short) nextOutBufferIndex );
800 Store (4, (byte) 0);
801 Store (5, (byte) 0);
802 if (tdsVersion >= TdsVersion.tds70)
803 Store (6, (byte) packetsSent);
804 else
805 Store (6, (byte) 0);
806 Store (7, (byte) 0);
808 stream.Write (outBuffer, 0, nextOutBufferIndex);
809 stream.Flush ();
811 if (!isLastSegment && packetType == TdsPacketType.Bulk)
813 System.Threading.Thread.Sleep (100);
816 packetsSent++;
820 public void Skip (long i)
822 for ( ; i > 0; i--)
823 GetByte ();
826 public void StartPacket (TdsPacketType type)
828 if (type != TdsPacketType.Cancel && inBufferIndex != inBufferLength)
829 inBufferIndex = inBufferLength;
831 packetType = type;
832 nextOutBufferIndex = headerLength;
835 private void Store (int index, byte value)
837 outBuffer[index] = value;
840 private void Store (int index, short value)
842 outBuffer[index] = (byte) (((byte) (value >> 8)) & 0xff);
843 outBuffer[index + 1] = (byte) (((byte) (value >> 0)) & 0xff);
846 #endregion // Methods
847 #region Async Methods
849 public IAsyncResult BeginReadPacket (AsyncCallback callback, object stateObject)
851 TdsAsyncResult ar = new TdsAsyncResult (callback, stateObject);
853 stream.BeginRead (tmpBuf, 0, 8, new AsyncCallback(OnReadPacketCallback), ar);
854 return ar;
857 /// <returns>Packet size in bytes</returns>
858 public int EndReadPacket (IAsyncResult ar)
860 if (!ar.IsCompleted)
861 ar.AsyncWaitHandle.WaitOne ();
862 return (int) ((TdsAsyncResult) ar).ReturnValue;
866 public void OnReadPacketCallback (IAsyncResult socketAsyncResult)
868 TdsAsyncResult ar = (TdsAsyncResult) socketAsyncResult.AsyncState;
869 int nread = stream.EndRead (socketAsyncResult);
870 int n;
872 while (nread < 8) {
873 n = Read (tmpBuf, nread, 8 - nread);
874 if (n <= 0) {
875 socket = null;
876 stream.Close ();
877 throw new IOException (n == 0 ? "Connection lost" : "Connection error");
879 nread += n;
882 TdsPacketType packetType = (TdsPacketType) tmpBuf[0];
883 if (packetType != TdsPacketType.Logon && packetType != TdsPacketType.Query && packetType != TdsPacketType.Reply)
885 throw new Exception (String.Format ("Unknown packet type {0}", tmpBuf[0]));
888 // figure out how many bytes are remaining in this packet.
889 int len = Ntohs (tmpBuf, 2) - 8;
891 if (len >= inBuffer.Length)
892 inBuffer = new byte[len];
894 if (len < 0) {
895 throw new Exception (String.Format ("Confused by a length of {0}", len));
898 GetPhysicalPacketData (len);
899 int value = len + 8;
900 ar.ReturnValue = ((object)value); // packet size
901 ar.MarkComplete ();
904 #endregion // Async Methods