diff --git a/assets/bin/generate_proto.bat b/assets/bin/generate_proto.bat new file mode 100644 index 0000000..3e7d5a7 --- /dev/null +++ b/assets/bin/generate_proto.bat @@ -0,0 +1,5 @@ +::Protocol Buffer version 3.11.4 +set CURRENT_PATH=%cd% +set UNITY_PACKET_PATH=%CURRENT_PATH%\..\csharp +protoc -I=%CURRENT_PATH%\..\protobuf --dart_out=%CURRENT_PATH%\..\..\lib\socket\packets %CURRENT_PATH%\..\protobuf\*.proto --plugin=protoc_plugin.exe +protoc -I=%CURRENT_PATH%\..\protobuf --csharp_out=%UNITY_PACKET_PATH% %CURRENT_PATH%\..\protobuf\*.proto \ No newline at end of file diff --git a/assets/bin/protoc.exe b/assets/bin/protoc.exe new file mode 100644 index 0000000..501b41c Binary files /dev/null and b/assets/bin/protoc.exe differ diff --git a/assets/bin/protoc_plugin.exe b/assets/bin/protoc_plugin.exe new file mode 100644 index 0000000..43490d1 Binary files /dev/null and b/assets/bin/protoc_plugin.exe differ diff --git a/assets/csharp/MessageCommon.cs b/assets/csharp/MessageCommon.cs new file mode 100644 index 0000000..a78a427 --- /dev/null +++ b/assets/csharp/MessageCommon.cs @@ -0,0 +1,385 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: message_common.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +/// Holder for reflection information generated from message_common.proto +public static partial class MessageCommonReflection { + + #region Descriptor + /// File descriptor for message_common.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static MessageCommonReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChRtZXNzYWdlX2NvbW1vbi5wcm90byI7CgpQYWNrZXRCYXNlEhAKCHR5cGVO", + "YW1lGAEgASgJEg0KBW5vbmNlGAIgASgFEgwKBGRhdGEYAyABKAwiLgoMVGVt", + "cGxhdGVEYXRhEg0KBWluZGV4GAEgASgFEg8KB21lc3NhZ2UYAiABKAliBnBy", + "b3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::PacketBase), global::PacketBase.Parser, new[]{ "TypeName", "Nonce", "Data" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::TemplateData), global::TemplateData.Parser, new[]{ "Index", "Message" }, null, null, null, null) + })); + } + #endregion + +} +#region Messages +public sealed partial class PacketBase : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PacketBase()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::MessageCommonReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PacketBase() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PacketBase(PacketBase other) : this() { + typeName_ = other.typeName_; + nonce_ = other.nonce_; + data_ = other.data_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public PacketBase Clone() { + return new PacketBase(this); + } + + /// Field number for the "typeName" field. + public const int TypeNameFieldNumber = 1; + private string typeName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string TypeName { + get { return typeName_; } + set { + typeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "nonce" field. + public const int NonceFieldNumber = 2; + private int nonce_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Nonce { + get { return nonce_; } + set { + nonce_ = value; + } + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 3; + private pb::ByteString data_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Data { + get { return data_; } + set { + data_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as PacketBase); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(PacketBase other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (TypeName != other.TypeName) return false; + if (Nonce != other.Nonce) return false; + if (Data != other.Data) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (TypeName.Length != 0) hash ^= TypeName.GetHashCode(); + if (Nonce != 0) hash ^= Nonce.GetHashCode(); + if (Data.Length != 0) hash ^= Data.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (TypeName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(TypeName); + } + if (Nonce != 0) { + output.WriteRawTag(16); + output.WriteInt32(Nonce); + } + if (Data.Length != 0) { + output.WriteRawTag(26); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (TypeName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeName); + } + if (Nonce != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Nonce); + } + if (Data.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(PacketBase other) { + if (other == null) { + return; + } + if (other.TypeName.Length != 0) { + TypeName = other.TypeName; + } + if (other.Nonce != 0) { + Nonce = other.Nonce; + } + if (other.Data.Length != 0) { + Data = other.Data; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + TypeName = input.ReadString(); + break; + } + case 16: { + Nonce = input.ReadInt32(); + break; + } + case 26: { + Data = input.ReadBytes(); + break; + } + } + } + } + +} + +public sealed partial class TemplateData : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TemplateData()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::MessageCommonReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TemplateData() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TemplateData(TemplateData other) : this() { + index_ = other.index_; + message_ = other.message_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TemplateData Clone() { + return new TemplateData(this); + } + + /// Field number for the "index" field. + public const int IndexFieldNumber = 1; + private int index_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Index { + get { return index_; } + set { + index_ = value; + } + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 2; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TemplateData); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TemplateData other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Index != other.Index) return false; + if (Message != other.Message) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Index != 0) hash ^= Index.GetHashCode(); + if (Message.Length != 0) hash ^= Message.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Index != 0) { + output.WriteRawTag(8); + output.WriteInt32(Index); + } + if (Message.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Message); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Index != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Index); + } + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TemplateData other) { + if (other == null) { + return; + } + if (other.Index != 0) { + Index = other.Index; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Index = input.ReadInt32(); + break; + } + case 18: { + Message = input.ReadString(); + break; + } + } + } + } + +} + +#endregion + + +#endregion Designer generated code diff --git a/assets/protobuf/message_common.proto b/assets/protobuf/message_common.proto new file mode 100644 index 0000000..0aa0cc3 --- /dev/null +++ b/assets/protobuf/message_common.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +message PacketBase { + string typeName = 1; + int32 nonce = 2; + bytes data = 3; +} + +message TemplateData { + int32 index = 1; + string message = 2; +} \ No newline at end of file diff --git a/lib/communicator.dart b/lib/communicator.dart new file mode 100644 index 0000000..111e273 --- /dev/null +++ b/lib/communicator.dart @@ -0,0 +1,89 @@ + +// ignore_for_file: prefer_final_fields + +import 'package:protobuf/protobuf.dart'; + +abstract class Communicator +{ + Map _handlerDic = {}; + late Map)> _instanceGenerator; + + Communicator(); + + void initialize(Map)> instanceGenerator) + { + _instanceGenerator = instanceGenerator; + } + + T Function(List) getGenerator(String type) + { + if(!_instanceGenerator.containsKey(type)) + { + throw Exception('Must set protobuf packet creator before use it.'); + } + return _instanceGenerator[type] as T Function(List); + } + + Future send(T data); + + void onReceivedData(String typeName, List data) + { + if( _handlerDic.containsKey(typeName) ) { + _handlerDic[typeName]?.onMessage(data); + } + } + + void addListener(void Function(T) listener) + { + var type = T.toString(); + if(!_handlerDic.containsKey(type)) + { + _handlerDic[type] = DataHandler(getGenerator(type)); + } + var handler = _handlerDic[type] as DataHandler; + handler.addListener(listener); + } + + void removeListener(void Function(T) listener) + { + var type = T.toString(); + if(_handlerDic.containsKey(type)) + { + var handler = _handlerDic[type] as DataHandler; + handler.removeListener(listener); + } + } +} + +abstract class IDataHandler +{ + void onMessage(List data); +} + +class DataHandler implements IDataHandler +{ + T Function(List) _generator; + List _listeners = []; + + DataHandler(this._generator); + + @override + void onMessage(List data) + { + for(var listener in _listeners) + { + listener.call(_generator(data)); + } + } + + void addListener(void Function(T) handler) + { + removeListener(handler); //중복 리스너 불허 + _listeners.add(handler); + } + + void removeListener(void Function(T) handler) + { + _listeners.remove(handler); + } +} \ No newline at end of file diff --git a/lib/socket/packets/message_common.pb.dart b/lib/socket/packets/message_common.pb.dart new file mode 100644 index 0000000..e9ac75a --- /dev/null +++ b/lib/socket/packets/message_common.pb.dart @@ -0,0 +1,160 @@ +// +// Generated code. Do not modify. +// source: message_common.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class PacketBase extends $pb.GeneratedMessage { + factory PacketBase({ + $core.String? typeName, + $core.int? nonce, + $core.List<$core.int>? data, + }) { + final $result = create(); + if (typeName != null) { + $result.typeName = typeName; + } + if (nonce != null) { + $result.nonce = nonce; + } + if (data != null) { + $result.data = data; + } + return $result; + } + PacketBase._() : super(); + factory PacketBase.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PacketBase.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PacketBase', createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'typeName', protoName: 'typeName') + ..a<$core.int>(2, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.O3) + ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'data', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + PacketBase clone() => PacketBase()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + PacketBase copyWith(void Function(PacketBase) updates) => super.copyWith((message) => updates(message as PacketBase)) as PacketBase; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static PacketBase create() => PacketBase._(); + PacketBase createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static PacketBase getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static PacketBase? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get typeName => $_getSZ(0); + @$pb.TagNumber(1) + set typeName($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasTypeName() => $_has(0); + @$pb.TagNumber(1) + void clearTypeName() => clearField(1); + + @$pb.TagNumber(2) + $core.int get nonce => $_getIZ(1); + @$pb.TagNumber(2) + set nonce($core.int v) { $_setSignedInt32(1, v); } + @$pb.TagNumber(2) + $core.bool hasNonce() => $_has(1); + @$pb.TagNumber(2) + void clearNonce() => clearField(2); + + @$pb.TagNumber(3) + $core.List<$core.int> get data => $_getN(2); + @$pb.TagNumber(3) + set data($core.List<$core.int> v) { $_setBytes(2, v); } + @$pb.TagNumber(3) + $core.bool hasData() => $_has(2); + @$pb.TagNumber(3) + void clearData() => clearField(3); +} + +class TemplateData extends $pb.GeneratedMessage { + factory TemplateData({ + $core.int? index, + $core.String? message, + }) { + final $result = create(); + if (index != null) { + $result.index = index; + } + if (message != null) { + $result.message = message; + } + return $result; + } + TemplateData._() : super(); + factory TemplateData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TemplateData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TemplateData', createEmptyInstance: create) + ..a<$core.int>(1, _omitFieldNames ? '' : 'index', $pb.PbFieldType.O3) + ..aOS(2, _omitFieldNames ? '' : 'message') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + TemplateData clone() => TemplateData()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TemplateData copyWith(void Function(TemplateData) updates) => super.copyWith((message) => updates(message as TemplateData)) as TemplateData; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TemplateData create() => TemplateData._(); + TemplateData createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TemplateData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TemplateData? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get index => $_getIZ(0); + @$pb.TagNumber(1) + set index($core.int v) { $_setSignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasIndex() => $_has(0); + @$pb.TagNumber(1) + void clearIndex() => clearField(1); + + @$pb.TagNumber(2) + $core.String get message => $_getSZ(1); + @$pb.TagNumber(2) + set message($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasMessage() => $_has(1); + @$pb.TagNumber(2) + void clearMessage() => clearField(2); +} + + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/lib/socket/packets/message_common.pbenum.dart b/lib/socket/packets/message_common.pbenum.dart new file mode 100644 index 0000000..e8eea36 --- /dev/null +++ b/lib/socket/packets/message_common.pbenum.dart @@ -0,0 +1,11 @@ +// +// Generated code. Do not modify. +// source: message_common.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + diff --git a/lib/socket/packets/message_common.pbjson.dart b/lib/socket/packets/message_common.pbjson.dart new file mode 100644 index 0000000..386b6cb --- /dev/null +++ b/lib/socket/packets/message_common.pbjson.dart @@ -0,0 +1,44 @@ +// +// Generated code. Do not modify. +// source: message_common.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use packetBaseDescriptor instead') +const PacketBase$json = { + '1': 'PacketBase', + '2': [ + {'1': 'typeName', '3': 1, '4': 1, '5': 9, '10': 'typeName'}, + {'1': 'nonce', '3': 2, '4': 1, '5': 5, '10': 'nonce'}, + {'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'}, + ], +}; + +/// Descriptor for `PacketBase`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List packetBaseDescriptor = $convert.base64Decode( + 'CgpQYWNrZXRCYXNlEhoKCHR5cGVOYW1lGAEgASgJUgh0eXBlTmFtZRIUCgVub25jZRgCIAEoBV' + 'IFbm9uY2USEgoEZGF0YRgDIAEoDFIEZGF0YQ=='); + +@$core.Deprecated('Use templateDataDescriptor instead') +const TemplateData$json = { + '1': 'TemplateData', + '2': [ + {'1': 'index', '3': 1, '4': 1, '5': 5, '10': 'index'}, + {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'}, + ], +}; + +/// Descriptor for `TemplateData`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List templateDataDescriptor = $convert.base64Decode( + 'CgxUZW1wbGF0ZURhdGESFAoFaW5kZXgYASABKAVSBWluZGV4EhgKB21lc3NhZ2UYAiABKAlSB2' + '1lc3NhZ2U='); + diff --git a/lib/socket/packets/message_common.pbserver.dart b/lib/socket/packets/message_common.pbserver.dart new file mode 100644 index 0000000..34528ee --- /dev/null +++ b/lib/socket/packets/message_common.pbserver.dart @@ -0,0 +1,14 @@ +// +// Generated code. Do not modify. +// source: message_common.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +export 'message_common.pb.dart'; + diff --git a/lib/socket/protobuf_client.dart b/lib/socket/protobuf_client.dart new file mode 100644 index 0000000..a447850 --- /dev/null +++ b/lib/socket/protobuf_client.dart @@ -0,0 +1,126 @@ + +// ignore_for_file: avoid_init_to_null, prefer_final_fields, avoid_print + +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:dart_framework/utils/system_util.dart'; +import 'package:protobuf/protobuf.dart'; +import 'package:dart_framework/communicator.dart'; +import 'package:dart_framework/socket/packets/message_common.pb.dart'; + +class ProtobufClient extends Communicator +{ + final int _headerSize = 4; + final Socket _socket; + int? _length = null; + late List _arrivedData = []; + List _onDisconnectListenerList = []; + + + ProtobufClient(this._socket) + { + print('Connected New Client'); + super.initialize({ + (TemplateData).toString() : TemplateData.fromBuffer + }); + _socket.listen(onData, onError: onError) + .asFuture().then(onDisconnected); + } + + void addDisconnectListener(void Function(ProtobufClient) handler) + { + if(!_onDisconnectListenerList.contains(handler)) + { + _onDisconnectListenerList.add(handler); + } + } + + void removeDisconnectListener(void Function(ProtobufClient) handler) + { + if(_onDisconnectListenerList.contains(handler)) + { + _onDisconnectListenerList.remove(handler); + } + } + + void onDisconnected(dynamic data) + { + //client disconnected + for (var item in _onDisconnectListenerList) { + item.call(this); + } + } + + void onError(dynamic e) + { + print('=========> onError: $e'); + } + + void onData(Uint8List data) async + { + try + { + // printPacket('## Received', data); + if(_length == null) + { + var header = data.sublist(0, _headerSize); + _length = header.buffer.asByteData().getInt32(0); + _arrivedData.addAll(data.sublist(_headerSize)); + } + else + { + _arrivedData.addAll(data); + } + + if(_arrivedData.length == _length) + { + var common = PacketBase.fromBuffer(_arrivedData); + var nonce = common.nonce; + onReceivedData(common.typeName, common.data); + _length = null; + _arrivedData.clear(); + } + } on Exception catch(e) { + print(e); + } + } + + @override + Future send(T data) async { + List packet = []; + var base = PacketBase(); + base.typeName = data.info_.qualifiedMessageName; + base.nonce = 0; + base.data = data.writeToBuffer(); + var baseBytes = base.writeToBuffer(); + int length = baseBytes.length + _headerSize; + var header = Uint8List(_headerSize) + ..buffer.asByteData().setInt32(0, length); + packet.addAll(header); + packet.addAll(baseBytes); + + // printPacket('Send', packet); + + _socket.add(packet); + await _socket.flush(); + return simpleFuture; + } + + void printPacket(String prefix, List packet) + { + var s = StringBuffer(); + for(var item in packet) + { + s.write('$item, '); + } + print('$prefix: ${s.toString()}'); + } + + void dispose() + { + _onDisconnectListenerList.clear(); + _arrivedData.clear(); + _socket.close(); + } +} diff --git a/lib/socket/protobuf_server.dart b/lib/socket/protobuf_server.dart new file mode 100644 index 0000000..0cc3053 --- /dev/null +++ b/lib/socket/protobuf_server.dart @@ -0,0 +1,42 @@ +// ignore_for_file: avoid_print, prefer_final_fields + +import 'dart:io'; +import 'package:dart_framework/socket/packets/message_common.pb.dart'; +import 'package:dart_framework/socket/protobuf_client.dart'; + +class ProtobufServer +{ + late ServerSocket _server; + List _clientList = []; + String _host; + int _port; + + ProtobufServer(this._host, this._port); + + Future start() async + { + _server = await ServerSocket.bind(_host, _port); + _server.listen((Socket socket) { + var client = ProtobufClient(socket); + client.addDisconnectListener(onDisconnectedClient); + client.addListener(onTestSocket); + _clientList.add(client); + }); + } + + void onDisconnectedClient(ProtobufClient client) + { + _clientList.remove(client); + client.dispose(); + print('Client disconnected'); + } + + void onTestSocket(TemplateData data) + { + print(data.message); + var test = TemplateData(); + test.index = 3125; + test.message = 'This message from flutter'; + _clientList[0].send(test); + } +}