Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
tintin++ ogg sound player script for linux
Author: Robert Smith
Submitted by: Vladaar
6Dragons ogg Soundpack
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.4
Author: Vladaar
Submitted by: Vladaar
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
Users Online
CommonCrawl, Yandex, DotBot

Members: 0
Guests: 6
Stats
Files
Topics
Posts
Members
Newest Member
481
3,734
19,366
618
Micheal64X
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » General » Coding » IPC Shared memory
Forum Rules | Mark all | Recent Posts

IPC Shared memory
< Newer Topic :: Older Topic > Semaphole what?

Pages:<< prev 1 next >>
Post is unread #1 Mar 3, 2008, 10:48 am
Go to the top of the page
Go to the bottom of the page

Exodus
Fledgling
GroupMembers
Posts12
JoinedOct 9, 2006

As some of you may recall, I was brainstorming on IMC yesterday about being able to transfer a descriptor from one MUD to another.
The basic premise of this is to be able to connect to a MUD, and be able to move that connection to another mud on the same machine without booting the character. (Think about making an exit in a room to another plane of existence, going through that exit and arriving in an entirely new world, eg. another MUD)

For some background information, the codebases would be generally the same, perhaps scaled down a bit for the lesser one, with different areas and possibly different classes/skill sets.

Also of note, a character can be logged in to only one MUD or the other, never both on the same character. Assume both MUDs use the same pfile to read/write to.

My idea is to use IPC shared memory space to do this, but I have some problems getting the actual code worked out because my knowledge of IPC is limited and there is not a great deal of applicable help out there.

The basic design is this:
Character connects and logs into MUD A as normal.
Character does something to trigger the transfer to MUD B (Doesn't really matter what the trigger is, that's simple)
MUD A copies the character's descriptor data to a shared memory space using IPC
MUD A notifies MUD B that there is a transfer to be made via IPC messaging queues and tells it the shared memory key.
MUD B responds that it received the message and accesses the shared memory space using the given key and creates a descriptor with the accessed information.
MUD B places a pointer to the new descriptor it made in shared memory with a different key and notifies MUD A with the new key.
MUD A accesses the shared memory with the new key and moves the character's descriptor pointer to the new one in shared memory, I'm assuming this will effectively move the character to the new section of memory in MUD B.


Does anyone see any issues with this? Here is an example I was testing last night to store data in shared memory using IPC:


CMDF do_socktest( CHAR_DATA *ch, char *argument )
{
  int key;
  int shmid;
  char *data;
  static short SHM_SIZE = 1024;

  key = 666;
  /* connect to (and possibly create) the segment: */
  if( (shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1 )
  {
    bug("shmget";);
    return;
  }

  /* attach to the segment to get a pointer to it: */
  data = (char *) shmat(shmid, (void *)0, 0);
  if( data == (char *)(-1) )
  {
    bug("shmat";);
    return;
  }

  /* read or modify the segment, based on the command line: */
  if( !NULLSTR(argument) )
  {
    ch_printf(ch, "writing to segment: \"%s\"\n", argument );
    strncpy(data, argument, SHM_SIZE);
  }
  else
    ch_printf(ch, "segment contains: \"%s\"\n", data);

  /* detach from the segment: */
  if (shmdt(data) == -1)
  {
    bug("shmdt";);
    return;
  }
  return;
}


My problem is I don't quite understand how to store a whole data structure in this space just yet. I also am not certain that by storing the descriptor data from MUD A in shared memory, accessing it with MUD B and recreating the data there and replacing the data in shared memory with a pointer to the data on MUD B will allow me to reassign the descriptor to this new address and effectively move the character in memory to a different MUD.

Perhaps something like this to store it:
struct descriptor_data *d;

d = ch->desc;
shmget(key, sizeof(d), 0644 | IPC_CREAT)


And some function to copy it on the other mud, followed by the above a second time to store the pointer to it, followed by something like this to move the pointer:
struct descriptor_data *data;

data = shmat(shmid, (void *)0, 0);
ch->desc = data;


Any insight you guys can give me this would be very helpful.

Exo
       
Post is unread #2 Mar 3, 2008, 12:25 pm
Go to the top of the page
Go to the bottom of the page

Quixadhal
Conjurer
GroupMembers
Posts398
JoinedMar 8, 2005

'ware! There be dragonnes here!

I'm not sure shared memory is going to get you where you want to go. AFAIK, descriptors can only be shared if they're in the same process group (IE: you did a fork or an exec), and while you could wrap up the structure data and toss it into shared memory (I'd use shm_open() myself), the pointers won't be valid on the other side because the things they point TO aren't in shared memory -- and the MMU maintains seperate virtual memory addressing for each process.

However, to pass a player from one to the other is easy enough. Just open a new socket to the destination mud and use dup2 on the descriptors, then close your socket. (AberMUD used to do this). You might do some handshaking and whenever someone logs into either mud, ask the other one if they're logged in before allowing it.
       
Post is unread #3 Mar 3, 2008, 2:22 pm
Go to the top of the page
Go to the bottom of the page

Exodus
Fledgling
GroupMembers
Posts12
JoinedOct 9, 2006

I see what you're getting at here. This is what I have so far, it doesn't work. I think I'm going in the right direction though.
CMDF do_socktest( CHAR_DATA *ch, char *argument )
{
  int sockfd;
  struct hostent *he;
  struct sockaddr_in their_addr; // connector's address information
  static short prt = 6010;

  if( NULLSTR(argument) )
  {
    bug("usage: client hostname\n";);
    return;
  }

  if( (he=gethostbyname(argument)) == NULL )   // get the host info
  {
    bug("gethostbyname";);
    return;
  }

  if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
  {
    bug("socket";);
    return;
  }

  their_addr.sin_family = AF_INET;    // host byte order
  their_addr.sin_port = htons(prt);  // short, network byte order
  their_addr.sin_addr = *((struct in_addr *)he->h_addr);
  memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
  if( connect(sockfd, (struct sockaddr *)&their_addr, sizeof their_addr) == -1 )
  {
    bug("connect";);
    return;
  }

  dup2(sockfd, ch->desc->descriptor);
  return;
}
       
Post is unread #4 Mar 3, 2008, 11:16 pm
Go to the top of the page
Go to the bottom of the page

Exodus
Fledgling
GroupMembers
Posts12
JoinedOct 9, 2006

What the above code does is open a connection from one mud to another and attempt to transfer the descriptor to the latter.

I'm having difficulty figuring out just exactly how to use dup2 in this context. Do I need to copy the character's descriptor to the new socket's descriptor? Vice versa? Maybe it has something to do with the actual connect call, copying the char's descriptor to make the connection with via connect().

Any ideas? I looked through the Aber codebase. I couldn't find any real examples of doing this. Very little useful information on the net regarding it as well. Lots regarding doing stuff that I might do in the future however, but this is a fairly important feature I'd like to get implemented.

Thanks for any help on this!

Exo
       
Pages:<< prev 1 next >>