mirror of
https://github.com/EpochModTeam/DayZ-Epoch.git
synced 2025-12-14 20:13:13 +03:00
174 lines
5.0 KiB
Plaintext
174 lines
5.0 KiB
Plaintext
#include "Util.hpp"
|
|
#include "Request.hpp"
|
|
#include "Array.hpp"
|
|
#include "Mutex.hpp"
|
|
#include "Dictionary.hpp"
|
|
#include "Debug.hpp"
|
|
|
|
#define Request_New(id) [dz_owner, id]
|
|
#define Request_GetOwner(request) ((request) select 0)
|
|
#define Request_GetID(request) ((request) select 1)
|
|
#define Request_SetResult(request, result) ((request) set [2, result])
|
|
#define Request_GetResult(request) ((request) select 2)
|
|
|
|
#define Reply_GetID(reply) ((reply) select 0)
|
|
#define Reply_GetResult(reply) ((reply) select 1)
|
|
|
|
#define Request_Server_GetFunc(request) ((request) select 2)
|
|
#define Request_Server_GetArgs(request) ((request) select 3)
|
|
#define Request_Server_ExpectsReply(request) (Request_GetID(request) >= 0)
|
|
|
|
//TODO: make work for non-dedicated server as well?
|
|
|
|
if (!isServer) then //CLIENT
|
|
{
|
|
dz_request_mutex = Mutex_New();
|
|
dz_request_list = [];
|
|
|
|
//Send request
|
|
dz_fn_request_send = // [type, args, reply]
|
|
{
|
|
Debug_Assert(Request_IsInitialized());
|
|
Debug_CheckParams3(Array_New2("SCALAR","STRING"),"ANY","BOOL");
|
|
|
|
private ["_id", "_request"];
|
|
|
|
//Expecting reply
|
|
if (_this select 2) exitWith
|
|
{
|
|
//Acquire lock
|
|
Mutex_WaitLock_Fast(dz_request_mutex);
|
|
|
|
//Find first valid id and assign the new request to it
|
|
_id = dz_request_list find 0;
|
|
if (_id < 0) then { _id = count dz_request_list; };
|
|
_request = [dz_owner, _id];
|
|
dz_request_list set [_id, _request];
|
|
|
|
Mutex_Unlock(dz_request_mutex);
|
|
|
|
Util_PublicVariableServer_Fast("dz_pvs_request", _request + Array_New2(_this select 0, _this select 1));
|
|
|
|
/*//send request to server
|
|
dz_pvs_request = _request + [_this select 0, _this select 1];
|
|
publicVariableServer "dz_pvs_request";*/
|
|
|
|
//return the request object
|
|
_request
|
|
};
|
|
|
|
//Not expecting reply
|
|
|
|
Util_PublicVariableServer_Fast("dz_pvs_request", Array_New4(dz_owner, -1, _this select 0, _this select 1));
|
|
|
|
/*//Acquire lock
|
|
Mutex_WaitLock_Fast(dz_request_mutex);
|
|
|
|
//Send request to server
|
|
dz_pvs_request = Request_New(-1) + [_this select 0, _this select 1];
|
|
publicVariableServer "dz_pvs_request";
|
|
|
|
//Unlock
|
|
Mutex_Unlock(dz_request_mutex);*/
|
|
|
|
//Return nil
|
|
nil
|
|
};
|
|
|
|
//receive reply
|
|
"dz_pvc_request" addPublicVariableEventHandler
|
|
{
|
|
_id = Reply_GetID(_this select 1);
|
|
|
|
//retrieve and remove request from global list
|
|
_request = dz_request_list select _id;
|
|
dz_request_list set [_id, 0];
|
|
|
|
//set result in request object
|
|
Request_SetResult(_request, Reply_GetResult(_this select 1));
|
|
};
|
|
}
|
|
else //SERVER
|
|
{
|
|
//dz_request_mutex = Mutex_New();
|
|
dz_request_handlers = Dictionary_New();
|
|
|
|
//receive request
|
|
"dz_pvs_request" addPublicVariableEventHandler
|
|
{
|
|
//request handler [handler, async]
|
|
_handler = Dictionary_Get(dz_request_handlers, Request_Server_GetFunc(_this select 1));
|
|
|
|
//No handler found
|
|
if (isNil "_handler") exitWith
|
|
{
|
|
diag_log format ["ERROR: Received an invalid request:%1 ClientID:%2",
|
|
Request_Server_GetFunc(_this select 1),
|
|
Request_GetOwner(_this select 1) ];
|
|
|
|
//Send reply to prevent client deadlock
|
|
if (Request_Server_ExpectsReply(_this select 1)) then
|
|
{
|
|
Util_PublicVariableClient_Fast("dz_pvc_request", DEFAULT_REPLY, Request_GetOwner(_this select 1));
|
|
|
|
//Return default value (empty array)
|
|
/*_temp = dz_pvc_request;
|
|
dz_pvc_request = DEFAULT_REPLY;
|
|
Request_GetOwner(_this select 1) publicVariableClient "dz_pvc_request";
|
|
dz_pvc_request = _temp;*/
|
|
};
|
|
};
|
|
|
|
//Async
|
|
if (_handler select 1) then
|
|
{
|
|
//Spawn a new thread to handle request asynchronously
|
|
[_this select 1, _handler select 0] spawn
|
|
{
|
|
__reply = Request_Server_ExpectsReply(_this select 0);
|
|
_result = Request_Server_GetArgs(_this select 0) call (_this select 1);
|
|
|
|
if (!__reply) exitWith {};
|
|
|
|
_result = [Request_GetID(_this select 0), _result];
|
|
|
|
Util_PublicVariableClient_Fast("dz_pvc_request", _result, Request_GetOwner(_this select 0));
|
|
|
|
/*//Acquire lock to prevent race conditions with other asynchronous handlers
|
|
Mutex_WaitLock_Fast(dz_request_mutex);
|
|
|
|
//Send reply
|
|
dz_pvc_request = _result;
|
|
Request_GetOwner(_this select 0) publicVariableClient "dz_pvc_request";
|
|
|
|
//Unlock
|
|
Mutex_Unlock(dz_request_mutex);*/
|
|
};
|
|
}
|
|
else //Sync
|
|
{
|
|
//Whether client expects a reply.
|
|
//If the handler knows that the player has disconnected they can set this to false to prevent replying.
|
|
__reply = Request_Server_ExpectsReply(_this select 1);
|
|
|
|
//Execute handler
|
|
_result = Request_Server_GetArgs(_this select 1) call (_handler select 0);
|
|
|
|
if (!__reply) exitWith {};
|
|
|
|
_result = [Request_GetID(_this select 1), _result];
|
|
|
|
Util_PublicVariableClient_Fast("dz_pvc_request", _result, Request_GetOwner(_this select 1));
|
|
|
|
//store previous value in case it's being used by a scheduled thread
|
|
/*_temp = dz_pvc_request;
|
|
|
|
//Send reply
|
|
dz_pvc_request = _result;
|
|
Request_GetOwner(_this select 1) publicVariableClient "dz_pvc_request";
|
|
|
|
//restore previous value
|
|
dz_pvc_request = _temp;*/
|
|
};
|
|
};
|
|
}; |