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

📄 messages.cs

📁 P2P (peer to peer) file sharing program in C#. Supports Gnutella, Gnutella2, eDonkey, and OpenNap. w
💻 CS
📖 第 1 页 / 共 4 页
字号:
// Messages.cs// Copyright (C) 2002 Matt Zyzik (www.FileScope.com)// // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program 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 General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USAusing System;using System.Collections;using System.Text;using System.Net;using System.Net.Sockets;namespace FileScope.Gnutella2{	/// <summary>	/// Holds shared member variables used in Message and Child classes.	/// Also contains the Read function which sets up children and finds the starting point of the payload.	/// </summary>	public abstract class G2Packet	{		public bool cf;						//compound flag; signifies child packets		public int payLen;					//length of the payload of this packet		public Child children = null;		//linked list of children that are mine		public Child nextChild = null;		//linked list of children that are my parent's		public Message root = null;			//store a reference to the root packet		/// <summary>		/// Iterate through all children and determine the beginning location of this packet's payload.		/// </summary>		public void Read(int buffIndex)		{			int start = buffIndex;			//if we have any child packets			if(this.cf)			{				Child curChild = null;				while((start+this.payLen) - buffIndex > 0)				{					//if there is payload following children, a null byte terminates the set of children					if(root.inPayload[buffIndex] == 0x00)					{						buffIndex++;						break;					}					//control byte					int llen = (int)root.inPayload[buffIndex] >> 6;					int nlen = ((int)(root.inPayload[buffIndex] & 0x38) >> 3) + 1;					buffIndex += 1+llen;					//name					string name = Encoding.ASCII.GetString(root.inPayload, buffIndex, nlen);					if(curChild == null)					{						//start the linked list						children = this.ChildType(ref name);						curChild = children;					}					else					{						//continue the linked list						curChild.nextChild = this.ChildType(ref name);						curChild = curChild.nextChild;					}#if DEBUG					if(curChild.GetType() == typeof(UnknownChild))					{//						if(name != "G1" && name != "NOG1" && name != "BH" && name != "UNSTA" && name != "SS")//							System.Diagnostics.Debug.WriteLine("unknown G2 child: " + this.GetType().ToString() + "/" + name);					}#endif					//ref to root					curChild.root = root;					buffIndex += nlen;					curChild.offset = buffIndex;					//length					if(llen == 0)						curChild.payLen = 0;					else						curChild.payLen = Endian.VarBytesToInt(root.inPayload, buffIndex-(llen+nlen), llen, root.be);					//more of control byte					curChild.cf = ((root.inPayload[buffIndex-(llen+nlen+1)] & 0x04) == 0x04);					//shareaza bug					if(curChild.payLen == 10 && curChild.cf && name == "CH")						curChild.cf = false;					buffIndex += curChild.payLen;				}			}			//process the payload			Process(buffIndex, (start+this.payLen) - buffIndex);		}		public abstract void Process(int offset, int len);		public virtual Child ChildType(ref string name)		{			return new UnknownChild(ref name);		}	}	/// <summary>	/// Message is for encapsulating root packets in the Gnutella2 format.	/// It is also the base class of many subclasses representing the different root packet types.	/// </summary>	public abstract class Message : G2Packet	{		public int sockNum;					//store where this message came from		public IPEndPoint ipep = null;		//store where this message came from (if not over tcp)		public bool be;						//big endian?		public byte[] inPayload = null;		//payload of the entire root packet (including children / sub-children)		/// <summary>		/// Incoming Message.		/// </summary>		public void GetMsg(Sck sck)		{			this.root = this;			this.sockNum = sck.sockNum;			int bytesRec;			//fill payload			if(this.payLen > 0)			{				this.inPayload = new byte[this.payLen];				bytesRec = sck.ReceiveData(this.inPayload, 0, this.payLen);				if(bytesRec == 0)				{					sck.Disconnect("nethin' received (G2) GetMsg");					return;				}			}		}		/// <summary>		/// Incoming UDP Message.		/// </summary>		public void GetMsg(IncomingPacket udpip)		{			this.root = this;			this.sockNum = -1;			//fill payload			if(this.payLen > 0)			{				this.inPayload = new byte[this.payLen];				udpip.GetData(this.inPayload, 0, this.payLen);			}		}		/// <summary>		/// This function returns an instance of a subclass of Message.		/// </summary>		public static Message RootMsgType(ref string name)		{//System.Diagnostics.Debug.WriteLine("in: " + name);			//ordered generally from most popular to least			switch(name)			{				case "Q2":					return new Query();				case "QH2":					return new QueryHit();				case "QKR":					return new QueryKeyRequest();				case "QKA":					return new QueryKeyAnswer();				case "QA":					return new QueryAck();				case "PUSH":					return new Push();				case "PI":					return new Ping();				case "PO":					return new Pong();				case "LNI":					return new LocalNodeInfo();				case "KHL":					return new KnownHubList();				case "QHT":					return new QueryHashTable();				case "UPROC":					return new UserProfileRequest();				case "UPROD":					return new UserProfileAnswer();				default:					return null;			}		}	}	/// <summary>	/// Used to encapsulate child packets.	/// This is also the base class for several subclasses representing G2 child packets.	/// </summary>	public abstract class Child : G2Packet	{		public int offset;		//offset of child payload in original root payload	}	/*   various subclasses of Message and Child   */	public class HandshakeMsg : Message	{		public string handshake = "";		public new void GetMsg(Sck sck)		{			int bytesRec;			while(true)			{				if(sck.state == Condition.hndshk2 || sck.browseHost)				{					/*					 * if we're receiving the last handshake from an incoming connection, then					 * things are a little different because actual packets may follow right after					 */					if(!sck.incoming && !sck.browseHost)						System.Diagnostics.Debug.WriteLine("G2 incoming final handshake problem");					//we'll get straight up to the \r\n\r\n part, and stop right there					int recLen = 4;					byte[] hndshk = new byte[4];					int endHndShk;					while(true)					{						bytesRec = sck.ReceiveData(hndshk, 0, recLen);						if(bytesRec == 0)						{							sck.Disconnect("nethin' received during handshake (G2)");							return;						}						handshake += Encoding.ASCII.GetString(hndshk, 0, bytesRec);						endHndShk = handshake.LastIndexOf("\r\n\r\n");						if(endHndShk != -1)							return;						if(handshake[handshake.Length-1] == '\n')							recLen = 2;						else if(handshake[handshake.Length-1] == '\r')							recLen = 1;						else							recLen = 4;					}				}				else				{					//usual handshake receive					byte[] hndshk = new byte[32768];					bytesRec = sck.ReceiveData(hndshk);					if(bytesRec == 0)					{						sck.Disconnect("nethin' received during handshake (G2)");						return;					}					handshake += Encoding.ASCII.GetString(hndshk, 0, bytesRec);					int endHndShk = handshake.LastIndexOf("\r\n\r\n");					if(endHndShk != -1)						break;					else						System.Diagnostics.Debug.WriteLine("G2 Handshake GetMsg didn't finish");				}			}		}		public override void Process(int offset, int len)		{			//		}	}	public class UnknownChild : Child	{		public string name;		public UnknownChild(ref string name)		{			this.name = name;		}		public override void Process(int offset, int len)		{			//		}	}	public class Ping : Message	{		public override void Process(int offset, int len)		{			if(this.sockNum != -1)			{				UDP udp = null;				bool relay = false;				Child child = this.children;				while(child != null)				{					if(child.GetType() == typeof(UDP))						udp = (UDP)child;					else if(child.GetType() == typeof(Relay))						relay = true;					child = child.nextChild;				}				if(!relay)				{					//add a relay child and forward to all ultrapeers if udp present					if(udp != null)					{						OUdpPingRelay oupr = new OUdpPingRelay();						Array.Copy(root.inPayload, udp.offset, oupr.endpoint, 0, 6);						//in case there's an endian-ness difference between this host and us						if(root.be != !Stats.Updated.le)						{							//reverse the byte order of the 16-bit port							Array.Reverse(oupr.endpoint, 4, 2);						}						lock(HostCache.recentHubs)						{							foreach(ConnectionManager.G2Host g2h in ConnectionManager.ultrapeers.Keys)								Sck.scks[g2h.sockNum].SendPacket(oupr);						}					}					else						Sck.scks[this.sockNum].SendPacket(new OPong());				}				else if(udp != null)				{					//we'll send a pong over udp with the relay child to the original host					udp.Read(udp.offset);					if(udp.ipep != null)						UDPSR.SendOutgoingPacket(new OPongRelay(), udp.ipep);				}			}			else			{				//ignoring any children, we'll send a plain pong back over udp				UDPSR.SendOutgoingPacket(new OPong(), this.ipep);			}		}		public override Child ChildType(ref string name)		{			if(name == "RELAY")				return new Relay();			else if(name == "UDP")				return new UDP();			else				return new UnknownChild(ref name);		}		public class Relay : Child		{			public override void Process(int offset, int len)			{				//			}		}		public class UDP : Child		{			public IPEndPoint ipep = null;			public override void Process(int offset, int len)			{				if(len == 6)					this.ipep = new IPEndPoint(Endian.GetIPAddress(root.inPayload, offset), Endian.ToUInt16(root.inPayload, offset+4, root.be));				else					System.Diagnostics.Debug.WriteLine("g2 ping udp len: " + len.ToString());			}		}	}	public class Pong : Message	{		public override void Process(int offset, int len)		{			//		}		public override Child ChildType(ref string name)		{			if(name == "RELAY")				return new Relay();			else				return new UnknownChild(ref name);		}		public class Relay : Child		{			public override void Process(int offset, int len)			{				//			}		}	}	public class LocalNodeInfo : Message	{		public override void Process(int offset, int len)		{			if(root.sockNum == -1)				return;			Child child = this.children;			while(child != null)			{				child.Read(child.offset);				child = child.nextChild;			}		}		public override Child ChildType(ref string name)		{			if(name == "NA")				return new NodeAddress();			else if(name == "GU")				return new GuIdent();			else if(name == "V")				return new VendorCode();			else if(name == "LS")				return new LibraryStats();			else if(name == "HS")				return new HubStatus();			else				return new UnknownChild(ref name);		}		public class NodeAddress : Child		{			public override void Process(int offset, int len)			{				//port is important				if(Sck.scks[root.sockNum].incoming && len == 6)					Sck.scks[root.sockNum].port = Endian.ToUInt16(root.inPayload, offset+4, root.be);			}		}		public class GuIdent : Child		{			public override void Process(int offset, int len)			{				if(!Stats.Updated.Gnutella2.ultrapeer)					return;				if(len == 16)				{					if(Sck.scks[root.sockNum].gitem == null)					{						GUIDitem gitem = new GUIDitem(root.inPayload, offset);						lock(Router.htRoutes)						{							Sck.scks[root.sockNum].gitem = gitem;							Router.RouteEntry re = new Router.RouteEntry();							re.gitem_key = gitem;							re.ipep = null;							re.sckNum = root.sockNum;							re.timeLeft = -9000;							Router.htRoutes.Add(gitem, re);						}					}				}				else					System.Diagnostics.Debug.WriteLine("G2 LNI GuIdent wrong length: " + len.ToString());			}		}		public class VendorCode : Child		{			public override void Process(int offset, int len)			{				//			}		}		public class LibraryStats : Child		{			public override void Process(int offset, int len)			{				Sck.scks[root.sockNum].numFiles = Endian.ToUInt32(root.inPayload, offset, root.be);				Sck.scks[root.sockNum].numKB = Endian.ToUInt32(root.inPayload, offset+4, root.be);			}		}		public class HubStatus : Child		{			public override void Process(int offset, int len)			{				Sck.scks[root.sockNum].leaves = Endian.ToUInt16(root.inPayload, offset, root.be);				Sck.scks[root.sockNum].maxleaves = Endian.ToUInt16(root.inPayload, offset+2, root.be);			}		}	}	public class KnownHubList : Message	{		public override void Process(int offset, int len)		{			//since we're expecting neighboring hubs info, we'll clear the old info			lock(HostCache.recentHubs)				Sck.scks[root.sockNum].neighbors.Clear();			int timeStamp = 0;			Child child = this.children;			while(child != null)			{				child.Read(child.offset);				if(child.GetType() == typeof(CachedHub))				{					CachedHub ch = (CachedHub)child;					if(ch.ipa != null)					{						HubInfo hi = new HubInfo();						hi.port = ch.port;						hi.timeKnown = Math.Abs(timeStamp - ch.timeStamp);						HostCache.AddRecentAndCache(ch.ipa, hi);					}				}				else if(child.GetType() == typeof(Timestamp))					timeStamp = ((Timestamp)child).timeStamp;				child = child.nextChild;			}		}		public override Child ChildType(ref string name)		{			if(name == "NH")				return new NeighborHub();			else if(name == "CH")				return new CachedHub();			else if(name == "TS")				return new Timestamp();			else				return new UnknownChild(ref name);		}		public class Timestamp : Child		{			public int timeStamp;			public override void Process(int offset, int len)			{				this.timeStamp = Endian.ToInt32(root.inPayload, offset, root.be);			}		}		public class NeighborHub : Child		{			public override void Process(int offset, int len)			{				if(len != 6)				{					Utils.Diag("G2 KHL/NH wrong length: " + len.ToString());					return;				}

⌨️ 快捷键说明

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