Exemple #1
0
        private void FlushReceivingQueue()
        {
            if (this.mReceivingSemaphore.WaitOne(0) == true)
            {
                // handle required packets
                while (this.mPacketizer.PacketCount > 0 && this.mPacketReceiveCallback != null)
                {
                    try
                    {
                        // unmarshal the packet
                        PyDataType packet = Unmarshal.ReadFromByteArray(this.mPacketizer.PopItem());
#if DEBUG
                        this.mPacketLog.Trace(PrettyPrinter.FromDataType(packet));
#endif
                        // and invoke the callback for the packet handling if it is present
                        this.mPacketReceiveCallback.Invoke(packet);
                    }
                    catch (Exception e)
                    {
                        this.HandleException(e);
                    }
                }

                // finally free the receiving semaphore
                this.mReceivingSemaphore.Release();
            }

            // semaphore not acquired, there's something already sending data, so we're sure the data will get there eventually
        }
Exemple #2
0
        /// <summary>
        /// Sends a PyObject through this socket
        /// </summary>
        /// <param name="packet">The packet data to send</param>
        public void Send(PyDataType packet)
        {
#if DEBUG
            this.mPacketLog.Trace(PrettyPrinter.FromDataType(packet));
#endif

            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);
            // marshal the packet first
            byte[] encodedPacket = PythonTypes.Marshal.Marshal.ToByteArray(packet);

            // compress the packet if it exceeds the maximum size
            if (encodedPacket.Length > Constants.Network.MAX_PACKET_SIZE)
            {
                encodedPacket = ZlibHelper.Compress(encodedPacket);
            }

            // write the size to the stream
            writer.Write(encodedPacket.Length);
            // finally copy the packet buffer
            writer.Write(encodedPacket);
            // after processing the whole packet queue the actual data
            this.Send(stream.ToArray());
        }
Exemple #3
0
        /// <summary>
        /// Sends a PyObject through this socket
        /// </summary>
        /// <param name="packet">The packet data to send</param>
        public void Send(PyDataType packet)
        {
#if DEBUG
            this.mPacketLog.Trace(PrettyPrinter.FromDataType(packet));
#endif
            // marshal the packet first
            byte[] encodedPacket = PythonTypes.Marshal.Marshal.ToByteArray(packet);

            // compress the packet if it exceeds the maximum size
            if (encodedPacket.Length > Constants.Network.MAX_PACKET_SIZE)
            {
                encodedPacket = ZlibHelper.Compress(encodedPacket);
            }

            // generate the final buffer
            byte[] packetBuffer = new byte[encodedPacket.Length + sizeof(int)];

            // write the packet size and the buffer to the new buffer
            Buffer.BlockCopy(BitConverter.GetBytes(encodedPacket.Length), 0, packetBuffer, 0, sizeof(int));
            Buffer.BlockCopy(encodedPacket, 0, packetBuffer, sizeof(int), encodedPacket.Length);

            // after processing the whole packet queue the actual data
            this.Send(packetBuffer);
        }
Exemple #4
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);
            }
        }
Exemple #5
0
        public PyDataType JoinChannels(PyList channels, PyInteger role, CallInformation call)
        {
            int callerCharacterID = call.Client.EnsureCharacterIsSelected();

            PyList result = new PyList();

            foreach (PyDataType channel in channels)
            {
                int        channelID;
                string     channelType;
                int?       entityID;
                PyDataType channelIDExtended = null;

                try
                {
                    this.ParseChannelIdentifier(channel, out channelID, out channelType, out entityID);
                }
                catch (InvalidDataException)
                {
                    throw new LSCCannotJoin("The specified channel cannot be found: " + PrettyPrinter.FromDataType(channel));
                }

                if (channelType == ChatDB.CHANNEL_TYPE_NORMAL)
                {
                    channelIDExtended = channelID;
                }
                else
                {
                    channelIDExtended = new PyTuple(1)
                    {
                        [0] = new PyTuple(2)
                        {
                            [0] = channelType,
                            [1] = entityID
                        }
                    };
                }

                // send notifications only on channels that should be receiving notifications
                // we don't want people in local to know about players unless they talk there
                if (channelType != ChatDB.CHANNEL_TYPE_REGIONID && channelType != ChatDB.CHANNEL_TYPE_CONSTELLATIONID && channelType != ChatDB.CHANNEL_TYPE_SOLARSYSTEMID2)
                {
                    PyDataType notification =
                        GenerateLSCNotification("JoinChannel", channelIDExtended, new PyTuple(0), call.Client);

                    if (channelType == ChatDB.CHANNEL_TYPE_NORMAL)
                    {
                        if (channelID < ChatDB.MIN_CHANNEL_ENTITY_ID)
                        {
                            // get users in the channel that are online now
                            PyList characters = this.DB.GetOnlineCharsOnChannel(channelID);

                            // notify them all
                            call.Client.ClusterConnection.SendNotification("OnLSC", "charid", characters, notification);
                        }
                    }
                    else
                    {
                        // notify all players on the channel
                        call.Client.ClusterConnection.SendNotification("OnLSC", channelType, new PyDataType [] { entityID }, notification);
                    }
                }

                try
                {
                    result.Add(
                        this.GetChannelInformation(
                            channelType, channelID, entityID, callerCharacterID, channelIDExtended, call
                            )
                        );
                }
                catch (Exception e)
                {
                    // most of the time this indicates a destroyed channel
                    // so build a destroy notification and let the client know this channel
                    // can be removed from it's lists
                    if (channelType == ChatDB.CHANNEL_TYPE_NORMAL && channelID != entityID)
                    {
                        // notify everyone in the channel only when it should
                        PyDataType notification =
                            GenerateLSCNotification("DestroyChannel", channelID, new PyTuple(0), call.Client);

                        // notify all characters in the channel
                        call.Client.ClusterConnection.SendNotification("OnLSC", "charid", callerCharacterID, call.Client, notification);
                    }

                    Log.Error($"LSC could not get channel information. Error: {e.Message}");
                }
            }

            return(result);
        }