1
+ using Google . Protobuf ;
2
+ using GameWorkstore . Patterns ;
3
+ using System ;
4
+ using System . Collections ;
5
+ using System . Text ;
6
+ using UnityEngine . Networking ;
7
+ using System . Collections . Generic ;
8
+
9
+ namespace GameWorkstore . AsyncNetworkEngine
10
+ {
11
+ public enum CloudProvider
12
+ {
13
+ GCP = 0 ,
14
+ AWS = 1
15
+ }
16
+
17
+ public static class AsyncNetworkEngineMap
18
+ {
19
+ internal static bool IsSingleCloud = true ;
20
+ internal static CloudProvider SingleCloudProvider = CloudProvider . AWS ;
21
+ internal static Dictionary < string , CloudProvider > MapCloudProvider = null ;
22
+
23
+ /// <summary>
24
+ /// Setup a single cloud provider for all functions.
25
+ /// </summary>
26
+ /// <param name="cloudProvider">Target cloud provider implementation.</param>
27
+ public static void SetupCloud ( CloudProvider cloudProvider )
28
+ {
29
+ IsSingleCloud = true ;
30
+ SingleCloudProvider = cloudProvider ;
31
+ }
32
+
33
+ /// <summary>
34
+ /// Setup a multi cloud provider for all functions.
35
+ /// </summary>
36
+ /// <param name="mapCloudProvider">Maps base url to cloud provider. Use the lowest possible string to differentiate clouds.</param>
37
+ public static void SetupCloudMap ( Dictionary < string , CloudProvider > mapCloudProvider )
38
+ {
39
+ IsSingleCloud = false ;
40
+ MapCloudProvider = mapCloudProvider ;
41
+ }
42
+ }
43
+
44
+ /// <summary>
45
+ /// Implements a UnityRequest for google protobuf web functions.
46
+ /// </summary>
47
+ /// <typeparam name="TR">Request</typeparam>
48
+ /// <typeparam name="TU">Response</typeparam>
49
+ public static class AsyncNetworkEngine < TR , TU >
50
+ where TR : IMessage < TR > , new ( )
51
+ where TU : IMessage < TU > , new ( )
52
+ {
53
+ private static readonly MessageParser < TU > _tuParser = new MessageParser < TU > ( ( ) => new TU ( ) ) ;
54
+ private static readonly MessageParser < GenericErrorResponse > _tvParser = new MessageParser < GenericErrorResponse > ( ( ) => new GenericErrorResponse ( ) ) ;
55
+ private static EventService _eventService = null ;
56
+
57
+ public static void Send ( string uri , TR request , Action < Transmission , TU , GenericErrorResponse > result )
58
+ {
59
+ if ( _eventService == null ) _eventService = ServiceProvider . GetService < EventService > ( ) ;
60
+ _eventService . StartCoroutine ( SendRequest ( uri , request , result ) ) ;
61
+ }
62
+
63
+ public static IEnumerator SendRequest ( string uri , TR request , Action < Transmission , TU , GenericErrorResponse > result )
64
+ {
65
+ //Notice: APIGateway automatically converts binary data into base64 strings
66
+ using var rqt = new UnityWebRequest ( uri , "POST" )
67
+ {
68
+ uploadHandler = new UploadHandlerRaw ( request . ToByteArray ( ) ) ,
69
+ downloadHandler = new DownloadHandlerBuffer ( )
70
+ } ;
71
+ yield return rqt . SendWebRequest ( ) ;
72
+
73
+ switch ( rqt . result )
74
+ {
75
+ case UnityWebRequest . Result . ConnectionError :
76
+ Return ( Transmission . ErrorConnection , result ) ;
77
+ break ;
78
+ case UnityWebRequest . Result . ProtocolError :
79
+ HandleError ( GetCloudProvider ( ref uri ) , rqt , result ) ;
80
+ break ;
81
+ case UnityWebRequest . Result . Success :
82
+ while ( ! rqt . downloadHandler . isDone ) yield return null ;
83
+ HandleSuccess ( GetCloudProvider ( ref uri ) , rqt , result ) ;
84
+ break ;
85
+ }
86
+ }
87
+
88
+ private static CloudProvider GetCloudProvider ( ref string url )
89
+ {
90
+ if ( ! AsyncNetworkEngineMap . IsSingleCloud )
91
+ {
92
+ foreach ( var pair in AsyncNetworkEngineMap . MapCloudProvider )
93
+ {
94
+ if ( ! url . StartsWith ( pair . Key ) ) continue ;
95
+ return pair . Value ;
96
+ }
97
+ }
98
+ return AsyncNetworkEngineMap . SingleCloudProvider ;
99
+ }
100
+
101
+ private static void HandleSuccess ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TU , GenericErrorResponse > result )
102
+ {
103
+ if ( rqt . downloadHandler . data == null )
104
+ {
105
+ Return ( Transmission . ErrorNoData , result ) ;
106
+ return ;
107
+ }
108
+ if ( rqt . downloadHandler . data . Length <= 0 )
109
+ {
110
+ Return ( Transmission . ErrorNoData , result ) ;
111
+ return ;
112
+ }
113
+
114
+ byte [ ] data = rqt . downloadHandler . data ;
115
+ if ( provider == CloudProvider . AWS )
116
+ {
117
+ data = Base64StdEncoding . Decode ( Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ) ;
118
+ }
119
+
120
+ TU packet ;
121
+ try
122
+ {
123
+ packet = _tuParser . ParseFrom ( data ) ;
124
+ }
125
+ catch
126
+ {
127
+ packet = default ;
128
+ }
129
+ Return ( packet != null ? Transmission . Success : Transmission . ErrorParser , packet , default , result ) ;
130
+ }
131
+
132
+ private static void HandleError ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TU , GenericErrorResponse > result )
133
+ {
134
+ if ( rqt . downloadHandler . data == null )
135
+ {
136
+ Return ( Transmission . ErrorProtocol , result ) ;
137
+ return ;
138
+ }
139
+ if ( rqt . downloadHandler . data . Length <= 0 )
140
+ {
141
+ Return ( Transmission . ErrorProtocol , result ) ;
142
+ return ;
143
+ }
144
+
145
+ byte [ ] data = rqt . downloadHandler . data ;
146
+ if ( provider == CloudProvider . AWS )
147
+ {
148
+ data = Base64StdEncoding . Decode ( Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ) ;
149
+ }
150
+
151
+ var transmission = ( Transmission ) rqt . responseCode ;
152
+ GenericErrorResponse packet ;
153
+ try
154
+ {
155
+ packet = _tvParser . ParseFrom ( data ) ;
156
+ }
157
+ catch
158
+ {
159
+ packet = default ;
160
+ }
161
+ Return ( packet != null ? transmission : Transmission . ErrorParser , default , packet , result ) ;
162
+ }
163
+
164
+ private static void Return ( Transmission result , Action < Transmission , TU , GenericErrorResponse > callback )
165
+ {
166
+ Return ( result , default , default , callback ) ;
167
+ }
168
+
169
+ private static void Return ( Transmission result , TU data , GenericErrorResponse error , Action < Transmission , TU , GenericErrorResponse > callback )
170
+ {
171
+ if ( callback == null ) return ;
172
+ _eventService . QueueAction ( ( ) => callback . Invoke ( result , data , error ) ) ;
173
+ //callback.Invoke(result, data, error);
174
+ }
175
+ }
176
+ }
0 commit comments