Esempio n. 1
0
        public void SendProvisionalResponse(CallInformation answerTo, ProvisionalResponse response)
        {
            PyPacket result = new PyPacket(PyPacket.PacketType.CALL_RSP);

            // ensure destination has clientID in it
            PyAddressClient source = answerTo.From as PyAddressClient;

            source.ClientID = answerTo.Client.AccountID;
            // switch source and dest
            result.Source      = answerTo.To;
            result.Destination = source;

            result.UserID      = source.ClientID;
            result.Payload     = new PyTuple(0);
            result.OutOfBounds = new PyDictionary
            {
                ["provisional"] = new PyTuple(3)
                {
                    [0] = response.Timeout, // macho timeout in seconds
                    [1] = response.EventID,
                    [2] = response.Arguments
                }
            };

            this.Socket.Send(result);
        }
Esempio n. 2
0
        private void HandlePingReq(PyPacket packet, Client client)
        {
            // alter package to include the times the data
            PyTuple         handleMessage = new PyTuple(3);
            PyAddressClient source        = packet.Source as PyAddressClient;

            // this time should come from the stream packetizer or the socket itself
            // but there's no way we're adding time tracking for all the goddamned packets
            // so this should be sufficient
            handleMessage[0] = DateTime.UtcNow.ToFileTime();
            handleMessage[1] = DateTime.UtcNow.ToFileTime();
            handleMessage[2] = "server::handle_message";

            PyTuple turnaround = new PyTuple(3);

            turnaround[0] = DateTime.UtcNow.ToFileTime();
            turnaround[1] = DateTime.UtcNow.ToFileTime();
            turnaround[2] = "server::turnaround";

            (packet.Payload[0] as PyList)?.Add(handleMessage);
            (packet.Payload[0] as PyList)?.Add(turnaround);

            // change to a response
            packet.Type = PyPacket.PacketType.PING_RSP;

            // switch source and destination
            packet.Source      = packet.Destination;
            packet.Destination = source;

            // queue the packet back
            this.Socket.Send(packet);
        }
Esempio n. 3
0
        public void SendException(CallInformation answerTo, PyDataType content)
        {
            // build a new packet with the correct information
            PyPacket result = new PyPacket(PyPacket.PacketType.ERRORRESPONSE);

            // ensure destination has clientID in it
            PyAddressClient source = answerTo.From as PyAddressClient;

            source.ClientID = answerTo.Client.AccountID;
            // switch source and dest
            result.Source      = answerTo.To;
            result.Destination = source;

            result.UserID  = source.ClientID;
            result.Payload = new PyTuple(3)
            {
                [0] = (int)answerTo.PacketType,
                [1] = (int)MachoErrorType.WrappedException,
                [2] = new PyTuple(1)
                {
                    [0] = new PySubStream(content)
                },
            };

            this.ClusterConnection.Send(result);
        }
Esempio n. 4
0
        public void SendCallResult(CallInformation answerTo, PyDataType content)
        {
            PyPacket result = new PyPacket(PyPacket.PacketType.CALL_RSP);

            // ensure destination has clientID in it
            PyAddressClient source = answerTo.From as PyAddressClient;

            source.ClientID = answerTo.Client.AccountID;
            // switch source and dest
            result.Source      = answerTo.To;
            result.Destination = source;

            result.UserID  = source.ClientID;
            result.Payload = new PyTuple(new PyDataType[] { new PySubStream(content) });

            this.Socket.Send(result);
        }
Esempio n. 5
0
        public void SendCallResult(CallInformation answerTo, PyDataType content)
        {
            // ensure destination has clientID in it
            PyAddressClient originalSource = answerTo.From as PyAddressClient;

            originalSource.ClientID = answerTo.Client.AccountID;

            this.ClusterConnection.Send(
                new PyPacket(PyPacket.PacketType.CALL_RSP)
            {
                // switch source and dest
                Source      = answerTo.To,
                Destination = originalSource,
                UserID      = originalSource.ClientID,
                Payload     = new PyTuple(1)
                {
                    [0] = new PySubStream(content)
                }
            }
                );
        }
