• Advertisement
Sign in to follow this  

I would like to use a smartpointer's address as a ID value

This topic is 1061 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all.

 

Not sure if this is a good idea but I would like to try it out.

What I have is a smartpointer returned from a connection class and I want to send it as the players ID, it will need to work for 32 and 64 bit systems

Would it be safe to use a unsigned 64 bit int, will it cover the range, the google protocol buffer has a fixed64 bit value can I use that.

 

 

I went ahead and set up a test it does work but how valid is it to do something like this

.

class t
{
public:

	t(){}
	~t(){}

	void Print()
	{
		std::cout << std::endl << "Printed Using the copyed address" << std::endl;
	}

};


int main(void)
 {


t *newt = new t();

t *temp = NULL;

Tespointer ptrs;//sfixed64 google protocol

//hold the pointer in the 64bit value
ptrs.set_address((::google::protobuf::int64)newt);

std::string serialized;
ptrs.SerializeToString(&serialized);

ptrs.ParseFromString(serialized);

temp = (t*)ptrs.address();

temp->Print();


   _getch();
   return 0;
 }
Edited by ankhd

Share this post


Link to post
Share on other sites
Advertisement

Hi.

What about just each run of the program, the ID would be ok, as long as I don't delete the pointer during the app current run.

 

Was reading this, but ??? I don't want to convert it to a different type just something to hold the value so it will be the same on a 32bit and a 64 bit

 

If I keep it a int64_t on a 32 bit system and a 64 bit system sends its ID will the 32 bit system display all its values.

Share this post


Link to post
Share on other sites

no. I was thinking about using it to link a remote object to its host object.

 

The host creates a object then tells all remote computers to also create a object then the remote object hold this value for sends back to the host object.  to link remote object to host object. Crazy maybe.blink.png

Share this post


Link to post
Share on other sites
What tonemgub said. This is a bad, bad idea.

A perfectly acceptable alternative is to just shove the pointer into an array. The player ID is the index into this array. If players can join mid-progress with the game, use a free-list of some sort to recycle player IDs when someone quits the game.

Note also that you don't want the player to ever tell the server who he is. You might tell a player that his ID is 2 and then he might send a command SelfDestruct(player=4) and bam, he just killed another player.

Each connection should have an implicit player ID on the server side. When input is received from a connection then the ID that is associated with it is automatically associated with the input. The player ID should only be used by players to identify other players when _requesting_ things over the network from the absolutely-authoritative server. Requests that affect a player himself should rely on that implicit player ID on the server, not sending the ID to the server as part of the request.

Share this post


Link to post
Share on other sites

My 2 cents: this "pointer-ID" could be used for arbitrary code execution over the network, as long as someone knows the memory layout of your object - which isn't hard, considering all C+ objects and most other types of objects keep a pointer to the virtual methods table right at the start of the object. All they would have to do is send you another "pointer-ID" which points to valid memory that has the same layout. At the least they could start sending random IDs and manage to crash your server with an access violation.

 

 

Oh the nasty barstards(kill the hackers). Man that sux, That 2 cent just busted the piggy bank. mmmm New plan..

Share this post


Link to post
Share on other sites
Coordinated unique IDs work well. Start with a block and have the machine maintain a set of numbers.

If you need different machines to generate their own then as part as client negotiation include banks of numbers. Perhaps a block of a million for local objects that never get shared (0-999,999,999) then another bank for shared objects from client 0, (from 1,000,000 to 1,999,999), a bank of a million for client 1 (from 2,000,000 to 2,999,999), and so on.

And that's it. Each client in the mesh (up to about four thousand of them) can generate whatever they want, whenever they want, and share with the mesh. Everybody can generate more shared unique IDs than you need for networked game objects.

That's overkill really, since if your networked simulation is trying to communicate more than a few hundred shared items at once you are likely outside the scope of a realtime game and more in the scope of some type of scientific processing like weather simulation.

Share this post


Link to post
Share on other sites

