1+ using Google . Protobuf ;
2+ using System ;
3+ using System . Collections ;
4+ using System . Text ;
5+ using UnityEngine . Networking ;
6+ using System . Collections . Generic ;
7+ using System . Linq ;
8+
9+ namespace GameWorkstore . AsyncNetworkEngine
10+ {
11+ public enum CloudProvider
12+ {
13+ Gcp = 0 ,
14+ Aws = 1
15+ }
16+
17+ public class FileData
18+ {
19+ public string URL ;
20+ public byte [ ] Data ;
21+ }
22+
23+ public static class AsyncNetworkEngineMap
24+ {
25+ internal static bool IsSingleCloud = true ;
26+ internal static CloudProvider SingleCloudProvider = CloudProvider . Aws ;
27+ internal static Dictionary < string , CloudProvider > MapCloudProvider ;
28+
29+ /// <summary>
30+ /// Setup a single cloud provider for all functions.
31+ /// </summary>
32+ /// <param name="cloudProvider">Target cloud provider implementation.</param>
33+ public static void SetupCloud ( CloudProvider cloudProvider )
34+ {
35+ IsSingleCloud = true ;
36+ SingleCloudProvider = cloudProvider ;
37+ }
38+
39+ /// <summary>
40+ /// Setup a multi cloud provider for all functions.
41+ /// </summary>
42+ /// <param name="mapCloudProvider">Maps base url to cloud provider. Use the lowest possible string to differentiate clouds.</param>
43+ public static void SetupCloudMap ( Dictionary < string , CloudProvider > mapCloudProvider )
44+ {
45+ IsSingleCloud = false ;
46+ MapCloudProvider = mapCloudProvider ;
47+ }
48+ }
49+
50+ public static class AsyncNetworkEngine
51+ {
52+ private static Patterns . EventService _eventService ;
53+
54+ public static void Download ( string url , Action < Transmission , FileData > callback )
55+ {
56+ if ( _eventService == null ) _eventService = Patterns . ServiceProvider . GetService < Patterns . EventService > ( ) ;
57+ _eventService . StartCoroutine ( SendRequest ( new [ ] { url } , ( result , files ) => {
58+ callback ? . Invoke ( result , files . FirstOrDefault ( ) ) ;
59+ } ) ) ;
60+ }
61+
62+ public static void Download ( string [ ] urls , Action < Transmission , Patterns . HighSpeedArray < FileData > > callback )
63+ {
64+ if ( _eventService == null ) _eventService = Patterns . ServiceProvider . GetService < Patterns . EventService > ( ) ;
65+ _eventService . StartCoroutine ( SendRequest ( urls , callback ) ) ;
66+ }
67+
68+ public static IEnumerator SendRequest ( string [ ] urls , Action < Transmission , Patterns . HighSpeedArray < FileData > > callback )
69+ {
70+ var data = new Patterns . HighSpeedArray < FileData > ( urls . Length ) ;
71+ foreach ( var url in urls )
72+ {
73+ using ( var rqt = UnityWebRequest . Get ( url ) )
74+ {
75+ yield return rqt . SendWebRequest ( ) ;
76+
77+ switch ( rqt . result )
78+ {
79+ case UnityWebRequest . Result . ConnectionError :
80+ Return ( Transmission . ErrorConnection , data , callback ) ;
81+ break ;
82+ case UnityWebRequest . Result . ProtocolError :
83+ Return ( Transmission . ErrorProtocol , data , callback ) ;
84+ break ;
85+ case UnityWebRequest . Result . DataProcessingError :
86+ Return ( Transmission . ErrorDecode , data , callback ) ;
87+ break ;
88+ case UnityWebRequest . Result . Success :
89+ data . Add ( new FileData ( )
90+ {
91+ URL = url ,
92+ Data = rqt . downloadHandler . data
93+ } ) ;
94+ break ;
95+ }
96+ }
97+ }
98+ Return ( Transmission . Success , data , callback ) ;
99+ }
100+
101+ private static void Return ( Transmission result , Patterns . HighSpeedArray < FileData > data , Action < Transmission , Patterns . HighSpeedArray < FileData > > callback )
102+ {
103+ if ( _eventService != null )
104+ {
105+ _eventService . QueueAction ( ( ) => callback . Invoke ( result , data ) ) ;
106+ }
107+ else
108+ {
109+ callback ? . Invoke ( result , data ) ;
110+ }
111+ }
112+ }
113+
114+ /// <summary>
115+ /// Implements a UnityRequest for google protobuf web functions.
116+ /// </summary>
117+ /// <typeparam name="TRqt">Request</typeparam>
118+ /// <typeparam name="TResp">Response</typeparam>
119+ public static class AsyncNetworkEngine < TRqt , TResp >
120+ where TRqt : IMessage < TRqt > , new ( )
121+ where TResp : IMessage < TResp > , new ( )
122+ {
123+ private static readonly MessageParser < TResp > _tuParser = new MessageParser < TResp > ( ( ) => new TResp ( ) ) ;
124+ private static readonly MessageParser < GenericErrorResponse > _tvParser = new MessageParser < GenericErrorResponse > ( ( ) => new GenericErrorResponse ( ) ) ;
125+ private static Patterns . EventService _eventService ;
126+
127+ public static void Send ( string url , TRqt request , Action < Transmission , TResp , GenericErrorResponse > callback )
128+ {
129+ if ( _eventService == null ) _eventService = Patterns . ServiceProvider . GetService < Patterns . EventService > ( ) ;
130+ _eventService . StartCoroutine ( SendRequest ( url , request , callback ) ) ;
131+ }
132+
133+ public static IEnumerator SendRequest ( string url , TRqt request , Action < Transmission , TResp , GenericErrorResponse > callback )
134+ {
135+ //Notice: APIGateway automatically converts binary data into base64 strings
136+ using ( var rqt = new UnityWebRequest ( url , "POST" )
137+ {
138+ uploadHandler = new UploadHandlerRaw ( request . ToByteArray ( ) ) ,
139+ downloadHandler = new DownloadHandlerBuffer ( )
140+ } )
141+ {
142+ yield return rqt . SendWebRequest ( ) ;
143+
144+ switch ( rqt . result )
145+ {
146+ case UnityWebRequest . Result . ConnectionError :
147+ Return ( Transmission . ErrorConnection , callback ) ;
148+ break ;
149+ case UnityWebRequest . Result . ProtocolError :
150+ HandleError ( GetCloudProvider ( ref url ) , rqt , callback ) ;
151+ break ;
152+ case UnityWebRequest . Result . Success :
153+ while ( ! rqt . downloadHandler . isDone ) yield return null ;
154+ HandleSuccess ( GetCloudProvider ( ref url ) , rqt , callback ) ;
155+ break ;
156+ }
157+ }
158+ }
159+
160+ private static CloudProvider GetCloudProvider ( ref string url )
161+ {
162+ if ( ! AsyncNetworkEngineMap . IsSingleCloud )
163+ {
164+ foreach ( var pair in AsyncNetworkEngineMap . MapCloudProvider )
165+ {
166+ if ( ! url . StartsWith ( pair . Key ) ) continue ;
167+ return pair . Value ;
168+ }
169+ }
170+ return AsyncNetworkEngineMap . SingleCloudProvider ;
171+ }
172+
173+ private static void HandleSuccess ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TResp , GenericErrorResponse > callback )
174+ {
175+ if ( rqt . downloadHandler . data == null )
176+ {
177+ Return ( Transmission . ErrorNoData , callback ) ;
178+ return ;
179+ }
180+
181+ var data = rqt . downloadHandler . data ;
182+ if ( provider == CloudProvider . Aws )
183+ {
184+ var s = Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ;
185+ if ( ! Base64StdEncoding . Decode ( s , out data ) )
186+ {
187+ Return ( Transmission . ErrorParser , default , new GenericErrorResponse ( ) { Error = "base64 string is invalid:" + s } , callback ) ;
188+ return ;
189+ }
190+ }
191+
192+ TResp packet ;
193+ try
194+ {
195+ packet = _tuParser . ParseFrom ( data ) ;
196+ }
197+ catch
198+ {
199+ Return ( Transmission . ErrorParser , callback ) ;
200+ return ;
201+ }
202+ Return ( Transmission . Success , packet , default , callback ) ;
203+ }
204+
205+ private static void HandleError ( CloudProvider provider , UnityWebRequest rqt , Action < Transmission , TResp , GenericErrorResponse > callback )
206+ {
207+ if ( rqt . downloadHandler . data == null )
208+ {
209+ Return ( Transmission . ErrorProtocol , callback ) ;
210+ return ;
211+ }
212+
213+ var data = rqt . downloadHandler . data ;
214+ if ( provider == CloudProvider . Aws )
215+ {
216+ var s = Encoding . ASCII . GetString ( rqt . downloadHandler . data ) ;
217+ if ( ! Base64StdEncoding . Decode ( s , out data ) )
218+ {
219+ Return ( Transmission . ErrorParser , default , new GenericErrorResponse ( ) { Error = "base64 string is invalid:" + s } , callback ) ;
220+ return ;
221+ }
222+ }
223+
224+ var transmission = ( Transmission ) rqt . responseCode ;
225+ GenericErrorResponse packet ;
226+ try
227+ {
228+ packet = _tvParser . ParseFrom ( data ) ;
229+ }
230+ catch
231+ {
232+ Return ( Transmission . ErrorParser , callback ) ;
233+ return ;
234+ }
235+ Return ( transmission , default , packet , callback ) ;
236+ }
237+
238+ private static void Return ( Transmission result , Action < Transmission , TResp , GenericErrorResponse > callback )
239+ {
240+ Return ( result , default , default , callback ) ;
241+ }
242+
243+ private static void Return ( Transmission result , TResp data , GenericErrorResponse error , Action < Transmission , TResp , GenericErrorResponse > callback )
244+ {
245+ if ( callback == null ) return ;
246+ if ( _eventService != null )
247+ {
248+ _eventService . QueueAction ( ( ) => callback . Invoke ( result , data , error ) ) ;
249+ }
250+ else
251+ {
252+ callback . Invoke ( result , data , error ) ;
253+ }
254+ }
255+ }
256+ }
0 commit comments