@@ -1,11 +0,0 @@ | |||
using System; | |||
namespace Svelto.ServiceLayer.Experimental | |||
{ | |||
public interface IServiceEventContainer : IDisposable | |||
{ | |||
//Delegate constraints to store delegates without needing a signature | |||
void ListenTo<TListener, TDelegate>(TDelegate callBack) | |||
where TListener : class, IServiceEventListener<TDelegate> where TDelegate : Delegate; | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
namespace Svelto.ServiceLayer.Experimental | |||
{ | |||
interface IServiceEventContainerFactory | |||
{ | |||
IServiceEventContainer Create(); | |||
} | |||
} |
@@ -1,14 +0,0 @@ | |||
using System; | |||
namespace Svelto.ServiceLayer.Experimental | |||
{ | |||
public interface IServiceEventListener<in TDelegate> : IServiceEventListenerBase where TDelegate : Delegate | |||
{ | |||
void SetCallback(TDelegate callback); | |||
} | |||
// This interface exists so we can use one type which can represent any of the interfaces above | |||
public interface IServiceEventListenerBase : IDisposable | |||
{ | |||
} | |||
} |
@@ -1,41 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
namespace Svelto.ServiceLayer.Experimental | |||
{ | |||
public abstract class ServiceEventContainer : IServiceEventContainer | |||
{ | |||
public void Dispose() | |||
{ | |||
foreach (var listener in _listeners) | |||
{ | |||
listener.Dispose(); | |||
} | |||
_listeners.Clear(); | |||
} | |||
protected ServiceEventContainer() | |||
{ | |||
//call all the AddRelation in the implementation if you wish | |||
} | |||
public void ListenTo<TListener, TDelegate>(TDelegate callBack) | |||
where TListener : class, IServiceEventListener<TDelegate> where TDelegate : Delegate | |||
{ | |||
var concreteType = _registeredTypes[typeof(TListener)]; | |||
var listener = (TListener)Activator.CreateInstance(concreteType); | |||
listener.SetCallback(callBack); | |||
_listeners.Add(listener); | |||
} | |||
protected void AddRelation<TInterface, TConcrete>() where TInterface : IServiceEventListenerBase | |||
where TConcrete : TInterface | |||
{ | |||
_registeredTypes.Add(typeof(TInterface), typeof(TConcrete)); | |||
} | |||
readonly List<IServiceEventListenerBase> _listeners = new List<IServiceEventListenerBase>(); | |||
readonly Dictionary<Type, Type> _registeredTypes = new Dictionary<Type, Type>(); | |||
} | |||
} |
@@ -1,15 +0,0 @@ | |||
using System.Collections.Generic; | |||
using Svelto.Tasks; | |||
namespace Svelto.ServiceLayer | |||
{ | |||
public interface IServiceRequest | |||
{ | |||
IEnumerator<TaskContract> Execute(); | |||
} | |||
public interface IServiceRequest<in TDependency>: IServiceRequest | |||
{ | |||
IServiceRequest Inject(TDependency registerData); | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
namespace Svelto.ServiceLayer | |||
{ | |||
public interface IServiceRequestsFactory | |||
{ | |||
RequestInterface Create<RequestInterface>() where RequestInterface:class, IServiceRequest; | |||
} | |||
} | |||
@@ -1,10 +0,0 @@ | |||
using System; | |||
namespace Svelto.ServiceLayer | |||
{ | |||
public class ServiceRequestFactoryArgumentException: ArgumentException | |||
{ | |||
public ServiceRequestFactoryArgumentException(string message):base(message) | |||
{} | |||
} | |||
} |
@@ -1,50 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
namespace Svelto.ServiceLayer | |||
{ | |||
public abstract class ServiceRequestsFactory : IServiceRequestsFactory | |||
{ | |||
public RequestInterface Create<RequestInterface>() where RequestInterface : class, IServiceRequest | |||
{ | |||
var ret = RetrieveObjectType<RequestInterface>(); | |||
return ret.CreateInstance() as RequestInterface; | |||
} | |||
protected void AddRelation<RequestInterface, RequestClass>() where RequestClass : class, RequestInterface, new() | |||
where RequestInterface : IServiceRequest | |||
{ | |||
_requestMap[typeof(RequestInterface)] = new Value<RequestClass>(); | |||
} | |||
IHoldValue RetrieveObjectType<RequestInterface>() | |||
{ | |||
if (_requestMap.ContainsKey(typeof(RequestInterface)) == false) | |||
throw new ServiceRequestFactoryArgumentException("Request not registered"); | |||
var ret = _requestMap[typeof(RequestInterface)]; | |||
if (ret == null) | |||
throw new ServiceRequestFactoryArgumentException("Request not found"); | |||
return ret; | |||
} | |||
readonly Dictionary<Type, IHoldValue> _requestMap = new Dictionary<Type, IHoldValue>(); | |||
interface IHoldValue | |||
{ | |||
IServiceRequest CreateInstance(); | |||
} | |||
class Value<RequestClass> : IHoldValue where RequestClass : class, IServiceRequest, new() | |||
{ | |||
public IServiceRequest CreateInstance() | |||
{ | |||
return new RequestClass(); | |||
} | |||
} | |||
} | |||
} |
@@ -1,17 +0,0 @@ | |||
{ | |||
"name": "Svelto.Services", | |||
"references": [ | |||
"Svelto.Common", | |||
"Svelto.Tasks", | |||
"Utf8Json" | |||
], | |||
"optionalUnityReferences": [], | |||
"includePlatforms": [], | |||
"excludePlatforms": [], | |||
"allowUnsafeCode": false, | |||
"overrideReferences": false, | |||
"precompiledReferences": [], | |||
"autoReferenced": true, | |||
"defineConstraints": [], | |||
"versionDefines": [] | |||
} |
@@ -1,19 +0,0 @@ | |||
namespace Svelto.Services | |||
{ | |||
public interface IResponseHandler<ResponseType> : IResponseHandler | |||
{ | |||
ResponseType response { get; } | |||
} | |||
public interface IResponseHandler | |||
{ | |||
// Called once per frame when data has been received from the network. | |||
bool ReceiveData(byte[] data, int dataLength); | |||
// Called when all data has been received from the server and delivered via ReceiveData. | |||
void CompleteContent(); | |||
// Called when a Content-Length header is received from the server. | |||
void ReceiveContentLength(int contentLength); | |||
} | |||
} |
@@ -1,176 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using UnityEngine; | |||
using System.Security.Cryptography.X509Certificates; | |||
using System.Net.Security; | |||
using Svelto.Tasks; | |||
using Svelto.Tasks.Enumerators; | |||
using UnityEngine.Networking; | |||
namespace Svelto.Services | |||
{ | |||
public enum Method | |||
{ | |||
GET, | |||
POST | |||
} | |||
public enum Result | |||
{ | |||
Success, | |||
ServerHandledError, | |||
ServerException, | |||
ClientFailure, | |||
} | |||
public sealed class StandardWebRequest | |||
{ | |||
static StandardWebRequest() | |||
{ | |||
ServicePointManager.ServerCertificateValidationCallback = CannotVerifyMessageCertificate; | |||
ServicePointManager.DefaultConnectionLimit = 64; | |||
} | |||
public Result result { get; private set; } | |||
public int maxAttempts = 3; | |||
public int waitOnRetrySeconds = 1; | |||
public int timeoutSeconds = 10; | |||
public Method method = Method.POST; | |||
public Func<HttpStatusCode, bool> processStatusCodes = code => false; | |||
public IResponseHandler responseHandler; | |||
public string URL; | |||
public IEnumerator<TaskContract> Execute(byte[] bodyRaw) | |||
{ | |||
int attemptNumber = 0; | |||
do | |||
{ | |||
using (UnityWebRequest request = new UnityWebRequest()) | |||
{ | |||
switch (method) | |||
{ | |||
case Method.GET: | |||
request.method = UnityWebRequest.kHttpVerbGET; | |||
break; | |||
case Method.POST: | |||
request.method = UnityWebRequest.kHttpVerbPOST; | |||
break; | |||
default: | |||
request.method = UnityWebRequest.kHttpVerbPOST; | |||
break; | |||
} | |||
request.url = URL; | |||
request.uploadHandler = new UploadHandlerRaw(bodyRaw); | |||
request.downloadHandler = new UnityDownloadHandler(responseHandler); | |||
request.SetRequestHeader("Content-Type", "application/json"); | |||
request.timeout = timeoutSeconds; | |||
AsyncOperation op = request.SendWebRequest(); | |||
while (op.isDone == false) | |||
{ | |||
yield return Yield.It; | |||
} | |||
if (request.isNetworkError == false) | |||
{ | |||
if (ProcessResponse(request) == true) | |||
{ | |||
result = Result.Success; | |||
Svelto.Console.LogDebug("web request completed"); | |||
yield break; | |||
} | |||
else | |||
{ | |||
Svelto.Console.LogDebug("web request completed with failure ", URL); | |||
try | |||
{ | |||
responseHandler?.CompleteContent(); | |||
result = Result.ServerHandledError; | |||
} | |||
catch | |||
{ | |||
result = Result.ServerException; | |||
} | |||
yield break; //no retry on server error! | |||
} | |||
} | |||
else | |||
if (++attemptNumber < maxAttempts) | |||
{ | |||
var wait = new ReusableWaitForSecondsEnumerator(waitOnRetrySeconds); | |||
while (wait.MoveNext() == true) yield return Yield.It; | |||
Svelto.Console.LogDebug("web request retry"); | |||
continue; //retry on client error | |||
} | |||
else | |||
{ | |||
result = Result.ClientFailure; | |||
yield break; | |||
} | |||
} | |||
} | |||
while (true); | |||
} | |||
bool ProcessResponse(UnityWebRequest request) | |||
{ | |||
HttpStatusCode statusCode = (HttpStatusCode) request.responseCode; | |||
if (statusCode != HttpStatusCode.OK) | |||
if (processStatusCodes(statusCode) == false) | |||
return false; | |||
return true; | |||
} | |||
// BOC:: After turning on SSL on the gameserver we started getting certificate problems. | |||
// Found this solution on Stack Overflow with Mike R | |||
// (https://stackoverflow.com/questions/4926676/mono-https-webrequest-fails-with-the-authentication-or-decryption-has-failed) | |||
static bool CannotVerifyMessageCertificate(System.Object sender, X509Certificate certificate, X509Chain chain, | |||
SslPolicyErrors sslPolicyErrors) | |||
{ | |||
bool isOk = true; | |||
// If there are errors in the certificate chain, | |||
// look at each error to determine the cause. | |||
if (sslPolicyErrors != SslPolicyErrors.None) | |||
{ | |||
for (int i = 0; i < chain.ChainStatus.Length; i++) | |||
{ | |||
if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown) | |||
continue; | |||
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; | |||
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; | |||
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0); | |||
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; | |||
bool chainIsValid = chain.Build((X509Certificate2) certificate); | |||
if (!chainIsValid) | |||
{ | |||
isOk = false; | |||
break; | |||
} | |||
} | |||
} | |||
return isOk; | |||
} | |||
} | |||
} |
@@ -1,61 +0,0 @@ | |||
using System; | |||
using System.IO; | |||
using System.Text; | |||
using UnityEngine.Networking; | |||
namespace Svelto.Services | |||
{ | |||
public class UnityDownloadHandler : DownloadHandlerScript | |||
{ | |||
public string GetError() | |||
{ | |||
if (String.IsNullOrEmpty(_errorString) == true) | |||
{ | |||
MemoryStream errorBuffer = new MemoryStream(_dataLength); | |||
errorBuffer.Write(data, 0, _dataLength); | |||
_errorString = Encoding.UTF8.GetString(errorBuffer.GetBuffer(), 0, (int) errorBuffer.Length); | |||
errorBuffer.Dispose(); | |||
} | |||
return _errorString; | |||
} | |||
protected override bool ReceiveData(byte[] data, int dataLength) | |||
{ | |||
if (data.Length < 1) | |||
return false; // No need to receive data | |||
_data = data; | |||
_dataLength = dataLength; | |||
if (_handler == null) | |||
return false; // No need to receive data | |||
return _handler.ReceiveData(data, dataLength); | |||
} | |||
public UnityDownloadHandler(IResponseHandler handler) | |||
{ | |||
_handler = handler; | |||
} | |||
protected override byte[] GetData() | |||
{ | |||
return _data; | |||
} | |||
// Called when all data has been received from the server and delivered via ReceiveData. | |||
protected override void CompleteContent() | |||
{ | |||
_handler?.CompleteContent(); | |||
} | |||
readonly IResponseHandler _handler; | |||
byte[] _data; | |||
int _dataLength; | |||
string _errorString; | |||
} | |||
} |