Пример #1
0
        /// <summary>
        ///     Reply to a enum query from freelancer clients with our server information.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="enum_payload"></param>
        public void SendCmdEnumResponse(IPEndPoint client, ushort enum_payload)
        {
            // TODO: we could need it
            const bool password = false;
            const bool nodpnsvr = true;

            var application_data = new byte[0];

            FLMsgType.AddAsciiStringLen0(ref application_data,
                                         "1:1:" + server_version + ":-1910309061:" + server_id + ":");
            FLMsgType.AddUnicodeStringLen0(ref application_data, server_description);

            byte[] pkt = { 0x00, 0x03 };
            FLMsgType.AddUInt16(ref pkt, enum_payload);
            FLMsgType.AddUInt32(ref pkt, 0x58 + (uint)server_name.Length * 2); // ReplyOffset
            FLMsgType.AddUInt32(ref pkt, (uint)application_data.Length);       // ReplySize/ResponseSize
            FLMsgType.AddUInt32(ref pkt, 0x50);                                // ApplicationDescSize
            FLMsgType.AddUInt32(ref pkt, (password ? 0x80u : 0x00u) | (nodpnsvr ? 0x40u : 0x00u));
            // ApplicationDescFlags
            FLMsgType.AddUInt32(ref pkt, max_players + 1);                // MaxPlayers
            FLMsgType.AddUInt32(ref pkt, (uint)dplay_sessions.Count + 1); // CurrentPlayers
            FLMsgType.AddUInt32(ref pkt, 0x58);                           // SessionNameOffset
            FLMsgType.AddUInt32(ref pkt, (uint)server_name.Length * 2);   // SessionNameSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // PasswordOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // PasswordSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // ReservedDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // ReservedDataSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // ApplicationReservedDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // ApplicationReservedDataSize
            FLMsgType.AddArray(ref pkt, ApplicationInstanceGUID);         // ApplicationInstanceGUID
            FLMsgType.AddArray(ref pkt, ApplicationGUID);                 // ApplicationGUID
            FLMsgType.AddUnicodeStringLen0(ref pkt, server_name);         // SessionName
            FLMsgType.AddArray(ref pkt, application_data);                // ApplicationData

            TxStart(pkt, client);
        }
