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