Top Mud Sites Forum Return to TopMudSites.com
Go Back   Top Mud Sites Forum > Mud Development and Administration > Advanced MUD Concepts
Click here to Register

Reply
 
Thread Tools
Old 03-15-2009, 06:25 PM   #1
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
MSSP (Mud Server Status Protocol)

A couple of weeks ago I posted a RFC on MudBytes regarding the creation of a protocol for Muds to automatically report their info to mud crawlers. Since then a lot has happened. I set up an official protocol specification and created a snippet that adds basic telnet handling for MCCP, MSSP, NAWS, and TTYPE. I also added MSSP support to TinTin++ so it can be used to debug server side MSSP support. So far four Muds (and one codebase) have implemented the protocol, the MudBytes crawler has added support for it and plans to integrate it into their mud directory, and both TMC and TMS have shown interest in adopting the protocol though they'll probably want to see it kick off first.

For a quick look at what MSSP entails see my mud crawler's output.

Feedback and comments are welcome, keep in mind that the protocol only defines a brief set of official variables, Mud listings can maintain a list of additional variables they support. If you implement MSSP and want to be added to the crawler give me a yell.

Links:

MSSP Protocol defintion

Client for debugging:
TinTin++ (Requires using '#config {debug telnet} on' to display MSSP output from a MUD server.)

Codebases supporing MSSP:
AckFUSS (As of version 4.4.0.)

MUD Crawlers supporing MSSP:
MudByte's MUD crawler
TinTin++ MUD crawler

Discussion forum for MSSP (on MydBytes)
MSSP Discussion Forum

Server supporting MSSP:
azereth.game-host.org:6400
cruentus.genesismuds.com:7070
home.gotr00t.us:3000
slackhalla.org:4321

MSSP Snippets:
MUD Telopt Handler - Handles MCCP, MSSP, NAWS, and TTYPE.
scandum is offline   Reply With Quote
Old 03-15-2009, 08:54 PM   #2
Zhiroc
Member
 
Join Date: Jan 2006
Posts: 92
Zhiroc is on a distinguished road
Re: MSSP (Mud Server Status Protocol)

Quote:
"PLAYERS" : Current number of players online, if multi-playing is allowed report the number of unique IPs instead.
Wouldn't it be better to allow the MUD to define what a player means? Given that multiple people may be playing behind NAT'ed firewalls, IPs may undercount drastically.

Come to think of it, my MUSH has a policy that no one is to know who may be multiplaying, so that may be problematical, as identifying how many players are on may give it away when the population is low.
Zhiroc is offline   Reply With Quote
Old 03-15-2009, 09:21 PM   #3
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

Quote:
Originally Posted by Zhiroc View Post
Wouldn't it be better to allow the MUD to define what a player means? Given that multiple people may be playing behind NAT'ed firewalls, IPs may undercount drastically.
If a MUD has a better way of reporting the actual player count I don't see a problem with that.

Quote:
Originally Posted by Zhiroc View Post
Come to think of it, my MUSH has a policy that no one is to know who may be multiplaying, so that may be problematical, as identifying how many players are on may give it away when the population is low.
As you already said yourself, IPs may undercount drastically regardless of multi-playing, so one would never be sure.

If push comes to shove the mud can only allow MSSP requests from trusted IPs.
scandum is offline   Reply With Quote
Old 03-16-2009, 12:07 AM   #4
mtfox
New Member
 
Join Date: Apr 2008
Posts: 1
mtfox is on a distinguished road
Re: MSSP (Mud Server Status Protocol)

Just a quick correction, azereth.game-host.org:6464 instead of port 6400
mtfox is offline   Reply With Quote
Old 03-16-2009, 11:04 AM   #5
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

I accidentally used the website's port, it's fixed now.

Update: The NakedMud codebase will support MSSP as of version 3.8.
scandum is offline   Reply With Quote
Old 03-18-2009, 12:29 AM   #6
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

Two more muds added MSSP bringing the total to 6:

kingdomsofahln.com:7777
patrickmn.com:5000

Also updated the mssp crawler to make the crawler page look a bit neater.

MSSP Mud Crawler
scandum is offline   Reply With Quote
Old 03-18-2009, 04:20 PM   #7
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

I'd include this functionality in NiMUD, how do you join the network?
locke is offline   Reply With Quote
Old 03-18-2009, 04:35 PM   #8
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