Пример #2
0
        /// <summary>
        ///     Try to send a dframe or a keep alive if no user data is waiting to be sent.
        /// </summary>
        /// <param name="sess"></param>
        /// <returns>Return true if a dframe was sent</returns>
        public bool SendDFrame(Session sess)
        {
            lock (sess)
            {
                if (sess.UserData.Count > 0)
                {
                    // If the window is full, don't send any thing
                    if (IsAckWindowFull(sess))
                    {
                        return(false);
                    }

                    // If we have sent a user data message that had to be carried in multiple
                    // dframes then stop sending. We can't have more than one of these on the
                    // wire at one time (if I've intepreted the specs correctly).
                    if (sess.MultipleDframePacket)
                    {
                        return(false);
                    }

                    // The retry time should start at 100 + rtt * 2.5 according to the specs but we use
                    // 2 as this is a round number.
                    uint retry_time = 100 + (sess.Rtt * 2);
                    while (sess.UserData.Count > 0)
                    {
                        byte[] ud = sess.UserData.First();
                        sess.UserData.RemoveFirst();

                        // Break the user data block into sizes smaller than the ethernet mtu. We
                        // assume an MTU of 1450 as some infrastructure steals some bytes.
                        int  offset       = 0;
                        bool first_packet = true;
                        bool last_packet  = false;
                        while (offset < ud.Length)
                        {
                            int length;
                            if ((ud.Length - offset) > 1450)
                            {
                                length = 1450;
                                sess.MultipleDframePacket = true;
                            }
                            else
                            {
                                length      = ud.Length - offset;
                                last_packet = true;
                            }

                            byte[] pkt = { 0x07, 0x00, sess.NextTxSeq, sess.NextRxSeq };

                            // If this is the first packet, set the flag to indicate this.
                            if (first_packet)
                            {
                                pkt[0] |= 0x10;
                            }

                            // If this is the last packet, set the flag to indicate this
                            if (last_packet)
                            {
                                pkt[0] |= 0x20;
                            }

                            // If the session isn't fully connected then this must be a session establishment
                            // message
                            if (sess.SessionState == Session.State.CONNECTING_SESSINFO)
                            {
                                pkt[0] |= 0x40;
                            }

                            FLMsgType.AddArray(ref pkt, ud, offset, length);

                            var spkt = new Session.Pkt();
                            spkt.Data      = pkt;
                            spkt.RetryTime = DateTime.UtcNow.AddMilliseconds(retry_time);
                            spkt.SendTime  = DateTime.UtcNow;

                            sess.UserDataPendingAck[sess.NextTxSeq] = spkt;
                            sess.BytesTx += pkt.Length;
                            TxStart(pkt, sess.Client);

                            // Increase the retry times if multiple packets are sent so that
                            // we're less likely to send a massive burst of packets to retry.
                            retry_time += 5;

                            sess.NextTxSeq++;

                            first_packet = false;
                            offset      += length;

                            // fixme: it's possible for a multi-dframe user data message to overrun
                            // the valid seq window size. this is bad and the connection will fail.
                        }

                        // If we have sent a user data message that had to be carried in multiple
                        // dframes then stop sending. We can't have more than one of these on the
                        // wire at one time (if I've intepreted the specs correctly).
                        if (sess.MultipleDframePacket)
                        {
                            break;
                        }

                        // If the window is full, don't send any more
                        if (IsAckWindowFull(sess))
                        {
                            break;
                        }
                    }

                    return(true);
                }
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        ///     Send a dummy trans
        /// </summary>
        /// <param name="sess"></param>
        private void SendTUDSessionInfo(Session sess)
        {
            var pkt = new byte[0];

            FLMsgType.AddUInt32(ref pkt, 0xC2);                           // dwPacketType
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwReplyOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwReplySize

            FLMsgType.AddUInt32(ref pkt, 0x50);                           // dwApplicationDescSize
            FLMsgType.AddUInt32(ref pkt, 0x01);                           // dwFlags
            FLMsgType.AddUInt32(ref pkt, max_players + 1);                // dwMaxPlayers
            FLMsgType.AddUInt32(ref pkt, (uint)dplay_sessions.Count + 1); // dwCurrentPlayers
            FLMsgType.AddUInt32(ref pkt, 0x6C + 0x60);                    // dwSessionNameOffset
            FLMsgType.AddUInt32(ref pkt, (uint)server_name.Length * 2);   // dwSessionNameSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwPasswordOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwPasswordSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwReservedDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwReservedDataSize
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwApplicationReservedDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);                              // dwApplicationReservedDataSize
            FLMsgType.AddArray(ref pkt, ApplicationInstanceGUID);
            FLMsgType.AddArray(ref pkt, ApplicationGUID);
            FLMsgType.AddUInt32(ref pkt, sess.DPlayID); // dpnid
            FLMsgType.AddUInt32(ref pkt, sess.DPlayID); // dwVersion
            FLMsgType.AddUInt32(ref pkt, 0);            // dwVersionNotUsed
            FLMsgType.AddUInt32(ref pkt, 2);            // dwEntryCount
            FLMsgType.AddUInt32(ref pkt, 0);            // dwMembershipCount

            // server name table entry
            FLMsgType.AddUInt32(ref pkt, 1);        // dpnid
            FLMsgType.AddUInt32(ref pkt, 0);        // dpnidOwner
            FLMsgType.AddUInt32(ref pkt, 0x000402); // dwFlags
            FLMsgType.AddUInt32(ref pkt, 2);        // dwVersion
            FLMsgType.AddUInt32(ref pkt, 0);        // dwVersionNotUsed
            FLMsgType.AddUInt32(ref pkt, 7);        // dwDNETVersion
            FLMsgType.AddUInt32(ref pkt, 0);        // dwNameOffset
            FLMsgType.AddUInt32(ref pkt, 0);        // dwNameSize
            FLMsgType.AddUInt32(ref pkt, 0);        // dwDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);        // dwDataSize
            FLMsgType.AddUInt32(ref pkt, 0);        // dwURLOffset
            FLMsgType.AddUInt32(ref pkt, 0);        // dwURLSize

            // connecting client name table entry
            FLMsgType.AddUInt32(ref pkt, sess.DPlayID); // dpnid
            FLMsgType.AddUInt32(ref pkt, 0);            // dpnidOwner
            FLMsgType.AddUInt32(ref pkt, 0x020000);     // dwFlags
            FLMsgType.AddUInt32(ref pkt, sess.DPlayID); // dwVersion
            FLMsgType.AddUInt32(ref pkt, 0);            // dwVersionNotUsed
            FLMsgType.AddUInt32(ref pkt, 7);            // dwDNETVersion
            FLMsgType.AddUInt32(ref pkt, 0);            // dwNameOffset
            FLMsgType.AddUInt32(ref pkt, 0);            // dwNameSize
            FLMsgType.AddUInt32(ref pkt, 0);            // dwDataOffset
            FLMsgType.AddUInt32(ref pkt, 0);            // dwDataSize
            FLMsgType.AddUInt32(ref pkt, 0);            // dwURLOffset
            FLMsgType.AddUInt32(ref pkt, 0);            // dwURLSize

            FLMsgType.AddUnicodeStringLen0(ref pkt, server_name);

            sess.UserData.AddLast(pkt);
            SendDFrame(sess);
        }
Пример #4
0
        // FLPACKET_SERVER_CREATESHIP
        public byte[] BuildCreateShip(Ship.Ship ship)
        {
            Log.AddLog(LogType.FL_MSG, "tx FLPACKET_SERVER_CREATESHIP objid={0}", ship.Objid);

            byte[] omsg = { 0x04, 0x02 };
            FLMsgType.AddUInt32(ref omsg, ship.Objid);
            FLMsgType.AddUInt16(ref omsg, ship.Arch.SmallID);
            FLMsgType.AddUInt32(ref omsg, 0);
            FLMsgType.AddUInt32(ref omsg, ship.player != null ? ship.player.FLPlayerID : 0);
            FLMsgType.AddUInt32(ref omsg, ship.com_body);
            FLMsgType.AddUInt32(ref omsg, ship.com_head);

            FLMsgType.AddUInt8(ref omsg, (uint)ship.Accessories.Count);
            foreach (uint accessory in ship.Accessories)
            {
                FLMsgType.AddUInt32(ref omsg, accessory);
            }

            FLMsgType.AddUInt32(ref omsg, ship.voiceid);

            FLMsgType.AddFloat(ref omsg, (float)ship.Position.x);
            FLMsgType.AddFloat(ref omsg, (float)ship.Position.y);
            FLMsgType.AddFloat(ref omsg, (float)ship.Position.z);

            Quaternion q = Quaternion.MatrixToQuaternion(ship.Orientation);

            FLMsgType.AddInt8(ref omsg, (int)(q.I * 127));
            FLMsgType.AddInt8(ref omsg, (int)(q.J * 127));
            FLMsgType.AddInt8(ref omsg, (int)(q.K * 127));
            FLMsgType.AddInt8(ref omsg, (int)(q.W * 127));

            FLMsgType.AddUInt8(ref omsg, (uint)(ship.Health * 255));

            FLMsgType.AddUInt16(ref omsg, (uint)(ship.Items.Count));
            foreach (ShipItem item in ship.Items.Values)
            {
                byte flag = 0;

                if (item.mounted)
                {
                    flag |= 0x01;
                }

                if (item.mission)
                {
                    flag |= 0x02;
                }

                if (item.count == 1)
                {
                    flag |= 0x80;
                }
                else
                {
                    flag |= 0x04;
                }

                if (item.health == 1.0f)
                {
                    flag |= 0x40;
                }

                if (item.hpname.Length > 0)
                {
                    flag |= 0x10;
                }
                else
                {
                    flag |= 0x20;
                }

                FLMsgType.AddUInt8(ref omsg, flag);

                if (item.count != 1)
                {
                    FLMsgType.AddUInt32(ref omsg, item.count);
                }

                if (item.health != 1.0f)
                {
                    FLMsgType.AddUInt8(ref omsg, (uint)(item.health * 255));
                }

                FLMsgType.AddUInt16(ref omsg, item.arch.SmallID);
                FLMsgType.AddUInt8(ref omsg, item.hpid);

                if (item.hpname.Length > 0)
                {
                    FLMsgType.AddAsciiStringLen8(ref omsg, item.hpname + "\0");
                }
            }

            FLMsgType.AddUInt8(ref omsg, (uint)(ship.cols.Count));
            foreach (CollisionGroup col in ship.cols)
            {
                FLMsgType.AddUInt8(ref omsg, col.id);
                FLMsgType.AddUInt8(ref omsg, (uint)(col.health * col.max_hit_pts * 255));
            }

            FLMsgType.AddUInt8(ref omsg, (ship.player != null) ? 4u : 0u); // flag
            FLMsgType.AddFloat(ref omsg, 0);                               // x
            FLMsgType.AddFloat(ref omsg, 0);                               // y
            FLMsgType.AddFloat(ref omsg, 0);                               // z
            FLMsgType.AddInt8(ref omsg, 0);
            FLMsgType.AddUInt16(ref omsg, 0);                              // dunno?
            FLMsgType.AddUInt8(ref omsg, ship.Rank);

            if (ship.player != null)
            {
                FLMsgType.AddUInt8(ref omsg, ship.player.FLPlayerID);
                FLMsgType.AddUInt16(ref omsg, 0);
                FLMsgType.AddUnicodeStringLen8(ref omsg, ship.player.Name);
            }
            else
            {
                var patrol_name = new FLFormatString(0x3f20);
                patrol_name.AddString(0x3016b);
                patrol_name.AddString(0x4074);
                patrol_name.AddString(0x30401);
                patrol_name.AddNumber(0x09);
                FLMsgType.AddArray(ref omsg, patrol_name.GetBytes());

                var ship_name = new FLFormatString(0x3f21);
                ship_name.AddString(0x301a4);
                ship_name.AddString(0x37bac);
                ship_name.AddString(0x37c2b);
                FLMsgType.AddArray(ref omsg, ship_name.GetBytes());
            }

            // The faction associated with the ship. For player ships this can be
            // -1 but for NPCs it needs to be set to a faction ID or the NPC will
            // not have a name shown in space or in the radar/scanner
            FLMsgType.AddUInt32(ref omsg, ship.faction.FactionID);

            // The reputation with reference to the faction..but it doesn't seem to
            // do much
            FLMsgType.AddInt8(ref omsg, -127);
            return(omsg);
        }