Why do you think you need a 64-bit id? Are you planning to have more than 4,294,967,296 players connected at once? (hint: that's well over half the world's population)


That is the range of 32-bit.
I think you meant 2^64 = 1,844674407371e+19 or the galaxy's stars several times over tongue.png Edited by swiftcoder

Share this post


Link to post
Share on other sites

That is the range of 32-bit.
I think you meant 2^64 = 1,844674407371e+19 or the galaxy's stars several times over tongue.png


Well, you only need 64 bit IDs if you have more than 4294967296 players. If you have less than that you can stick with 32 bit IDs.

Share this post


Link to post
Share on other sites

The 64 bit was to hold the address of a 64 bit pointer 32 bit's can't hold all the bits of a 64 bit pointer.

 

Yeah the 64 bit id is over kill, i'll be lucky to have 8 - 16 players per game. Like everyone has stated I can now generate the ID per Game that gets joined the host or the server could allocate the ID to new Players when they join the game lobby. I was trying to give ID as each player logged on to the server, But that ID would be a user account type ID not needed for game play.

 

I think I found a way to link the remote objects. Each computer that joins a game has a list of current players that contain that players remote objects in a map based on the objects ID, this way its a look up based on the players ID and the Objects ID.

 

If the server says Player 1 died it would send out a message killplayer that contains PlayerID(int), ObjectID, MessageType, and on remote Pc the message comes in and it first finds the players remotes, then finds the object in the map and that object can be killed and removed.

 

I'll give this a try to day.

Share this post


Link to post
Share on other sites

hi again.

 

Is there a elegant solution to some thing like this. I need to map the ID to the Connection and visa versa

.

//holds all clients of this lobby
std::set<cConnection_ptr> Clients;
	
//map the connection pointer to the id
boost::unordered_map<cConnection_ptr, int32_t> ClientID;

//map the ID to connection
boost::unordered_map<int32_t, cConnection_ptr> IDToConnection;

//client data is set when a client sends its accountinfo
boost::unordered_map<int32_t, cClientData> ClientData;

int32_t LobbyID;//each client gets a id

.

It gets really ugly when a client disconnects

.

void leave(cConnection_ptr client)
{
     std::set<cConnection_ptr>::iterator it = Clients.find(client);

     if(it != Clients.end())
     {
	boost::unordered_map<cConnection_ptr, int32_t>::const_iterator  itid = ClientID.find((*it));

       if(itid != ClientID.end())
       {	
	  boost::unordered_map<int32_t, cConnection_ptr>::const_iterator  itidtocon = IDToConnection.find(itid->second);
	 
	  boost::unordered_map<int32_t, cClientData>::const_iterator  itcdata = ClientData.find(itid->second);
//
	  if(itidtocon != IDToConnection.end())
		IDToConnection.erase(itidtocon);

	  if(itcdata != ClientData.end())
		ClientData.erase(itcdata);
						
       }//end itid
	 
       Clients.erase(it);
    }//end it
	  
	 
    Clients.rerase(client);
  }

Share this post


Link to post
Share on other sites

Wow.

 

 

If you don't mind taking a dependency on Boost, then Boost.Bimap is your friend for two-way mappings.

what a beast that all is.

I think this example is what I may need to follow.

.

typedef bimap<

    multiset_of< std::string >, // author
         set_of< std::string >, // title

      with_info< std::string >  // abstract THIS COULD BE THE ACCOUNT INFO

> bm_type;
typedef bm_type::value_type book;

bm_type bm;

bm.insert(

    book( "Bjarne Stroustrup"   , "The C++ Programming Language",

          "For C++ old-timers, the first edition of this book is"
          "the one that started it all—the font of our knowledge." )
);


// Print the author of the bible
std::cout << bm.right.at("The C++ Programming Language");

// Print the abstract of this book
bm_type::left_iterator i = bm.left.find("Bjarne Stroustrup");
std::cout << i->info;


.

Looking into it. thanks for the link, I tried a search on containers with 2 key values and a data element but came up short.(thats Gold).

