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
+ public static class AsyncNetworkEngine
45
+ {
46
+ private static EventService _eventService = null ;
47
+
48
+ public static void Download ( string uri , Action < Transmission , byte [ ] > result )
49
+ {
50
+ if ( _eventService == null ) _eventService = ServiceProvider . GetService < EventService > ( ) ;
51
+ _eventService . StartCoroutine ( SendRequest ( uri , result ) ) ;
52
+ }
53
+
54
+ public static IEnumerator SendRequest ( string uri , Action < Transmission , byte [ ] > result )
55
+ {
56
+ using var rqt = UnityWebRequest . Get ( uri ) ;
57
+ yield return rqt . SendWebRequest ( ) ;
58
+
59
+ switch ( rqt . result ) {
60
+ case UnityWebRequest . Result . ConnectionError :
61
+ Return ( Transmission . ErrorConnection , null , result ) ;
62
+ break ;
63
+ case UnityWebRequest . Result . Success :
64
+ HandleSuccess ( rqt , result ) ;
65
+ break ;
66
+ }
67
+ }
68
+
69
+ private static void HandleSuccess ( UnityWebRequest rqt , Action < Transmission , byte [ ] > result )
70
+ {
71
+ if ( rqt . downloadHandler . data == null )
72
+ {
73
+ Return ( Transmission . ErrorNoData , null , result ) ;
74
+ return ;
75
+ }
76
+ if ( rqt . downloadHandler . data . Length <= 0 )
77
+ {
78
+ Return ( Transmission . ErrorNoData , null , result ) ;
79
+ return ;
80
+ }
81
+ Return ( Transmission . Success , rqt . downloadHandler . data , result ) ;
82
+ }
83
+
84
+ private static void Return ( Transmission result , byte [ ] data , Action < Transmission , byte [ ] > callback )
85
+ {
86
+ callback ? . Invoke ( result , data ) ;
87
+ }
88
+ }
89
+
90
+ /// <summary>
91
+ /// Implements a UnityRequest for google protobuf web functions.
92
+ /// </summary>
93
+ /// <typeparam name="TR">Request</typeparam>
94
+ /// <typeparam name="TU">Response</typeparam>
95
+ public static class AsyncNetworkEngine < TR , TU >
96
+ where TR : IMessage < TR > , new ( )
97
+ where TU : IMessage < TU > , new ( )
98
+ {
99
+ private static readonly MessageParser < TU > _tuParser = new MessageParser < TU > ( ( ) => new TU ( ) ) ;
100
+ private static readonly MessageParser < GenericErrorResponse > _tvParser = new MessageParser < GenericErrorResponse > ( ( ) => new GenericErrorResponse ( ) ) ;
101
+ private static EventService _eventService = null ;
102
+
103
+ public static void Send ( string uri , TR request , Action < Transmission , TU , GenericErrorResponse > result )
104
+ {
105
+ if ( _eventService == null ) _eventService = ServiceProvider . GetService < EventService > ( ) ;
106
+ _eventService . StartCoroutine ( SendRequest ( uri , request , result ) ) ;
107
+ }
108
+
109
+ public static IEnumerator SendRequest ( string uri , TR request , Action < Transmission , TU , GenericErrorResponse > result )
110
+ {
111
+ //Notice: APIGateway automatically converts binary data into base64 strings
112
+ using var rqt = new UnityWebRequest ( uri , "POST" )
113
+ {
114
+ uploadHandler = new UploadHandlerRaw ( request . ToByteArray ( ) ) ,
115
+ downloadHandler = new DownloadHandlerBuffer ( )
116
+ } ;
117
+ yield return rqt . SendWebRequest ( ) ;
118
+
119
+ switch ( rqt . result )
120
+ {
121
+ case UnityWebRequest . Result . ConnectionError :
122
+ Return ( Transmission . ErrorConnection , result ) ;
123
+ break ;
124
+ case UnityWebRequest . Result . ProtocolError :
125
+ HandleError ( GetCloudProvider ( ref uri ) , rqt , result ) ;
126
+ break ;
127
+ case UnityWebRequest . Result . Success :
128
+ while ( ! rqt . downloadHandler . isDone ) yield return null ;
129
+ HandleSuccess ( GetCloudProvider ( ref uri ) , rqt , result ) ;
130
+ break ;
131
+ }
132
+ }
133
+
134
+ private static CloudProvider GetCloudProvider ( ref string url )
135
+ {
136
+ if ( ! AsyncNetworkEngineMap . IsSingleCloud )
137
+ {
138
+ foreach ( var pair in AsyncNetworkEngineMap . MapCloudProvider )
139
+ {
140
+ if ( ! url . StartsWith ( pair . Key ) ) continue ;
141
+ return pair . Value ;
142
+ }
143
+ }
144
+ return AsyncNetworkEngineMap . SingleCloudProvider ;
145
+ }
146
+
147
+ private static void HandleSuccess ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TU , GenericErrorResponse > result )
148
+ {
149
+ if ( rqt . downloadHandler . data == null )
150
+ {
151
+ Return ( Transmission . ErrorNoData , result ) ;
152
+ return ;
153
+ }
154
+ if ( rqt . downloadHandler . data . Length <= 0 )
155
+ {
156
+ Return ( Transmission . ErrorNoData , result ) ;
157
+ return ;
158
+ }
159
+
160
+ byte [ ] data = rqt . downloadHandler . data ;
161
+ if ( provider == CloudProvider . AWS )
162
+ {
163
+ data = Base64StdEncoding . Decode ( Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ) ;
164
+ }
165
+
166
+ TU packet ;
167
+ try
168
+ {
169
+ packet = _tuParser . ParseFrom ( data ) ;
170
+ }
171
+ catch
172
+ {
173
+ packet = default ;
174
+ }
175
+ Return ( packet != null ? Transmission . Success : Transmission . ErrorParser , packet , default , result ) ;
176
+ }
177
+
178
+ private static void HandleError ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TU , GenericErrorResponse > result )
179
+ {
180
+ if ( rqt . downloadHandler . data == null )
181
+ {
182
+ Return ( Transmission . ErrorProtocol , result ) ;
183
+ return ;
184
+ }
185
+ if ( rqt . downloadHandler . data . Length <= 0 )
186
+ {
187
+ Return ( Transmission . ErrorProtocol , result ) ;
188
+ return ;
189
+ }
190
+
191
+ byte [ ] data = rqt . downloadHandler . data ;
192
+ if ( provider == CloudProvider . AWS )
193
+ {
194
+ data = Base64StdEncoding . Decode ( Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ) ;
195
+ }
196
+
197
+ var transmission = ( Transmission ) rqt . responseCode ;
198
+ GenericErrorResponse packet ;
199
+ try
200
+ {
201
+ packet = _tvParser . ParseFrom ( data ) ;
202
+ }
203
+ catch
204
+ {
205
+ packet = default ;
206
+ }
207
+ Return ( packet != null ? transmission : Transmission . ErrorParser , default , packet , result ) ;
208
+ }
209
+
210
+ private static void Return ( Transmission result , Action < Transmission , TU , GenericErrorResponse > callback )
211
+ {
212
+ Return ( result , default , default , callback ) ;
213
+ }
214
+
215
+ private static void Return ( Transmission result , TU data , GenericErrorResponse error , Action < Transmission , TU , GenericErrorResponse > callback )
216
+ {
217
+ if ( callback == null ) return ;
218
+ _eventService . QueueAction ( ( ) => callback . Invoke ( result , data , error ) ) ;
219
+ //callback.Invoke(result, data, error);
220
+ }
221
+ }
222
+ }
0 commit comments