⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ber.cs

📁 用C#写的一个OPC CLIENT的工具
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Text;

// ASN.1 BER encoding library by Malcolm Crowe at the University of Paisley
// See http://cis.paisley.ac.uk/crow-ci0
// This is version 0 of the library, please advise me about any bugs
// mailto:malcolm.crowe@paisley.ac.uk

// Restrictions: It is assumed that no encoding has a length greater than 2^31-1.
// UNIVERSAL TYPES
// Some of the more unusual Universal encodings are supported but not fully implemented
// Should you require these types, as an alternative to changing this code
// you can catch the exception that is thrown and examine the contents yourself.
// APPLICATION TYPES
// If you want to handle Application types systematically, you can derive a class from
// Universal, and provide the Creator and Creators methods for your class
// You will see an example of how to do this in the Snmplib
// CONTEXT AND PRIVATE TYPES
// Ad hoc coding can be used for these, as an alterative to derive a class as above.

namespace X690 // all references here are to ITU-X.690-12/97
{
	public class Integer // This namespace has its own concept of Integer
	{
		public byte[] octVal = null;
		public Integer(byte[] b)
		{
			octVal = b;
		}
		public Integer(int iVal)
		{
			if (iVal>=-127 && iVal<=127)
			{
				octVal = new byte[1];
				octVal[0] = (byte)iVal;
			} 
			else 
			{
				ArrayList v = new ArrayList();
				int n = iVal;
				while (n!=0 && n!=-1)
				{
					v.Add((byte)(n&0xff));
					n >>= 8;
				}
				octVal = new byte[v.Count];
				int len = 0;
				for (int j=v.Count-1;j>=0;j--)
					octVal[len++] = (byte)v[j];
			}
		}
		public Integer(long i64Val)
		{
			if (i64Val>=-127 && i64Val<=127)
			{
				octVal = new byte[1];
				octVal[0] = (byte)i64Val;
			} 
			else 
			{
				ArrayList v = new ArrayList();
				System.Int64 n = i64Val;
				while (n!=0 && n!=-1)
				{
					v.Add((byte)(n&0xff));
					n >>= 8;
				}
				octVal = new byte[v.Count];
				int len = 0;
				for (int j=v.Count-1;j>=0;j--)
					octVal[len++] = (byte)v[j];
			}
		}
		static public implicit operator int(Integer x)
		{
			if (x.octVal.Length>4)
					throw(new Exception("truncation error for 32-bit integer coding"));
			int	iVal = 0;
			for (int j=0;j<x.octVal.Length;j++)
					iVal = (iVal<<8)|(int)x.octVal[j];
			return iVal;
		}
		static public implicit operator long(Integer x)
		{
			if (x.octVal.Length>8)
				throw(new Exception("truncation error for 64-bit integer coding"));
			long i64Val = 0;
			for (int j=0;j<x.octVal.Length;j++)
				i64Val = (i64Val<<8)|(int)x.octVal[j];
			return i64Val;
		}
	}
	public class Real
	{
		public byte[] octVal = null;
		public Real(byte[] b)
		{
			octVal = b; 
		}
		public Real(double b)
		{
			if (b==0.0) 
			{
				octVal = new byte[0];
				return;
			}
			string s = b.ToString("E"); // hope this is acceptable..
			octVal = new byte[s.Length+1];
			octVal[0] = 0x0;
			new ASCIIEncoding().GetBytes(s,0,s.Length,octVal,1);
		}
		static public implicit operator double(Real x)
		{
			if (x.octVal.Length==0)
				return 0.0;
			if ((x.octVal[0]&0x80)!=0) // 8.5.5 binary encoding
			{
				byte c = x.octVal[0];
				int s = ((c&0x40)!=0)?-1:1;
				int t = c&0x30;
				int b = (t==0)?2:(t==1)?8:16;
				if (t==3)
					throw(new Exception("X690:8.5.5.2 reserved encoding"));
				int f = (c&0xc)>>2;
				f = 1<<f;
				int p = 1;
				long e = 0;
				switch (c&0x3) 
				{
					case 0: e = x.octVal[p++]; break;
					case 1:	e = ((int)x.octVal[p++])<<8; e+= x.octVal[p++]; break;
					case 2: e = ((int)x.octVal[p++])<<16;
						e += ((int)x.octVal[p++])<<8; e+= x.octVal[p++]; break;
					case 3: int h = x.octVal[p++];
						byte[] g = new byte[h];
						for (int j=0;j<h;j++)
							g[j]=x.octVal[p++];
						e = new Integer(g); 
						break;
				}
				byte[] m = new byte[x.octVal.Length-p+1];
				for (int k=0;p<x.octVal.Length;k++,p++)
					m[k]=x.octVal[p];
				long n = new Integer(m);
				return ((double)(s*n*f))*Math.Pow((double)b,(double)e);
			} 
			else if ((x.octVal[0]&0x40)==0) // 8.5.6 decimal encoding
				return double.Parse(new ASCIIEncoding().GetString(x.octVal,0,x.octVal.Length));
			else // 8.5.7 special real encoding
				switch (x.octVal[0])
				{
					case 0x40: return double.PositiveInfinity;
					case 0x41: return double.NegativeInfinity;
					default: throw(new Exception("X690:8.5.7 reserved encoding"));
				}
		}
	}
	public abstract class BER
	{
		// internal representation of the encoding
		public BERtag type; // BERtag class does encoding/decoding
		protected uint len; // GetUInt/PutUInt for external representation
		protected object val = null;
		// safety field
		protected bool e; // encode if true, decode if false
		// external representation of the contents octets
		protected byte[] b;
		public bool Encode { get { return e; }}
		protected byte ReadByte(Stream s)
		{
			int n = s.ReadByte();
			if (n==-1)
				throw(new Exception("BER end of file"));
			return (byte)n;
		}
		protected void WriteByte(Stream s,byte b)
		{
			s.WriteByte(b);
		}
	}
	public enum BERtype  // 8.1.2.2
	{
		Universal=0, Application=1, Context=2, Private=3
	}
	public enum UniversalType
	{
		EndMarker = 0x00,
		Boolean = 0x01,
		Integer=0x02, // X690.Integer
		BitString=0x03,  // BitSet
		OctetString=0x04, // string
		Null=0x05,
		ObjectIdentifier=0x06, // uint[]
		ObjectDescriptor=0x7,
		ExternalInstance=0x8,
		Real=0x9,  // X690.Real
		Enumerated=0xa,
		EmbeddedPDV=0xb,
		UTF8String=0xc,
		RelativeOID=0xd,
		Reserved1=0xe,
		Reserved2=0xf,
		Sequence=0x10,
		Set=0x11,
		NumericString=0x12,
		PrintableString=0x13,
		T61String=0x14,
		VideoTextString=0x15,
		IA5String=0x16,
		UTCTime=0x17,
		GeneralizedTime=0x18,
		GrahicString=0x19,
		VisibleString=0x1a,
		GeneralString=0x1b,
		UniversalString=0x1c,
		CharacterString=0x1d,
		BMPString=0x1e
	}
	public class BERtag : BER
	{
		// Internal representation of Identifier octets 8.1.2.3
		public BERtype atp; 
		public bool comp;
		public ulong tag;
		public BERtag() { atp=BERtype.Universal; comp=false; tag=0; } // EndMarker
		public BERtag(BERtype a,bool c, ulong t) { atp=a; comp=c; tag=t; }
		public BERtag(UniversalType b) : this((byte)b) {}
		public BERtag(byte b) 
		{
			// decoding 8.1.2.4.3 for small tag values
			atp = (BERtype)(((uint)b&0xc0)>>6);
			comp = ((b&0x20)!=0);
			tag = (ulong)(b&0x1f);
			if (tag==0x1f)
				throw(new Exception("BER bad byte tag"));
		}
		public BERtag(Stream s) 
		{
			// decoding 8.1.2.4.3
			byte b = ReadByte(s);
			atp = (BERtype)((b&0xc0)>>6);
			comp = ((b&0x20)!=0);
			tag = (ulong)(b&0x1f);
			if ((b&0x1f)==0x1f) 
				tag = GetBigTag(s);
		}
		public void Send(Stream s)
		{
			// encoding 8.1.2.4.3
			byte b = (byte)(((uint)atp)<<6 | (comp?0x20:0));
			if (tag<31) 
			{
				b |= (byte)tag;
				s.WriteByte(b);
				return;
			}
			b |=31;
			s.WriteByte(b);
			PutBigTag(s,tag);
		}
		public byte ToByte()
		{
			byte b = (byte)(((uint)atp<<6) | (comp?0x20:0));
			if (tag>=31) 
				throw(new Exception("BERtag out of range for convert to byte"));
			b |= (byte)tag;
			return b;
		}
		public bool isEndMarker
		{
			get { return (atp==BERtype.Universal && !comp && tag==0); }
		}
		public ulong GetBigTag(Stream s)
		{
			ulong r = 0;
			byte x = ReadByte(s);
			do 
			{
				r = (r<<7)+(ulong)(x&0x7f);
			} while ((x&0x80)!=0);
			return r;
		}
		public void PutBigTag(Stream s,ulong n)
		{
			byte[] c = new byte[16];
			int j=0;
			while (n>0)
			{
				c[j++] = (byte)(n&0x7f);
				n = n>>7;
			}
			while (j>0) 
			{
				byte x = c[--j];
				if (j>0)
					x |= 0x80;
				WriteByte(s,x);
			}
		}
		public ulong ExtLength() // calculate length required for identifier octets
		{
			if (tag<31)
				return 1;
			ulong a = tag;
			ulong j = 1;
			while (a>0) 
			{
				j++;
				a = a>>7;
			}
			return j;
		}
		public override string ToString()
		{
			if (atp==BERtype.Universal && !comp)
				return ((UniversalType)tag).ToString().ToUpper();
			return "[" + atp.ToString().ToUpper()+" "+(comp?"SEQUENCE ":"")+tag+"]";
		}
	}
	// The following class provides for the Universal encodings and the encodings needed for SNMP
	// For application or context-specific encodings, derive a class from this and override the
	// Evaluate method, which creates an object called val based on the contents in byte[] b.
	// Evaluate takes a single uint parameter which is the number of bytes to use in b.
	public class Universal : BER 
	{
		// override these two functions in any subclass of Universal so that SEQUENCES work correctly
		protected virtual BERtag CreateTag(Stream s) { return new BERtag(s); }
		protected virtual Universal Creator(Stream s) { return new Universal(s); }
		protected virtual Universal[] Creators(int n) { return new Universal[n]; }
		protected Universal() {}
		public static Universal Null 
		{
			get 
			{
				return new Universal(new BERtag(UniversalType.Null),new Universal[0]); 
			}
		}
		public Universal(bool x) // 8.2
		{
			type = new BERtag(UniversalType.Boolean);
			e = true;
			len = 1;
			b = new byte[1];
			b[0] = (byte)(x?0xff:0);
		}
		public Universal(int n) // 8.3
		{
			type = new BERtag(UniversalType.Integer);
			e = true;
			b = new Integer(n).octVal;
			len = (uint)b.Length;
		}
		public Universal(double d)
		{
			type = new BERtag(UniversalType.Real);
			e = true;
			b = new Real(d).octVal;
			len = (uint)b.Length;
		}
		public Universal(BitSet a)
		{
			// encoding 8.6.2
			type = new BERtag(UniversalType.BitString);
			e = true;
			int n = (a.Length+7)/8;
			byte r = (byte)(8-a.Length%8);
			b = new byte[n+1];
			len = 0;
			b[len++] = r;
			int k = 24;
			int i = 0;
			for (int j=0;j<n;j++) 
			{
				b[len++] = (byte)(a.bits[i]>>k);
				k -= 8;
				if (k<0) 
				{
					i++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -