tanghai 13 лет назад
Родитель
Сommit
bcd93b60e9

+ 1 - 1
CSharp/App/Modules/Robot/Packages.config

@@ -5,5 +5,5 @@
   <package id="Google.ProtocolBuffers" version="2.4.1.473" targetFramework="net45" />
   <package id="Prism" version="4.1.0.0" targetFramework="net45" />
   <package id="Prism.MEFExtensions" version="4.1.0.0" targetFramework="net45" />
-  <package id="protobuf-net" version="2.0.0.612" targetFramework="net45" />
+  <package id="protobuf-net" version="2.0.0.621" targetFramework="net45" />
 </packages>

+ 38 - 5
CSharp/App/Modules/Robot/Protos/Messages.cs

@@ -1,25 +1,58 @@
 using System.Collections.Generic;
+using System.Runtime.Serialization;
 using ProtoBuf;
 
 namespace Robot.Protos
 {
-	[ProtoContract]
-	[System.Xml.Serialization.XmlType(TypeName = "SMSG_Auth_Challenge")]
+	public static class MessageOpcode
+	{
+		public const ushort CMSG_AUTHLOGONPERMIT = 800;
+		public const ushort CMSG_OTP_PASSWORD = 801;
+		public const ushort CMSG_PPC_PASSWORD = 802;
+		public const ushort CMSG_AUTHLOGONCHALLENGE = 803;
+		public const ushort CMSG_AUTHLOGONCHALLENGE_2 = 804;
+		public const ushort CMSG_AUTHLOGONPROOF = 805;
+		public const ushort SMSG_AUTH_LOGON_CHALLENGE_RESPONSE = 900;
+		public const ushort SMSG_REALM_LOGON_RESPONSE = 901;
+		public const ushort SMSG_REALM_LIST = 902;
+		public const ushort SMSG_LOCK_FOR_SAFE_TIME = 903;
+		public const ushort SMSG_PASSWORD_PROTECT_TYPE = 904;
+	}
+
+	[DataContract]
+	public class CMSG_AuthLogonPermit
+	{
+		[DataMember(Order = 1, IsRequired = true)]
+		public string Account
+		{
+			get;
+			set;
+		}
+		[DataMember(Order = 2, IsRequired = true)]
+		public string PasswordMd5
+		{
+			get;
+			set;
+		}
+	}
+
+
+	[DataContract]
 	public class SMSG_Auth_Challenge
 	{
-		[ProtoMember(1, IsRequired = true)]
+		[DataMember(Order = 1, IsRequired = true)]
 		public uint Num
 		{
 			get;
 			set;
 		}
-		[ProtoMember(2, IsRequired = true)]
+		[DataMember(Order = 2, IsRequired = true)]
 		public uint Seed
 		{
 			get;
 			set;
 		}
-		[ProtoMember(3)]
+		[DataMember(Order = 3)]
 		public List<uint> Random
 		{
 			get;

+ 0 - 6
CSharp/App/Modules/Robot/Protos/Person.proto

@@ -1,6 +0,0 @@
-package Egametang;
-
-message Person
-{
-	required int32 id = 1;
-};

+ 97 - 0
CSharp/App/Modules/Robot/RealmSession.cs

@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using Helper;
+using Log;
+using Org.BouncyCastle.Utilities.Encoders;
+using ProtoBuf;
+using Robot.Protos;
+using Helper;
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Robot
+{
+	public class RealmSession: IDisposable
+	{
+		private readonly NetworkStream networkStream;
+
+		public RealmSession(string host, ushort port)
+		{
+			Socket socket = ConnectSocket(host, port);
+			networkStream = new NetworkStream(socket);
+		}
+
+		public void Dispose()
+		{
+			networkStream.Dispose();
+		}
+
+		public static Socket ConnectSocket(string host, ushort port)
+		{
+			IPHostEntry hostEntry = Dns.GetHostEntry(host);
+
+			foreach (IPAddress address in hostEntry.AddressList)
+			{
+				var ipe = new IPEndPoint(address, port);
+				var tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+
+				tempSocket.Connect(ipe);
+
+				if (!tempSocket.Connected)
+				{
+					continue;
+				}
+
+				return tempSocket;
+			}
+			Logger.Debug("socket is null, address: {0}:{1}", host, port);
+			throw new SocketException(10000);
+		}
+
+		public async void SendMessage<T>(ushort opcode, T message)
+		{
+			byte[] protoBytes = ProtobufHelper.ProtoToBytes(message);
+			var neworkBytes = new byte[sizeof(int) + sizeof(ushort) + protoBytes.Length];
+
+			int totalSize = sizeof(ushort) + protoBytes.Length;
+			
+			var totalSizeBytes = BitConverter.GetBytes(totalSize);
+			totalSizeBytes.CopyTo(neworkBytes, 0);
+
+			var opcodeBytes = BitConverter.GetBytes(opcode);
+			opcodeBytes.CopyTo(neworkBytes, sizeof(int));
+			
+			protoBytes.CopyTo(neworkBytes, sizeof(int) + sizeof(ushort));
+
+			await networkStream.WriteAsync(neworkBytes, 0, neworkBytes.Length);
+		}
+
+		public void Login(string account, string password)
+		{
+			try
+			{
+				byte[] passwordBytes = password.ToByteArray();
+				var digest = new MD5Digest();
+				var passwordMd5 = new byte[digest.GetDigestSize()];
+
+				digest.BlockUpdate(passwordBytes, 0, passwordBytes.Length);
+				digest.DoFinal(passwordMd5, 0);
+
+				var cmsgAuthLogonPermit = new CMSG_AuthLogonPermit
+				{
+					Account = account,
+					PasswordMd5 = Hex.ToHexString(passwordMd5)
+				};
+
+				Logger.Debug("password: {0}", cmsgAuthLogonPermit.PasswordMd5);
+
+				SendMessage(MessageOpcode.CMSG_AUTHLOGONPERMIT, cmsgAuthLogonPermit);
+			}
+			catch (SocketException e)
+			{
+				Logger.Debug("socket exception, error: {}", e.ErrorCode);
+			}
+		}
+	}
+}

+ 7 - 7
CSharp/App/Modules/Robot/Robot.csproj

@@ -32,6 +32,9 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="BouncyCastle.Crypto">
+      <HintPath>..\..\..\packages\BouncyCastle.1.7.0\lib\Net20\BouncyCastle.Crypto.dll</HintPath>
+    </Reference>
     <Reference Include="Google.ProtocolBuffers">
       <HintPath>..\..\..\packages\Google.ProtocolBuffers.2.4.1.473\lib\net40\Google.ProtocolBuffers.dll</HintPath>
     </Reference>
@@ -46,19 +49,21 @@
     </Reference>
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationFramework" />
-    <Reference Include="protobuf-net, Version=2.0.0.612, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
+    <Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\..\packages\protobuf-net.2.0.0.612\lib\net40\protobuf-net.dll</HintPath>
+      <HintPath>..\..\..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xaml" />
     <Reference Include="System.Xml" />
     <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Protos\Messages.cs" />
+    <Compile Include="RealmSession.cs" />
     <Compile Include="Robot.cs" />
     <Compile Include="RobotModule.cs" />
     <Compile Include="RobotViewModel.cs" />
@@ -95,11 +100,6 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="Packages.config" />
-    <None Include="google\protobuf\csharp_options.proto" />
-    <None Include="google\protobuf\descriptor.proto" />
-    <None Include="Protos\Person.proto">
-      <Generator>ProtobufTool</Generator>
-    </None>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\nuget.targets" />

+ 1 - 1
CSharp/App/Modules/Robot/RobotView.xaml.cs

@@ -31,7 +31,7 @@ namespace Modules.Robot
 
 		private void btnLogin_Click(object sender, RoutedEventArgs e)
 		{
-			this.ViewModel.Login();
+			this.ViewModel.Login("egametang@163.com", "111111");
 		}
 	}
 }

+ 23 - 25
CSharp/App/Modules/Robot/RobotViewModel.cs

@@ -1,14 +1,9 @@
 using System;
 using System.ComponentModel.Composition;
-using System.IO;
-using System.Text;
 using System.Windows.Threading;
 using ENet;
-using Helper;
-using Log;
 using Microsoft.Practices.Prism.ViewModel;
-using ProtoBuf;
-using Robot.Protos;
+using Robot;
 
 namespace Modules.Robot
 {
@@ -80,26 +75,29 @@ namespace Modules.Robot
 			this.clientHost.Dispose();
 		}
 
-		public async void Login()
+		public void Login(string account, string password)
 		{
-			try
-			{
-				var address = new Address { HostName = this.LoginIp, Port = this.LoginPort };
-				Peer peer = await this.clientHost.ConnectAsync(address);
-				using (Packet packet = await peer.ReceiveAsync())
-				{
-					var bytes = packet.Bytes;
-					var packetStream = new MemoryStream(bytes, 4, bytes.Length - 4);
-					var smsg = Serializer.Deserialize<SMSG_Auth_Challenge>(packetStream);
-					Logger.Debug(string.Format("opcode: {0}\n{1}", 
-						BitConverter.ToUInt16(bytes, 0), XmlHelper.XmlSerialize(smsg)));
-					await peer.DisconnectLaterAsync();
-				}
-			}
-			catch (Exception e)
-			{
-				Logger.Debug(e.Message);
-			}
+			//try
+			//{
+			//	var address = new Address { HostName = this.LoginIp, Port = this.LoginPort };
+			//	Peer peer = await this.clientHost.ConnectAsync(address);
+			//	using (Packet packet = await peer.ReceiveAsync())
+			//	{
+			//		var bytes = packet.Bytes;
+			//		var packetStream = new MemoryStream(bytes, 4, bytes.Length - 4);
+			//		var smsg = Serializer.Deserialize<SMSG_Auth_Challenge>(packetStream);
+			//		Logger.Debug(string.Format("opcode: {0}\n{1}",
+			//			BitConverter.ToUInt16(bytes, 0), XmlHelper.XmlSerialize(smsg)));
+			//		await peer.DisconnectLaterAsync();
+			//	}
+			//}
+			//catch (Exception e)
+			//{
+			//	Logger.Debug(e.Message);
+			//}
+
+			var session = new RealmSession("192.168.11.95", 8888);
+			session.Login(account, password);
 		}
 	}
 }

+ 0 - 111
CSharp/App/Modules/Robot/google/protobuf/csharp_options.proto

@@ -1,111 +0,0 @@
-// Extra options for C# generator
-
-import "google/protobuf/descriptor.proto";
-
-package google.protobuf;
-
-message CSharpFileOptions {
-
-  // Namespace for generated classes; defaults to the package.
-  optional string namespace = 1;
-  
-  // Name of the "umbrella" class used for metadata about all
-  // the messages within this file. Default is based on the name
-  // of the file.
-  optional string umbrella_classname = 2;
-  
-  // Whether classes should be public (true) or internal (false)
-  optional bool public_classes = 3 [default = true];
-
-  // Whether to generate a single file for everything within the
-  // .proto file (false), or one file per message (true).
-  // This option is not currently honored; please log a feature
-  // request if you really want it.
-  optional bool multiple_files = 4;
-
-  // Whether to nest messages within a single umbrella class (true)
-  // or create the umbrella class as a peer, with messages as
-  // top-level classes in the namespace (false)
-  optional bool nest_classes = 5;
-  
-  // Generate appropriate support for Code Contracts
-  // (Ongoing; support should improve over time)
-  optional bool code_contracts = 6;
-  
-  // Create subdirectories for namespaces, e.g. namespace "Foo.Bar"
-  // would generate files within [output directory]/Foo/Bar
-  optional bool expand_namespace_directories = 7;
-
-  // Generate attributes indicating non-CLS-compliance
-  optional bool cls_compliance = 8 [default = true];
-  
-  // Generate messages/builders with the [Serializable] attribute
-  optional bool add_serializable = 9 [default = false];
-  
-  // Generates a private ctor for Message types
-  optional bool generate_private_ctor = 10 [default = true];
-
-  // The extension that should be appended to the umbrella_classname when creating files.
-  optional string file_extension = 221 [default = ".cs"];
-  
-  // A nested namespace for the umbrella class.  Helpful for name collisions caused by 
-  // umbrella_classname conflicting with an existing type.  This will be automatically
-  // set to 'Proto' if a collision is detected with types being generated.  This value
-  // is ignored when nest_classes == true
-  optional string umbrella_namespace = 222;
-  
-  // The output path for the source file(s) generated
-  optional string output_directory = 223 [default = "."];
-
-  // Will ignore the type generations and remove dependencies for the descriptor proto
-  // files that declare their package to be "google.protobuf"
-  optional bool ignore_google_protobuf = 224 [default = false];
-
-  // Controls how services are generated, GENERIC is the deprecated original implementation
-  // INTERFACE generates service interfaces only, RPCINTEROP generates interfaces and 
-  // implementations using the included Windows RPC interop libarary.
-  optional CSharpServiceType service_generator_type = 225 [default = NONE];
-}
-
-enum CSharpServiceType {
-  // Services are ignored by the generator
-  NONE = 0;
-  // Generates the original Java generic service implementations
-  GENERIC = 1;
-  // Generates an interface for the service and nothing else
-  INTERFACE = 2;
-  // Generates an interface for the service and client/server wrappers for the interface
-  IRPCDISPATCH = 3;
-}
-
-extend FileOptions {
-  optional CSharpFileOptions csharp_file_options = 1000;
-}
-
-extend FieldOptions {
-  optional CSharpFieldOptions csharp_field_options = 1000;
-}
-
-message CSharpFieldOptions {
-  // Provides the ability to override the name of the property
-  // generated for this field. This is applied to all properties
-  // and methods to do with this field, including HasFoo, FooCount,
-  // FooList etc.
-  optional string property_name = 1;
-}
-
-message CSharpServiceOptions {
-  optional string interface_id = 1;
-}
-
-extend ServiceOptions {
-  optional CSharpServiceOptions csharp_service_options = 1000;
-}
-
-message CSharpMethodOptions {
-  optional int32 dispatch_id = 1;
-}
-
-extend MethodOptions {
-  optional CSharpMethodOptions csharp_method_options = 1000;
-}

