// created on 1/6/2002 at 22:27 // Npgsql.PGUtil.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.IO; using System.Text; using System.Net.Sockets; using System.Net; using System.Resources; namespace Npgsql { internal struct ProtocolVersion { public const Int32 Version2 = 131072; public const Int32 Version3 = 196608; } internal enum FormatCode: short { Text = 0, Binary = 1 } /// /// This class provides many util methods to handle /// reading and writing of PostgreSQL protocol messages. /// /// [FIXME] Does this name fully represent the class responsability? /// Should it be abstract or with a private constructor to prevent /// creating instances? // internal sealed class PGUtil { // Logging related values private static readonly String CLASSNAME = "PGUtil"; private static ResourceManager resman = new ResourceManager(typeof(PGUtil)); /// /// This method gets a C NULL terminated string from the network stream. /// It keeps reading a byte in each time until a NULL byte is returned. /// It returns the resultant string of bytes read. /// This string is sent from backend. /// public static String ReadString(Stream network_stream, Encoding encoding) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadString"); // [FIXME] Is 512 enough? Byte[] buffer = new Byte[512]; Byte b; Int16 counter = 0; // [FIXME] Is this cast always safe? b = (Byte)network_stream.ReadByte(); while(b != 0) { buffer[counter] = b; counter++; b = (Byte)network_stream.ReadByte(); } String string_read = encoding.GetString(buffer, 0, counter); NpgsqlEventLog.LogMsg(resman, "Log_StringRead", LogLevel.Debug, string_read); return string_read; } /// /// This method writes a C NULL terminated string to the network stream. /// It appends a NULL terminator to the end of the String. /// public static void WriteString(String the_string, Stream network_stream, Encoding encoding) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "WriteString"); network_stream.Write(encoding.GetBytes(the_string + '\x00') , 0, encoding.GetByteCount(the_string) + 1); } /// /// This method writes a C NULL terminated string limited in length to the /// backend server. /// It pads the string with null bytes to the size specified. /// public static void WriteLimString(String the_string, Int32 n, Stream network_stream, Encoding encoding) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "WriteLimString"); // [FIXME] Parameters should be validated. And what about strings // larger than or equal to n? // Pad the string to the specified value. String string_padded = the_string.PadRight(n, '\x00'); network_stream.Write(encoding.GetBytes(string_padded), 0, n); } public static void CheckedStreamRead(Stream stream, Byte[] buffer, Int32 offset, Int32 size) { Int32 bytes_from_stream = 0; Int32 total_bytes_read = 0; do { bytes_from_stream = stream.Read(buffer, offset + total_bytes_read, size); total_bytes_read += bytes_from_stream; size -= bytes_from_stream; } while(size > 0); } public static void WriteInt32(Stream stream, Int32 value) { stream.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)), 0, 4); } public static Int32 ReadInt32(Stream stream, Byte[] buffer) { CheckedStreamRead(stream, buffer, 0, 4); return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0)); } public static void WriteInt16(Stream stream, Int16 value) { stream.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)), 0, 2); } public static Int16 ReadInt16(Stream stream, Byte[] buffer) { CheckedStreamRead(stream, buffer, 0, 2); return IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, 0)); } /*public static void WriteQueryToStream( String query, Stream stream, Encoding encoding ) { NpgsqlEventLog.LogMsg( CLASSNAME + query, LogLevel.Debug ); // Send the query to server. // Write the byte 'Q' to identify a query message. stream.WriteByte((Byte)'Q'); // Write the query. In this case it is the CommandText text. // It is a string terminated by a C NULL character. stream.Write(encoding.GetBytes(query + '\x00') , 0, query.Length + 1); // Send bytes. stream.Flush(); } public static Int32 ProtocolVersionMajor(Int32 protocolVersion) { return (protocolVersion >> 16) & 0xffff; } public static Int32 ProtocolVersionMinor(Int32 protocolVersion) { return protocolVersion & 0xffff; }*/ } }