Esempio n. 6
0
        private void HandleCallReq(PyPacket packet, Client client)
        {
            PyTuple callInfo = ((packet.Payload[0] as PyTuple)[1] as PySubStream).Stream as PyTuple;

            string          call               = callInfo[1] as PyString;
            PyTuple         args               = callInfo[2] as PyTuple;
            PyDictionary    sub                = callInfo[3] as PyDictionary;
            PyDataType      callResult         = null;
            PyAddressClient source             = packet.Source as PyAddressClient;
            string          destinationService = null;
            CallInformation callInformation;

            if (packet.Destination is PyAddressAny destAny)
            {
                destinationService = destAny.Service;
            }
            else if (packet.Destination is PyAddressNode destNode)
            {
                destinationService = destNode.Service;

                if (destNode.NodeID != Container.NodeID)
                {
                    Log.Fatal(
                        "Received a call request for a node that is not us, did the ClusterController get confused or something?!"
                        );
                    return;
                }
            }

            callInformation = new CallInformation
            {
                Client       = client,
                CallID       = source.CallID,
                NamedPayload = sub,
                PacketType   = packet.Type,
                Service      = destinationService,
                From         = packet.Source,
                To           = packet.Destination
            };

            try
            {
                if (destinationService == null)
                {
                    if (callInfo[0] is PyString == false)
                    {
                        Log.Fatal("Expected bound call with bound string, but got something different");
                        return;
                    }

                    string boundString = callInfo[0] as PyString;

                    // parse the bound string to get back proper node and bound ids
                    Match regexMatch = Regex.Match(boundString, "N=([0-9]+):([0-9]+)");

                    if (regexMatch.Groups.Count != 3)
                    {
                        Log.Fatal($"Cannot find nodeID and boundID in the boundString {boundString}");
                        return;
                    }

                    int nodeID  = int.Parse(regexMatch.Groups[1].Value);
                    int boundID = int.Parse(regexMatch.Groups[2].Value);

                    if (nodeID != this.Container.NodeID)
                    {
                        Log.Fatal("Got bound service call for a different node");
                        // TODO: MIGHT BE A GOOD IDEA TO RELAY THIS CALL TO THE CORRECT NODE
                        // TODO: INSIDE THE NETWORK, AT LEAST THAT'S WHAT CCP IS DOING BASED
                        // TODO: ON THE CLIENT'S CODE... NEEDS MORE INVESTIGATION
                        return;
                    }

#if DEBUG
                    CallLog.Trace("Payload");
                    CallLog.Trace(PrettyPrinter.FromDataType(args));
                    CallLog.Trace("Named payload");
                    CallLog.Trace(PrettyPrinter.FromDataType(sub));
#endif

                    callResult = this.BoundServiceManager.ServiceCall(
                        boundID, call, args, callInformation
                        );

#if DEBUG
                    ResultLog.Trace("Result");
                    ResultLog.Trace(PrettyPrinter.FromDataType(callResult));
#endif
                }
                else
                {
                    Log.Trace($"Calling {destinationService}::{call}");

#if DEBUG
                    CallLog.Trace("Payload");
                    CallLog.Trace(PrettyPrinter.FromDataType(args));
                    CallLog.Trace("Named payload");
                    CallLog.Trace(PrettyPrinter.FromDataType(sub));
#endif

                    callResult = this.ServiceManager.ServiceCall(
                        destinationService, call, args, callInformation
                        );

#if DEBUG
                    ResultLog.Trace("Result");
                    ResultLog.Trace(PrettyPrinter.FromDataType(callResult));
#endif
                }

                this.SendCallResult(callInformation, callResult);
            }
            catch (PyException e)
            {
                this.SendException(callInformation, e);
            }
            catch (ProvisionalResponse provisional)
            {
                this.SendProvisionalResponse(callInformation, provisional);
            }
        }
Esempio n. 7
0
        private void ReceiveNormalPacketCallback(PyDataType ar)
        {
            PyPacket packet = ar;

            if (packet.Type == PyPacket.PacketType.CALL_REQ)
            {
                PyPacket result;
                PyTuple  callInfo = ((packet.Payload[0] as PyTuple)[1] as PySubStream).Stream as PyTuple;

                string          call       = callInfo[1] as PyString;
                PyTuple         args       = callInfo[2] as PyTuple;
                PyDictionary    sub        = callInfo[3] as PyDictionary;
                PyDataType      callResult = null;
                PyAddressClient source     = packet.Source as PyAddressClient;

                try
                {
                    if (packet.Destination is PyAddressAny destAny)
                    {
                        Log.Trace($"Calling {destAny.Service.Value}::{call}");
                        callResult = this.Container.ServiceManager.ServiceCall(
                            destAny.Service, call, args, sub, this.Container.ClientManager.Get(packet.UserID)
                            );
                    }
                    else if (packet.Destination is PyAddressNode destNode)
                    {
                        Log.Trace($"Calling {destNode.Service.Value}::{call}");
                        callResult = this.Container.ServiceManager.ServiceCall(
                            destNode.Service, call, args, sub, this.Container.ClientManager.Get(packet.UserID)
                            );
                    }
                    else
                    {
                        Log.Error($"Received packet that wasn't directed to us");
                    }

                    result = new PyPacket(PyPacket.PacketType.CALL_RSP);

                    // ensure destination has clientID in it
                    source.ClientID = (int)packet.UserID;
                    // switch source and dest
                    result.Source      = packet.Destination;
                    result.Destination = source;

                    result.UserID = packet.UserID;

                    result.Payload = new PyTuple(new PyDataType[] { new PySubStream(callResult) });
                }
                catch (PyException e)
                {
                    // PyExceptions have to be relayed to the client
                    // this way it's easy to notify the user without needing any special code
                    result = new PyPacket(PyPacket.PacketType.ERRORRESPONSE);

                    source.ClientID    = (int)packet.UserID;
                    result.Source      = packet.Destination;
                    result.Destination = source;

                    result.UserID  = packet.UserID;
                    result.Payload = new PyTuple(new PyDataType[]
                    {
                        (int)packet.Type, (int)MachoErrorType.WrappedException, new PyTuple(new PyDataType[] { new PySubStream(e) }),
                    });
                }

                // any of the paths that lead to the send here must have the PyPacket initialized
                // so a null check is not needed
                this.Socket.Send(result);
            }
            else if (packet.Type == PyPacket.PacketType.SESSIONCHANGENOTIFICATION)
            {
                Log.Debug($"Updating session for client {packet.UserID}");

                // ensure the client is registered in the node and store his session
                if (this.Container.ClientManager.Contains(packet.UserID) == false)
                {
                    this.Container.ClientManager.Add(packet.UserID, new Client());
                }

                this.Container.ClientManager.Get(packet.UserID).UpdateSession(packet);
            }
        }