Listings on MudBytes should automatically be crawled, though MudBytes is currently not doing anything with the data, and if someone gives me the host and port of a MSSP supporting Mud I'll manually add it to my crawler.
scandum is offline   Reply With Quote
Old 03-18-2009, 05:35 PM   #9
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Actually, I downloaded the MSSP snippet. I'm attempting to install it, but I wonder how to report to a crawler?

BTW, it complains about signedness several times, though some of these seem intentional. Here are my compilation warnings:


telopt.c: In function 'translate_telopts':
telopt.c:123: warning: pointer targets in assignment differ in signedness
telopt.c:124: warning: pointer targets in assignment differ in signedness
telopt.c:134: warning: pointer targets in assignment differ in signedness
telopt.c: At top level:
telopt.c:447: warning: no previous prototype for 'send_will_mssp'
telopt.c:524: warning: no previous prototype for 'zlib_alloc'
telopt.c:530: warning: no previous prototype for 'zlib_free'
telopt.c: In function 'write_compressed':
telopt.c:618: warning: pointer targets in assignment differ in signedness
telopt.c: In function 'write_to_descriptor':
telopt.c:752: warning: pointer targets in passing argument 2 of 'debug_telopts' differ in signedness
telopt.c:756: warning: pointer targets in passing argument 1 of 'recv_sb_mssp' differ in signedness
gcc -O -g -g3 -ggdb3 -DMALLOC_DEBUG -D_GNU_SOURCE -o nimud alias.o admin.o admin_edit.o admin_info.o bit.o board.o client.o combat.o config.o def.o door.o edit.o events.o load.o functions.o furn.o grammar.o graphics.o handler.o html.o disease.o interpreter.o language.o lists.o magic.o map.o mem.o money.o mount.o nanny.o net.o imc.o info.o move.o props.o parser.o save.o shop.o skills.o social.o string.o tips.o translate.o track.o update.o worldgen.o xrand.o mssp_client.o mssp_tables.o telopt.o -lcrypt -lz


locke is offline   Reply With Quote
Old 03-18-2009, 05:36 PM   #10
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Scandum:

nimud.divineright.org 5333

I have not yet fully implemented it though. Is there a MUD I can meet you on to ask questions?
locke is offline   Reply With Quote
Old 03-18-2009, 07:55 PM   #11
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

I'm not actively hanging out on any mud.

You can use tintin in telnet debugging mode for debugging, and look at the mth snippet as an example of a server side implementation.

I tested your mud but am getting the following response:

Code:
RCVD IAC DO LINEMODE
SENT IAC WONT LINEMODE
RCVD IAC WILL ECHO
SENT IAC DO ECHO
RCVD IAC 0 0
<greeting>
RCVD IAC 34 255
Feel free to PM me with specific questions.
scandum is offline   Reply With Quote
Old 03-18-2009, 08:44 PM   #12
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Quote:
Originally Posted by scandum View Post
I'm not actively hanging out on any mud.

You can use tintin in telnet debugging mode for debugging, and look at the mth snippet as an example of a server side implementation.

I tested your mud but am getting the following response:

Code:
RCVD IAC DO LINEMODE
SENT IAC WONT LINEMODE
RCVD IAC WILL ECHO
SENT IAC DO ECHO
RCVD IAC 0 0
<greeting>
RCVD IAC 34 255
Feel free to PM me with specific questions.
I did use mth. I am using files, renamed:
mud.h -> mssp.h
telnet.h -> telnet.h
telopt.c -> telopt.c
table.c -> mssp_table.c
client.c -> mssp_client.c

I am using your write_to_descriptor only for your code, since I use something called "write_to_connection"

I am using translate_telopts(), zlib, etc.

I added the content, verbatim, to DESCRIPTOR_DATA (called CONNECTION_DATA here):

Code:
/*
 * Connection (channel) structure.
 */
struct    connection_data
{
    CONNECTION_DATA *    next;
    CONNECTION_DATA *    snoop_by;
    PLAYER_DATA *        character;
    PLAYER_DATA *        original;
    char *        host;
    int          lingua;
    int        connection;
    int        connected;
    bool        fcommand;
    bool                client;
    bool                fpromptok;
    int                showing;  // for simulated local echo
    char                inbuf       [4 * MAX_INPUT_LENGTH];
    char                incomm      [MAX_INPUT_LENGTH];
    char                inlast      [MAX_INPUT_LENGTH];
    char                screen[80*50];      /* for graphical windows       */
    int            repeat;
    char *              showstr_head;
    char *              showstr_point;
    char *        outbuf;
    int            outsize;
    int            outtop;
    void *              pEdit;
    char **             pString;

/*
 * Information gathered with MSSP snippet.
 */

        char              * terminal_type;
        char                msoutbuf[MAX_STRING_LENGTH];
        int                 msouttop;
        char                telbuf[MAX_INPUT_LENGTH];
        int                 teltop;
        short               comm_flags;
        short               cols;
        short               rows;
        z_stream          * mccp;
};
msouttop
msoutbuf

these are not used at all actually.

Well, the preface to this is that NiMUD uses character mode, not line mode.

There has been a slight issue during login prior to this where it gets stuck waiting for something, and then a few code characters show up in the buffers from the remote client.

NiMUD simulates local echo by receiving characters from the remote host and then printing the characters that pass through a filter, discarding unwanted characters (sometimes telnet codes). This happens after the call to translate_telopts, however.

It seems what is happening now that I have inserted your translate_telopts() is that during the first few lines it at first is set the same way (or close to properly for character mode) and then after one line of text, something is switching it back into line mode. I'm trying to figure out where you are sending those codes inside the telopt.c client.c etc... but I have not yet found this issue. Ideally, it would properly manage character mode, then switch into line mode only if MSSP needs it, then return the connection to character mode.

The reason NiMUD does this is to interpret ansi keyboard codes like \x1b[C

Any ideas how to stop this from happening? It seems once you've logged out, and you log in the second time, something goes awry with the ability to hit return. Weird.

Code:
/*
 * Read and place in buffer.
 */
bool read_from_connection( CONNECTION_DATA *d )
{
    int iStart;
    char ansiCode=' ';

    /*
     * Abort if pending command already.
     */
    if ( d->incomm[0] != '\0' )
        return TRUE;


    /*
     * Check for overflow.
     */
    d->showing = iStart = strlen(d->inbuf);
    if ( iStart >= sizeof(d->inbuf) - 10 )
    {
        sprintf( log_buf, "%s input overflow!", d->host );
        log_string( log_buf );
        write_to_connection( d->connection,
        "\n\r*** BUFFER OVERFLOW ***\n\r", 0 );
        return FALSE;
    }

    for ( ; ; )
    {

        int nRead;

        nRead = read( d->connection, d->inbuf + iStart,
            sizeof(d->inbuf) - 10 - iStart );
        if ( nRead > 0 )
        {
            d->showing=iStart;
            iStart += translate_telopts(d, d->inbuf + iStart, nRead, d->inbuf+iStart );
         if( d->inbuf[iStart - 1] == '\n' )
            break;
        }
        else if ( nRead == 0 )
        {
         char buf[MAX_STRING_LENGTH];

         if ( d != NULL && d->character != NULL
          && str_cmp( d->character->name, "INFO" ) ) {
         wtf_logf( "%s disconnected.", NAME(d->character) );
         snprintf( buf, MAX_STRING_LENGTH, "Notify> %s has disconnected (EOF).",
                      (d != NULL && d->character != NULL)
                                  ? d->character->name : "Guest" );
         NOTIFY( buf, LEVEL_IMMORTAL, WIZ_NOTIFY_LOGIN );
        }

        return FALSE;
        }
    else if ( errno == EWOULDBLOCK )  break;
        else
        {
        perror( "Read_from_connection" );
            return FALSE;
        }
    }
    d->inbuf[iStart] = '\0';
    return TRUE;
}



void new_connection( int c )
{
    char buf[MAX_STRING_LENGTH];
    CONNECTION_DATA *dnew;
    BAN_DATA *pban;
    struct sockaddr_in sock;
    struct hostent *from;
    int desc;
    unsigned int size;
    extern bool fBootDb;

    size = sizeof(sock);
    getsockname( c, (struct sockaddr *) &sock, &size );
    if ( ( desc = accept( c, (struct sockaddr *) &sock, &size) ) < 0 )
    {
        perror( "New_connection: accept" );
        return;
    }

#if !defined(FNDELAY)
#define FNDELAY O_NDELAY
#endif

    if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
    {
        perror( "New_connection: fcntl: FNDELAY" );
        return;
    }

    /*
     * Cons a new connection.
     */
    dnew = new_connection_data( );
    dnew->connection = desc;

    size = sizeof(sock);
    if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
    {
        perror( "New_connection: getpeername" );
        dnew->host = str_dup( "(unknown)" );
    }
    else
    {
        /*
         * Would be nice to use inet_ntoa here but it takes a struct arg,
         * which ain't very compatible between gcc and system libraries.
         */
        int addr;

        addr = ntohl( sock.sin_addr.s_addr );
        snprintf( buf, MAX_STRING_LENGTH, "%d.%d.%d.%d",
            ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
            ( addr >>  8 ) & 0xFF, ( addr       ) & 0xFF
            );
        sprintf( log_buf, "Sock.sinaddr:  %s", buf );
        log_string( log_buf );
.
.
.
    /*
     * Init connection data.
     */
    dnew->showing=0;
    dnew->next                  = connection_list;
    connection_list             = dnew;

    /*
     * Send the greeting.
     */
    if ( !fBootDb )
    {
        extern char * help_greeting;

// IAC WONT LINEMODE IAC WILL (373) ECHO
    write_to_buffer(dnew, "\377\375\042\377\373\001",6);  // throws telnet into character mode

    write_to_buffer(dnew, VERSION_STR, 0 );
    write_to_buffer(dnew, "\n\r", 0 );

        if ( help_greeting[0] == '.' )
            write_to_buffer( dnew, help_greeting+1, 0 );
        else
            write_to_buffer( dnew, help_greeting  , 0 );
    }
    else write_to_buffer( dnew, "Please wait.\n\r", 0 );

    return;
}


/*
 * Transfer one line from input buffer to input line.
 */
void read_from_buffer( CONNECTION_DATA *d )
{
    int i, j, k;

    /*
     * Hold horses if pending command already.
     */
//    if ( d->incomm[0] != '\0' )
//      return;

    /*
     * Look for at least one new line.
     */
    for ( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
    {
        if ( d->inbuf[i] == '\0' ) {
            d->showing=i;
            return;
        }

        if ( d->character && d->inbuf[i] == '\x1b' ) {
              if ( d->inbuf[i+1] == '[' ) {
                  char acode[5];
                  acode[0] = '[';  acode[1] = d->inbuf[i+2];  acode[2] = d->inbuf[i+3];
                  if ( d->inbuf[i+3] == '~' ) acode[3]='\0';
                  else if ( d->inbuf[i+4] == '~' ) { acode[3]=d->inbuf[i+4]; acode[4]='\0'; }
                  else acode[2] = '\0';
                  ansi_keyboard( d->character, acode );
                  d->inbuf[0]='\0'; d->showing=0; return;
              }
          } else
           if ( i >= d->showing && DC(d) != CON_GET_NEW_PASSWORD
            &&  DC(d) != CON_CONFIRM_NEW_PASSWORD
            &&  DC(d) != CON_GET_OLD_PASSWORD ) {

                if ( d->inbuf[i] == '\b' || d->inbuf[i] == 127 ) { char b[3]; b[0]='\b'; b[1]=' '; b[2]='\b';
                 write_to_connection( d->connection, b, 3 ); d->showing=i;
                } else
                if ( char_isof(d->inbuf[i],
" `1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?" )
 ) { char b[2]; b[0]=d->inbuf[i]; b[1]='\0';
                 write_to_connection( d->connection, b, 1 ); d->showing=i; } //simulated local echo

              }
    } // end for
.
. (Canonical input processing)
.
}

Last edited by locke : 03-18-2009 at 09:15 PM.
locke is offline   Reply With Quote
Old 03-18-2009, 10:55 PM   #13
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

For starters, to push a telnet client into character mode you need to send:

IAC WILL SUPPRESS GA
IAC WILL ECHO

For MSSP you need to send on connect:

IAC WILL MSSP

The write_to_descriptor calls should be replaced with whatever function NiMUD uses, so that should probably be write_to_connection.

You won't need client.c which is just for debugging, and the same goes for mud.c.

The call to translate_telopts looks alright.
scandum is offline   Reply With Quote
Old 03-18-2009, 11:00 PM   #14
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Unfortunately I had to remove that line to translate_telopt() because the number it was returning was messing up my connection. Like I said when I logged back in something was awry the second time and I couldn't hit return. When I removed the translate_telopt line, this problem went way.

I will check into those codes for character mode, but I cannot find where IAC 0 0 is sent or where IAC 34 255 is sent. For now I've removed it until I can spend more time with it. The reason I chose yours is because I didn't know if it was cleaner or something.

When I used the SUPPRESS_GA code, it worked from telnet at a linux prompt but PuTTy still doesn't seem to realize this properly.

The write_* I have is:

Code:
/*
 * Lowest level output function.
 * Write a block of text to the file connection.
 */
bool write_to_connection( int desc, char *txt, int length )
{
    int iStart;
    int nWrite;
    int nBlock;

#if defined(macintosh) || defined(MSDOS)
    if ( desc == 0 )
    desc = 1;
#endif

    if ( length <= 0 )
        length = strlen(txt);

    for ( iStart = 0; iStart < length; iStart += nWrite )
    {
        nBlock = UMIN( length - iStart, 4096 );
        if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 )
        {
            perror( "Write_to_connection" );
            return FALSE;
        }
    }

    return TRUE;
}

Last edited by locke : 03-18-2009 at 11:11 PM.
locke is offline   Reply With Quote
Old 03-18-2009, 11:49 PM   #15
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

Looks like write_to_connection does the same like write_to_descriptor does in merc, so it should be safe to use it.

You really wouldn't want to be using functions from mud.c since those are just dummies.

Not entirely sure what's going wrong and if it's related to mth. Other than a clean compile and adding some log calls to check what's going on I don't have any suggestions.
scandum is offline   Reply With Quote
Old 03-19-2009, 12:03 AM   #16
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Quote:
Originally Posted by scandum View Post
Looks like write_to_connection does the same like write_to_descriptor does in merc, so it should be safe to use it.

You really wouldn't want to be using functions from mud.c since those are just dummies.

Not entirely sure what's going wrong and if it's related to mth. Other than a clean compile and adding some log calls to check what's going on I don't have any suggestions.

I'm not sure either why it would lock up on <enter> What I mean by that is you can type but you can't hit return. My guess is that the number iStart is being set to is the problem. One other inconsistency was that I do not use a static size for the inbuf, which you did.

Also, the signedness issues bring in to question stability. I'd love to use this code and distribute it with my package, but until we can figure this out I haven't got a clue.
locke is offline   Reply With Quote
Old 03-19-2009, 12:20 AM   #17
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

One thing is that mth strips out the \r character, that might be an issue? If your code checks for \r\n that would break it. So either remove the \r stripping, or change your code to only check for a \n. I'd do the latter since that's a lot easier.
scandum is offline   Reply With Quote
Old 03-19-2009, 01:07 AM   #18
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

It checks for either with an || , why would that matter?
locke is offline   Reply With Quote
Old 03-19-2009, 01:17 AM   #19
locke
Banned
 
Join Date: Jan 2009
Home MUD: nimud.divineright.org 5333
Posts: 195
locke is an unknown quantity at this point
Re: MSSP (Mud Server Status Protocol)

Quote:
Originally Posted by scandum View Post
For starters, to push a telnet client into character mode you need to send:

IAC WILL SUPPRESS GA
IAC WILL ECHO
Ok I am now sending these I believe.

Quote:
Originally Posted by scandum View Post
For MSSP you need to send on connect:

IAC WILL MSSP
Does this mean I call announce_support()? This is being done right after the above.

Quote:
Originally Posted by scandum View Post
The write_to_descriptor calls should be replaced with whatever function NiMUD uses, so that should probably be write_to_connection.
Done.

Quote:
Originally Posted by scandum View Post
You won't need client.c which is just for debugging, and the same goes for mud.c.

The call to translate_telopts looks alright.
I cannot call translate_telopt(), and I am not using client.c's stuff either.

When you login to the mud, it writes a Y with two dots at the prompt in PuTTy. This problem existed before, I'm not sure why it was happening, but it apparently is still happening.

I'm using 3 for SUPPRESS_GA.

It seems to only work properly with linux telnet, but the random character appears differently as a ".
locke is offline   Reply With Quote
Old 03-19-2009, 09:52 AM   #20
scandum
Senior Member
 
scandum's Avatar
 
Join Date: Jun 2004
Posts: 308
scandum will become famous soon enough
Re: MSSP (Mud Server Status Protocol)

Seems to be sending out the requests now, but it's not answering.

Other muds haven't had any issues adding mth, so I guess you'll need to do some debugging and figure out what goes wrong.
scandum is offline   Reply With Quote
Reply


Thread Tools


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off

All times are GMT -4. The time now is 10:16 PM.


Powered by vBulletin® Version 3.6.7
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Style based on a design by Essilor
Copyright Top Mud Sites.com 2014