+ 0 - 533
CSharp/App/Modules/Robot/google/protobuf/descriptor.proto

@@ -1,533 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// The messages in this file describe the definitions found in .proto files.
-// A valid .proto file can be translated directly to a FileDescriptorProto
-// without any other information (e.g. without reading its imports).
-
-
-
-package google.protobuf;
-option java_package = "com.google.protobuf";
-option java_outer_classname = "DescriptorProtos";
-
-// descriptor.proto must be optimized for speed because reflection-based
-// algorithms don't work during bootstrapping.
-option optimize_for = SPEED;
-
-// The protocol compiler can output a FileDescriptorSet containing the .proto
-// files it parses.
-message FileDescriptorSet {
-  repeated FileDescriptorProto file = 1;
-}
-
-// Describes a complete .proto file.
-message FileDescriptorProto {
-  optional string name = 1;       // file name, relative to root of source tree
-  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
-
-  // Names of files imported by this file.
-  repeated string dependency = 3;
-
-  // All top-level definitions in this file.
-  repeated DescriptorProto message_type = 4;
-  repeated EnumDescriptorProto enum_type = 5;
-  repeated ServiceDescriptorProto service = 6;
-  repeated FieldDescriptorProto extension = 7;
-
-  optional FileOptions options = 8;
-
-  // This field contains optional information about the original source code.
-  // You may safely remove this entire field whithout harming runtime
-  // functionality of the descriptors -- the information is needed only by
-  // development tools.
-  optional SourceCodeInfo source_code_info = 9;
-}
-
-// Describes a message type.
-message DescriptorProto {
-  optional string name = 1;
-
-  repeated FieldDescriptorProto field = 2;
-  repeated FieldDescriptorProto extension = 6;
-
-  repeated DescriptorProto nested_type = 3;
-  repeated EnumDescriptorProto enum_type = 4;
-
-  message ExtensionRange {
-    optional int32 start = 1;
-    optional int32 end = 2;
-  }
-  repeated ExtensionRange extension_range = 5;
-
-  optional MessageOptions options = 7;
-}
-
-// Describes a field within a message.
-message FieldDescriptorProto {
-  enum Type {
-    // 0 is reserved for errors.
-    // Order is weird for historical reasons.
-    TYPE_DOUBLE         = 1;
-    TYPE_FLOAT          = 2;
-    TYPE_INT64          = 3;   // Not ZigZag encoded.  Negative numbers
-                               // take 10 bytes.  Use TYPE_SINT64 if negative
-                               // values are likely.
-    TYPE_UINT64         = 4;
-    TYPE_INT32          = 5;   // Not ZigZag encoded.  Negative numbers
-                               // take 10 bytes.  Use TYPE_SINT32 if negative
-                               // values are likely.
-    TYPE_FIXED64        = 6;
-    TYPE_FIXED32        = 7;
-    TYPE_BOOL           = 8;
-    TYPE_STRING         = 9;
-    TYPE_GROUP          = 10;  // Tag-delimited aggregate.
-    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
-
-    // New in version 2.
-    TYPE_BYTES          = 12;
-    TYPE_UINT32         = 13;
-    TYPE_ENUM           = 14;
-    TYPE_SFIXED32       = 15;
-    TYPE_SFIXED64       = 16;
-    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
-    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
-  };
-
-  enum Label {
-    // 0 is reserved for errors
-    LABEL_OPTIONAL      = 1;
-    LABEL_REQUIRED      = 2;
-    LABEL_REPEATED      = 3;
-    // TODO(sanjay): Should we add LABEL_MAP?
-  };
-
-  optional string name = 1;
-  optional int32 number = 3;
-  optional Label label = 4;
-
-  // If type_name is set, this need not be set.  If both this and type_name
-  // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
-  optional Type type = 5;
-
-  // For message and enum types, this is the name of the type.  If the name
-  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
-  // rules are used to find the type (i.e. first the nested types within this
-  // message are searched, then within the parent, on up to the root
-  // namespace).
-  optional string type_name = 6;
-
-  // For extensions, this is the name of the type being extended.  It is
-  // resolved in the same manner as type_name.
-  optional string extendee = 2;
-
-  // For numeric types, contains the original text representation of the value.
-  // For booleans, "true" or "false".
-  // For strings, contains the default text contents (not escaped in any way).
-  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
-  // TODO(kenton):  Base-64 encode?
-  optional string default_value = 7;
-
-  optional FieldOptions options = 8;
-}
-
-// Describes an enum type.
-message EnumDescriptorProto {
-  optional string name = 1;
-
-  repeated EnumValueDescriptorProto value = 2;
-
-  optional EnumOptions options = 3;
-}
-
-// Describes a value within an enum.
-message EnumValueDescriptorProto {
-  optional string name = 1;
-  optional int32 number = 2;
-
-  optional EnumValueOptions options = 3;
-}
-
-// Describes a service.
-message ServiceDescriptorProto {
-  optional string name = 1;
-  repeated MethodDescriptorProto method = 2;
-
-  optional ServiceOptions options = 3;
-}
-
-// Describes a method of a service.
-message MethodDescriptorProto {
-  optional string name = 1;
-
-  // Input and output type names.  These are resolved in the same way as
-  // FieldDescriptorProto.type_name, but must refer to a message type.
-  optional string input_type = 2;
-  optional string output_type = 3;
-
-  optional MethodOptions options = 4;
-}
-
-// ===================================================================
-// Options
-
-// Each of the definitions above may have "options" attached.  These are
-// just annotations which may cause code to be generated slightly differently
-// or may contain hints for code that manipulates protocol messages.
-//
-// Clients may define custom options as extensions of the *Options messages.
-// These extensions may not yet be known at parsing time, so the parser cannot
-// store the values in them.  Instead it stores them in a field in the *Options
-// message called uninterpreted_option. This field must have the same name
-// across all *Options messages. We then use this field to populate the
-// extensions when we build a descriptor, at which point all protos have been
-// parsed and so all extensions are known.
-//
-// Extension numbers for custom options may be chosen as follows:
-// * For options which will only be used within a single application or
-//   organization, or for experimental options, use field numbers 50000
-//   through 99999.  It is up to you to ensure that you do not use the
-//   same number for multiple options.
-// * For options which will be published and used publicly by multiple
-//   independent entities, e-mail kenton@google.com to reserve extension
-//   numbers.  Simply tell me how many you need and I'll send you back a
-//   set of numbers to use -- there's no need to explain how you intend to
-//   use them.  If this turns out to be popular, a web service will be set up
-//   to automatically assign option numbers.
-
-
-message FileOptions {
-
-  // Sets the Java package where classes generated from this .proto will be
-  // placed.  By default, the proto package is used, but this is often
-  // inappropriate because proto packages do not normally start with backwards
-  // domain names.
-  optional string java_package = 1;
-
-
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
-  optional string java_outer_classname = 8;
-
-  // If set true, then the Java code generator will generate a separate .java
-  // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
-  // generated to contain the file's getDescriptor() method as well as any
-  // top-level extensions defined in the file.
-  optional bool java_multiple_files = 10 [default=false];
-
-  // If set true, then the Java code generator will generate equals() and
-  // hashCode() methods for all messages defined in the .proto file. This is
-  // purely a speed optimization, as the AbstractMessage base class includes
-  // reflection-based implementations of these methods.
-  optional bool java_generate_equals_and_hash = 20 [default=false];
-
-  // Generated classes can be optimized for speed or code size.
-  enum OptimizeMode {
-    SPEED = 1;        // Generate complete code for parsing, serialization,
-                      // etc.
-    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
-    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
-  }
-  optional OptimizeMode optimize_for = 9 [default=SPEED];
-
-
-
-
-  // Should generic services be generated in each language?  "Generic" services
-  // are not specific to any particular RPC system.  They are generated by the
-  // main code generators in each language (without additional plugins).
-  // Generic services were the only kind of service generation supported by
-  // early versions of proto2.
-  //
-  // Generic services are now considered deprecated in favor of using plugins
-  // that generate code specific to your particular RPC system.  Therefore,
-  // these default to false.  Old code which depends on generic services should
-  // explicitly set them to true.
-  optional bool cc_generic_services = 16 [default=false];
-  optional bool java_generic_services = 17 [default=false];
-  optional bool py_generic_services = 18 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MessageOptions {
-  // Set true to use the old proto1 MessageSet wire format for extensions.
-  // This is provided for backwards-compatibility with the MessageSet wire
-  // format.  You should not use this for any other reason:  It's less
-  // efficient, has fewer features, and is more complicated.
-  //
-  // The message must be defined exactly as follows:
-  //   message Foo {
-  //     option message_set_wire_format = true;
-  //     extensions 4 to max;
-  //   }
-  // Note that the message cannot have any defined fields; MessageSets only
-  // have extensions.
-  //
-  // All extensions of your type must be singular messages; e.g. they cannot
-  // be int32s, enums, or repeated messages.
-  //
-  // Because this is an option, the above two restrictions are not enforced by
-  // the protocol compiler.
-  optional bool message_set_wire_format = 1 [default=false];
-
-  // Disables the generation of the standard "descriptor()" accessor, which can
-  // conflict with a field of the same name.  This is meant to make migration
-  // from proto1 easier; new code should avoid fields named "descriptor".
-  optional bool no_standard_descriptor_accessor = 2 [default=false];
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message FieldOptions {
-  // The ctype option instructs the C++ code generator to use a different
-  // representation of the field than it normally would.  See the specific
-  // options below.  This option is not yet implemented in the open source
-  // release -- sorry, we'll try to include it in a future version!
-  optional CType ctype = 1 [default = STRING];
-  enum CType {
-    // Default mode.
-    STRING = 0;
-
-    CORD = 1;
-
-    STRING_PIECE = 2;
-  }
-  // The packed option can be enabled for repeated primitive fields to enable
-  // a more efficient representation on the wire. Rather than repeatedly
-  // writing the tag and type for each element, the entire array is encoded as
-  // a single length-delimited blob.
-  optional bool packed = 2;
-
-
-  // Is this field deprecated?
-  // Depending on the target platform, this can emit Deprecated annotations
-  // for accessors, or it will be completely ignored; in the very least, this
-  // is a formalization for deprecating fields.
-  optional bool deprecated = 3 [default=false];
-
-  // EXPERIMENTAL.  DO NOT USE.
-  // For "map" fields, the name of the field in the enclosed type that
-  // is the key for this map.  For example, suppose we have:
-  //   message Item {
-  //     required string name = 1;
-  //     required string value = 2;
-  //   }
-  //   message Config {
-  //     repeated Item items = 1 [experimental_map_key="name"];
-  //   }
-  // In this situation, the map key for Item will be set to "name".
-  // TODO: Fully-implement this, then remove the "experimental_" prefix.
-  optional string experimental_map_key = 9;
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumOptions {
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message EnumValueOptions {
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message ServiceOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-message MethodOptions {
-
-  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
-  //   framework.  We apologize for hoarding these numbers to ourselves, but
-  //   we were already using them long before we decided to release Protocol
-  //   Buffers.
-
-  // The parser stores options it doesn't recognize here. See above.
-  repeated UninterpretedOption uninterpreted_option = 999;
-
-  // Clients can define custom options in extensions of this message. See above.
-  extensions 1000 to max;
-}
-
-// A message representing a option the parser does not recognize. This only
-// appears in options protos created by the compiler::Parser class.
-// DescriptorPool resolves these when building Descriptor objects. Therefore,
-// options protos in descriptor objects (e.g. returned by Descriptor::options(),
-// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
-// in them.
-message UninterpretedOption {
-  // The name of the uninterpreted option.  Each string represents a segment in
-  // a dot-separated name.  is_extension is true iff a segment represents an
-  // extension (denoted with parentheses in options specs in .proto files).
-  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
-  // "foo.(bar.baz).qux".
-  message NamePart {
-    required string name_part = 1;
-    required bool is_extension = 2;
-  }
-  repeated NamePart name = 2;
-
-  // The value of the uninterpreted option, in whatever type the tokenizer
-  // identified it as during parsing. Exactly one of these should be set.
-  optional string identifier_value = 3;
-  optional uint64 positive_int_value = 4;
-  optional int64 negative_int_value = 5;
-  optional double double_value = 6;
-  optional bytes string_value = 7;
-  optional string aggregate_value = 8;
-}
-
-// ===================================================================
-// Optional source code info
-
-// Encapsulates information about the original source file from which a
-// FileDescriptorProto was generated.
-message SourceCodeInfo {
-  // A Location identifies a piece of source code in a .proto file which
-  // corresponds to a particular definition.  This information is intended
-  // to be useful to IDEs, code indexers, documentation generators, and similar
-  // tools.
-  //
-  // For example, say we have a file like:
-  //   message Foo {
-  //     optional string foo = 1;
-  //   }
-  // Let's look at just the field definition:
-  //   optional string foo = 1;
-  //   ^       ^^     ^^  ^  ^^^
-  //   a       bc     de  f  ghi
-  // We have the following locations:
-  //   span   path               represents
-  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
-  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
-  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
-  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
-  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
-  //
-  // Notes:
-  // - A location may refer to a repeated field itself (i.e. not to any
-  //   particular index within it).  This is used whenever a set of elements are
-  //   logically enclosed in a single code segment.  For example, an entire
-  //   extend block (possibly containing multiple extension definitions) will
-  //   have an outer location whose path refers to the "extensions" repeated
-  //   field without an index.
-  // - Multiple locations may have the same path.  This happens when a single
-  //   logical declaration is spread out across multiple places.  The most
-  //   obvious example is the "extend" block again -- there may be multiple
-  //   extend blocks in the same scope, each of which will have the same path.
-  // - A location's span is not always a subset of its parent's span.  For
-  //   example, the "extendee" of an extension declaration appears at the
-  //   beginning of the "extend" block and is shared by all extensions within
-  //   the block.
-  // - Just because a location's span is a subset of some other location's span
-  //   does not mean that it is a descendent.  For example, a "group" defines
-  //   both a type and a field in a single declaration.  Thus, the locations
-  //   corresponding to the type and field and their components will overlap.
-  // - Code which tries to interpret locations should probably be designed to
-  //   ignore those that it doesn't understand, as more types of locations could
-  //   be recorded in the future.
-  repeated Location location = 1;
-  message Location {
-    // Identifies which part of the FileDescriptorProto was defined at this
-    // location.
-    //
-    // Each element is a field number or an index.  They form a path from
-    // the root FileDescriptorProto to the place where the definition.  For
-    // example, this path:
-    //   [ 4, 3, 2, 7, 1 ]
-    // refers to:
-    //   file.message_type(3)  // 4, 3
-    //       .field(7)         // 2, 7
-    //       .name()           // 1
-    // This is because FileDescriptorProto.message_type has field number 4:
-    //   repeated DescriptorProto message_type = 4;
-    // and DescriptorProto.field has field number 2:
-    //   repeated FieldDescriptorProto field = 2;
-    // and FieldDescriptorProto.name has field number 1:
-    //   optional string name = 1;
-    //
-    // Thus, the above path gives the location of a field name.  If we removed
-    // the last element:
-    //   [ 4, 3, 2, 7 ]
-    // this path refers to the whole field declaration (from the beginning
-    // of the label to the terminating semicolon).
-    repeated int32 path = 1 [packed=true];
-
-    // Always has exactly three or four elements: start line, start column,
-    // end line (optional, otherwise assumed same as start line), end column.
-    // These are packed into a single field for efficiency.  Note that line
-    // and column numbers are zero-based -- typically you will want to add
-    // 1 to each before displaying to a user.
-    repeated int32 span = 2 [packed=true];
-
-    // TODO(kenton):  Record comments appearing before and after the
-    // declaration.
-  }
-}

+ 2 - 2
CSharp/Platform/ENet/Peer.cs

@@ -5,7 +5,7 @@ using Log;
 
 namespace ENet
 {
-	public sealed class Peer
+	public sealed class Peer: IDisposable
 	{
 		private readonly PeerEvent peerEvent = new PeerEvent();
 		private IntPtr peerPtr;
@@ -15,7 +15,7 @@ namespace ENet
 			this.peerPtr = peerPtr;
 		}
 
-		private void Reset()
+		public void Dispose()
 		{
 			if (this.peerPtr == IntPtr.Zero)
 			{

+ 10 - 4
CSharp/Platform/ENetTest/ENetClientServerTest.cs

@@ -28,12 +28,14 @@ namespace ENetCSTest
 			host.Stop();
 		}
 
-		private static async void ServerEvent(ServerHost host)
+		private static async void ServerEvent(ServerHost host, Barrier barrier)
 		{
 			var peer = await host.AcceptAsync();
 			// Client断开,Server端收到Disconnect事件,结束Server线程
 			peer.PeerEvent.Disconnect += ev => host.Stop();
 
+			barrier.SignalAndWait();
+
 			using (var rPacket = await peer.ReceiveAsync())
 			{
 				Logger.Debug(rPacket.Bytes.ToStr());
@@ -59,11 +61,15 @@ namespace ENetCSTest
 			serverThread.Start();
 			clientThread.Start();
 
-			// 往client host线程增加事件,client线程连接server
-			clientHost.Events += () => ClientEvent(clientHost, address);
+			var barrier = new Barrier(2);
 
 			// 往server host线程增加事件,accept
-			serverHost.Events += () => ServerEvent(serverHost);
+			serverHost.Events += () => ServerEvent(serverHost, barrier);
+
+			barrier.SignalAndWait();
+
+			// 往client host线程增加事件,client线程连接server
+			clientHost.Events += () => ClientEvent(clientHost, address);
 
 			serverThread.Join();
 			clientThread.Join();

+ 11 - 0
CSharp/Platform/Helper/Helper.csproj

@@ -11,6 +11,8 @@
     <AssemblyName>Helper</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -30,6 +32,10 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Xml" />
@@ -37,11 +43,16 @@
   <ItemGroup>
     <Compile Include="ByteHelper.cs" />
     <Compile Include="LoaderHelper.cs" />
+    <Compile Include="ProtobufHelper.cs" />
     <Compile Include="StringHelper.cs" />
     <Compile Include="XmlHelper.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="Packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 4 - 0
CSharp/Platform/Helper/Packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="protobuf-net" version="2.0.0.621" targetFramework="net45" />
+</packages>

+ 15 - 0
CSharp/Platform/Helper/ProtobufHelper.cs

@@ -0,0 +1,15 @@
+using System.IO;
+using ProtoBuf;
+
+namespace Helper
+{
+	public static class ProtobufHelper
+	{
+		public static byte[] ProtoToBytes<T>(T message)
+		{
+			var ms = new MemoryStream();
+			Serializer.Serialize(ms, message);
+			return ms.ToArray();
+		}
+	}
+}