Share this post


Link to post
Share on other sites

What tonemgub said. This is a bad, bad idea.

A perfectly acceptable alternative is to just shove the pointer into an array. The player ID is the index into this array. If players can join mid-progress with the game, use a free-list of some sort to recycle player IDs when someone quits the game.

Note also that you don't want the player to ever tell the server who he is. You might tell a player that his ID is 2 and then he might send a command SelfDestruct(player=4) and bam, he just killed another player.

Each connection should have an implicit player ID on the server side. When input is received from a connection then the ID that is associated with it is automatically associated with the input. The player ID should only be used by players to identify other players when _requesting_ things over the network from the absolutely-authoritative server. Requests that affect a player himself should rely on that implicit player ID on the server, not sending the ID to the server as part of the request.

 

This is a good idea, but still if you do this remember to always range check your array index server side (common sense really).

 

Otherwise the first person to request that their character attack player id -54124 or such will bring you a whole new definition to the meaning of frustration.

Share this post


Link to post
Share on other sites

Thanks everyone.

 

Here is a example of the bimap(I chuckle when I write that).

.

#include <boost/shared_ptr.hpp>
#include <boost/bimap.hpp>


class cClientData
{
public:
	cClientData(){}
	~cClientData(){}

	std::string Name;
};

typedef boost::shared_ptr<cClientData> cConnection_ptr;

typedef boost::bimap<

		cConnection_ptr , // connection
        int32_t ,  // ID
		boost::bimaps::with_info<cClientData>  // abstract

>bm_type;
typedef bm_type::value_type client_bm_type;







int main()
{
  

        //it will be a connection class in the real app
        //just testing smart pointer
        cConnection_ptr PTR =  boost::shared_ptr<cClientData>(new cClientData());

        cConnection_ptr PTR2 =  boost::shared_ptr<cClientData>(new cClientData());

	cConnection_ptr PTR3 =  boost::shared_ptr<cClientData>(new cClientData());

	cConnection_ptr PTR4 =  boost::shared_ptr<cClientData>(new cClientData());

	cClientData cd;
	

	bm_type bm;
	int32_t id = 10;
	int32_t id2 = 13;
	int32_t id3 = 16;
	int32_t id4 = 11;

	cd.Name = "Sam1";
	bm.insert(client_bm_type(PTR, id, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam2 Long ffffffffffffffffffffffffffffffffffffff";
	bm.insert(client_bm_type(PTR2, id2, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam3";
	bm.insert(client_bm_type(PTR3, id3, cd));//this is typedef bm_type::value_type client;

	cd.Name = "Sam4";
	bm.insert(client_bm_type(PTR4, id4, cd));//this is typedef bm_type::value_type client;

	

	

	// Print the new abstract by using connection pointer
std::cout << "abstract Data using Pointer Key = " << bm.left.info_at(PTR).Name << std::endl;

std::cout << "abstract Data using int32_t Key = " << bm.right.info_at(id).Name << std::endl;


// Print the client data by left side 
bm_type::left_iterator i = bm.left.find(PTR);
if(i != bm.left.end())
	std::cout << "Finding by Pointer1 = " << i->info.Name << std::endl;


i = bm.left.find(PTR2);
if(i != bm.left.end())
	std::cout << "Finding by Pointer2 = " << i->info.Name << std::endl;

i = bm.left.find(PTR3);
if(i != bm.left.end())
	std::cout << "Finding by Pointer3 = " << i->info.Name << std::endl;

i = bm.left.find(PTR4);
if(i != bm.left.end())
	std::cout << "Finding by Pointer4 = " << i->info.Name << std::endl;




// Print the client data by right side 
bm_type::right_iterator ir = bm.right.find(20);//not a entry
if(ir != bm.right.end())
	std::cout << "Finding by ID = " << i->info.Name << std::endl;
else
	std::cout << "Finding Failed No ID";


	return 0;
}

.

And if your searching the web with boost::bimap watch out stay with boost pages , here or stackoverflow.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement