/*

Peerchat IP encoding/decoding algorithm 0.1
by Luigi Auriemma
e-mail: aluigi@autistici.org
web:    aluigi.org


INTRODUCTION
============
Peerchat is the name of the encrypted IRC server of Gamespy
peerchat.gamespy.com:6667.
The game clients that use this server (like Race Driver, Haegemonia,
Ground Control II, Gamespy Arcade and many others) send their IP
(returned by the same Peerchat server after the command USRIP) in the
command USER so when someone does a /whois on an user he gets some
informations similar to the following:

   X19s4Fp1DX|123456

The text string before the '|' is just the IP address of the client and
is encoded using the simple algorithm available in this file.
FYI the number after the '|' is the unique profile ID used by Gamespy
Arcade and identify your registered account on Gamespy.
The games that don't need it set this number to 0.


HOW TO USE
==========
peerchat_ip_encoder: give the real IP address (unsigned int) to it and
                     it returns a text string that contains the encoded
                     IP
peerchat_ip_decoder: give the text string containing the Peerchat
                     encoded IP and it returns the real IP address
                     (unsigned int)


LICENSE
=======
    Copyright 2004,2005,2006 Luigi Auriemma

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

    http://www.gnu.org/licenses/gpl.txt
*/


    /* the other choice was strchr(encdata, *data++) - encdata */
    /* but I think the following solution is a bit faster */
unsigned char peerchat_ip_decoder_switch(unsigned char num) {
    switch(num) {
        case 'a': return(0);
        case 'F': return(1);
        case 'l': return(2);
        case '4': return(3);
        case 'u': return(4);
        case 'O': return(5);
        case 'D': return(6);
        case '9': return(7);
        case 's': return(8);
        case 'f': return(9);
        case 'W': return(10);
        case 'q': return(11);
        case '1': return(12);
        case 'v': return(13);
        case 'G': return(14);
        case 'p':
        default: return(15);
    }
}



unsigned char *peerchat_ip_encoder(unsigned int ip) {
    const static unsigned char  encdata[] = "aFl4uOD9sfWq1vGp";
    static unsigned char        ret[11];

    ip ^= 0xc3801dc7;
    ret[0] = 'X';
    ret[1] = encdata[ip >> 28];
    ret[2] = encdata[(ip >> 24) & 0xf];
    ret[3] = encdata[(ip >> 20) & 0xf];
    ret[4] = encdata[(ip >> 16) & 0xf];
    ret[5] = encdata[(ip >> 12) & 0xf];
    ret[6] = encdata[(ip >> 8) & 0xf];
    ret[7] = encdata[(ip >> 4) & 0xf];
    ret[8] = encdata[ip & 0xf];
    ret[9] = 'X';
    ret[10] = 0;

    return(ret);
}



unsigned int peerchat_ip_decoder(unsigned char *data) {
    unsigned int   ip = 0;

    data++; // skip X
    ip |= peerchat_ip_decoder_switch(*data++) << 28;
    ip |= peerchat_ip_decoder_switch(*data++) << 24;
    ip |= peerchat_ip_decoder_switch(*data++) << 20;
    ip |= peerchat_ip_decoder_switch(*data++) << 16;
    ip |= peerchat_ip_decoder_switch(*data++) << 12;
    ip |= peerchat_ip_decoder_switch(*data++) << 8;
    ip |= peerchat_ip_decoder_switch(*data++) << 4;
    ip |= peerchat_ip_decoder_switch(*data);
    ip ^= 0xc3801dc7;

    return(ip);
}



