Пример #1
0
void QTcpClient::readMessage()
{
    qDebug()<<"////////////////";
    qint64 numc = 0;
    qint64 numb = tcpsocket->bytesAvailable();
    qDebug()<<numb<<"  numb";
    while(numc < numb)
    {
        int type = 0;
        int length = 0;
        QByteArray databy;
        databy = tcpsocket->read(1);
        numc++;
        type = databy.toInt();
        if(type != m_type)
        {
            databy = tcpsocket->readAll();
            databy.clear();
            continue;
        }
        databy.clear();
        databy = tcpsocket->read(4);
        numc = numc + 4;
        length = Char2Dec(databy.data());
        if(length == 0)
        {
            continue;
        }
        databy.clear();
        databy = tcpsocket->read(length);
        numc = numc +length;
        qDebug()<<m_time.currentDateTime().toString("hh:mm:ss.zzz")<<" Lib";
        (*g_callRead)(databy);
    }
}
Пример #2
0
/*
 * This function parses the address and checks if it conforms to the
 * RFCs 2373, 2460 and 5952.
 * We do not support Microsoft UNC encoding, i.e.
 * hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh.ipv6-literal.net
 * Despite following RFC 5292 we do not signal errors derived from bad
 * zero compression although this might change on time, so please do not
 * trust that we will honor address with wrong zero compression.
 *
 * Returns 0 on success.
 */
static int IPV6_parser(const char *source, struct IPV6Address *address)
{
    /*
     * IPV6 parsing is more complex than IPV4 parsing. There are a few ground rules:
     * - Leading zeros can be omitted.
     * - Fields that are just zeros can be abbreviated to one zero or completely omitted.
     * In the later case the following notation is used: '::'.
     * - Port number is specified in a special way:
     * [hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh]:ppppp
     * Notice that it is possible to have the '[' and ']' without specifying a port.
     *
     * Simplified state machine:
     *
     * _h      _h      _h      _h      _h      _h      _h      _h              _d
     * |/ ':'  |/ ':'  |/ ':'  |/ ':'  |/ ':'  |/ ':'  |/ ':'  |/ ']'    ':'   |/ done
     * 0------>1------>2------>3------>4------>5------>6------>7------>8------>9------>11
     * |\                                                      | done  |
     * -'['                                                    9<------+
     *
     * This is a simplified state machine since I assume that we keep the square brackets inside
     * the same state as hexadecimal digits, which in practice is not true.
     */
    char *p = NULL;
    int sixteen = 0;
    int unsorted_sixteen[6];
    int unsorted_pointer = 0;
    int bracket_expected = 0;
    int port = 0;
    int char_counter = 0;
    bool is_start_bracket = 0;
    bool is_end_bracket = 0;
    bool is_colon = 0;
    bool is_hexdigit = 0;
    bool is_upper_hexdigit = 0;
    bool is_digit = 0;
    int zero_compression = 0;
    int already_compressed = 0;
    int state = 0;
    bool state_change = false;

    /*
     * Initialize our container for unknown numbers.
     */
    for (unsorted_pointer = 0; unsorted_pointer < 6; ++unsorted_pointer)
    {
        unsorted_sixteen[unsorted_pointer] = 0;
    }
    unsorted_pointer = 0;
    /*
     * For simplicity sake we initialize address (if not NULL).
     */
    if (address)
    {
        int i = 0;
        for (i = 0; i < 8; ++i)
        {
            address->sixteen[i] = 0;
        }
        address->port = 0;
    }

    for (p = (char *)source; *p != '\0'; ++p)
    {
        /*
         * Take a closer look at the character
         */
        is_start_bracket = (*p == '[') ? 1 : 0;
        is_end_bracket = (*p == ']') ? 1 : 0;
        is_hexdigit = isxdigit(*p);
        is_digit = isdigit(*p);
        is_colon = (*p == ':') ? 1 : 0;
        if (is_hexdigit)
        {
            if (isalpha(*p))
            {
                is_upper_hexdigit = isupper(*p);
            }
        }

        switch (state)
        {
        case 0:
            /*
             * This case is slightly different because of the possible presence of '['.
             * Notice that '[' is only valid as the first character, anything else is
             * an error!
             */
            if (is_start_bracket)
            {
                if (char_counter == 0)
                {
                    bracket_expected = 1;
                }
                else
                {
                    state = 11;
                    state_change = true;
                }
            }
            else if (is_hexdigit)
            {
                /*
                 * RFC 5952 forbids upper case hex digits
                 */
                if (is_upper_hexdigit)
                {
                    state = 11;
                    state_change = true;
                }
                else
                {
                    sixteen = Char2Hex(sixteen, *p);
                }
            }
            else if (is_colon)
            {
                if (address)
                {
                    address->sixteen[0] = sixteen;
                }
                state = 1;
                state_change = true;
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 1:
            /*
             * This state is special since it cannot have a ']' as in the next
             * states.
             */
            if (is_hexdigit)
            {
                /*
                 * RFC 5952 forbids upper case hex digits
                 */
                if (is_upper_hexdigit)
                {
                    state = 11;
                    state_change = true;
                }
                else
                {
                    sixteen = Char2Hex(sixteen, *p);
                }
            }
            else if (is_colon)
            {
                if (char_counter == 0)
                {
                    /*
                     * This means 'X::Y...' which means zero compression.
                     * Flag it!
                     */
                    zero_compression = 1;
                    already_compressed = 1;
                }
                else
                {
                    if (address)
                    {
                        address->sixteen[state] = sixteen;
                    }
                }
                ++state;
                state_change = true;
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
            if (is_hexdigit)
            {
                /*
                 * RFC 5952 forbids upper case hex digits
                 */
                if (is_upper_hexdigit)
                {
                    state = 11;
                    state_change = true;
                }
                else
                {
                    sixteen = Char2Hex(sixteen, *p);
                }
            }
            else if (is_colon)
            {
                if (char_counter == 0)
                {
                    if (already_compressed)
                    {
                        /*
                         * The '::' symbol can only occur once in a given address.
                         */
                        state = 11;
                        state_change = true;
                    }
                    else
                    {
                        /*
                         * This means '...:X::Y...' which means zero compression.
                         * Flag it!
                         */
                        zero_compression = 1;
                        already_compressed = 1;
                    }
                }
                else
                {
                    if (zero_compression)
                    {
                        /*
                         * If zero compression is enabled, then we cannot trust the position
                         * since we might compressed several fields. We store the value and
                         * look at them afterwards.
                         */
                        unsorted_sixteen[unsorted_pointer] = sixteen;
                        ++unsorted_pointer;
                    }
                    else
                    {
                        /*
                         * No zero compression, just assign the address and keep moving.
                         */
                        if (address)
                        {
                            address->sixteen[state] = sixteen;
                        }
                    }
                    ++state;
                    state_change = true;
                }
            }
            else if (is_end_bracket)
            {
                if (bracket_expected && zero_compression)
                {
                    bracket_expected = 0;
                    /*
                     * RFC 5952 says that we can end an address at any point after
                     * the second position (consequence of the zero compression).
                     * Therefore if we find a ']' we just jump to state 8.
                     */
                    unsorted_sixteen[unsorted_pointer] = sixteen;
                    ++unsorted_pointer;
                    state = 8;
                    state_change = true;
                }
                else
                {
                    /*
                     * Funny stuff, we got a ']' that we were not expecting.
                     * Politely walk back and signal the error.
                     */
                    state = 11;
                    state_change = true;
                }
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 7:
            /*
             * This case is special.
             */
            if (is_hexdigit)
            {
                /*
                 * RFC 5952 forbids uppercase hex digits
                 */
                if (is_upper_hexdigit)
                {
                    state = 11;
                    state_change = true;
                }
                else
                {
                    sixteen = Char2Hex(sixteen, *p);
                }
            }
            else if (is_end_bracket)
            {
                if (bracket_expected)
                {
                    bracket_expected = 0;
                    if (address)
                    {
                        address->sixteen[state] = sixteen;
                    }
                    /*
                     * The last possible position for a sixteen is number 8.
                     */
                    ++state;
                    state_change = true;
                }
                else
                {
                    /*
                     * Funny stuff, we got a ']' that we were not expecting.
                     * Politely walk back and signal the error.
                     */
                    state = 11;
                    state_change = true;
                }
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 8:
            if (is_colon)
            {
                ++state;
                state_change = true;
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 9:
            if (is_digit)
            {
                port = Char2Dec(port, *p);
            }
            else
            {
                state = 11;
                state_change = true;
            }
            break;
        case 10:
            break;
        case 11:
        default:
            return -1;
            break;
        }
        char_counter++;
        if (sixteen > 0xFFFF)
        {
            return -1;
        }
        if (port > 65535)
        {
            return -1;
        }
        if (state_change)
        {
            sixteen = 0;
            port = 0;
            char_counter = 0;
            is_start_bracket = false;
            is_end_bracket = false;
            is_colon = false;
            is_hexdigit = false;
            is_upper_hexdigit = false;
            is_digit = 0;
            state_change = false;
        }
    }
    /*
     * Look at the end state and return accordingly.
     */
    if ((state == 0) || (state == 1))
    {
        /*
         * These states are not final states, so if we exited is because something went wrong.
         */
        return -1;
    }
    /*
     * Thanks to RFC5952 the final states can be intermediate states. This because of zero compression,
     * which means that the following address 1:0:0:0:0:0:0:1 can be written as
     * 1::1. Not to mention more exotic varieties such as 1:0:0:0:0:0:0:0 1:: or
     * 0:0:0:0:0:0:0:0 ::
     * The first intermediate state that can exit is 2, since even the smallest of all address('::')
     * will have at least two ':'.
     * Another exotic case is 'X:0:0:Y:0:0:0:Z' which becomes 'X::Y:0:0:0:Z' or X:0:0:Y::Z because the symbol '::'
     * can appear only once in a given address.
     */
    if ((state == 2) || (state == 3) || (state == 4) || (state == 5) || (state == 6))
    {
        /*
         * We check first for non-closed brackets.
         * Then we check if there is a number that has not been added to our array.
         * Finally we move to zero compression.
         */
        if (bracket_expected)
        {
            return -1;
        }
        unsorted_sixteen[unsorted_pointer] = sixteen;
        ++unsorted_pointer;
        if (zero_compression)
        {
            /*
             * If there is no address, then we can just return :-)
             */
            if (address)
            {
                /*
                 * We need to find the rightful positions for those numbers.
                 * We use a simple trick:
                 * We know how many unsorted addresses we have from unsorted pointer,
                 * and we know that once zero_compression is activated we do not fill
                 * any more numbers to the address structure. Therefore the right way
                 * to do this is to take the array of unsorted_sixteen and start assigning
                 * numbers backwards.
                 */
                int i = 0;
                for (i = 0; i < unsorted_pointer; ++i)
                {
                    address->sixteen[7 - i] = unsorted_sixteen[unsorted_pointer - i - 1];
                }
            }
        }
        else
        {
            /*
             * We cannot end up here without zero compression, or an error.
             */
            return -1;
        }
    }
    if (state == 7)
    {
        /*
         * This state corresponds to the final state of a simple ipv6 address, i.e.
         * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
         * We exited because we ran out of characters. Let's check that we have something
         * before assigning things.
         */
        if (char_counter == 0)
        {
            /*
             * The last field was empty, signal the error.
             */
            return -1;
        }
        if (bracket_expected)
        {
            /*
             * We were expecting a bracket but it never came, so this is an error.
             */
            return -1;
        }
        if (address)
        {
            address->sixteen[7] = sixteen;
        }
    }
    if (state == 8)
    {
        /*
         * This state corresponds to the final state if brackets were present.
         * We still need to check if zero compression was activated and copy
         * the values if so.
         */
        if (zero_compression)
        {
            /*
             * If there is no address, then we can just return :-)
             */
            if (address)
            {
                /*
                 * We need to find the rightful positions for those numbers.
                 * We use a simple trick:
                 * We know how many unsorted addresses we have from unsorted pointer,
                 * and we know that once zero_compression is activated we do not fill
                 * any more numbers to the address structure. Therefore the right way
                 * to do this is to take the array of unsorted_sixteen and start assigning
                 * numbers backwards.
                 */
                int i = 0;
                for (i = 0; i < unsorted_pointer; ++i)
                {
                    address->sixteen[7 - i] = unsorted_sixteen[i];
                }
            }
        }
    }
    if (state == 9)
    {
        /*
         * This state corresponds to the final state if we had brackets around us.
         * This is usually used to append a port number to the address, so we check
         * if we have a port and then assign it.
         */
        if (char_counter == 0)
        {
            /*
             * The last field was empty, signal the error.
             */
            return -1;
        }
        if (address)
        {
            address->port = port;
        }
    }
    if (state == 11)
    {
        /*
         * Error state
         */
        return -1;
    }
    return 0;
}
Пример #3
0
/*
 * This function parses the source pointer and checks if it conforms to the
 * RFC 791.
 *
 * xxx.xxx.xxx.xxx[:ppppp]
 *
 * If address is not NULL and the address is IPV4, then the result is copied there.
 *
 * Returns 0 on success.
 */
static int IPV4_parser(const char *source, struct IPV4Address *address)
{
    char *p = NULL;
    int octet = 0;
    int port = 0;
    int period_counter = 0;
    int port_counter = 0;
    int char_counter = 0;
    bool is_period = false;
    bool is_digit = false;
    bool is_port = false;
    bool has_digit = false;

    /*
     * For simplicity sake we initialize address (if not NULL).
     */
    if (address)
    {
        int i = 0;
        for (i = 0; i < 4; ++i)
        {
            address->octets[i] = 0;
        }
        address->port = 0;
    }

    /*
     * IPV4 parsing has 6 states, of which:
     * 2 are end states
     * 4 are parsing states
     *
     * States 0 to 3 are purely address parsing. State 5
     * might never be reached if there is no port.
     * State 4 is the final state if everything went ok.
     * State 6 is reached in case of error.
     *
     * 0    1    2    3
     * |d   |d   |d   |d
     * | p  | p  | p  | done
     * 0 -> 1 -> 2 -> 3 ->  4
     * |    |    |    |     |
     * 7 <--+----+----+     |
     *     error      | ':' |
     *               _5-----+
     *             d \| done
     */
    int state = 0;
    bool state_change = false;
    for (p = (char *)source; *p != '\0'; ++p)
    {
        /*
         * Do some character recognition
         */
        is_digit = isdigit(*p);
        is_period = (*p == '.') ? 1 : 0;
        is_port = (*p == ':') ? 1 : 0;
        /*
         * Update the corresponding flags.
         */
        if (is_period)
        {
            period_counter++;
        }
        if (is_port)
        {
            port_counter++;
        }
        /*
         * Do the right operation depending on the state
         */
        switch (state)
        {
        case 0:
        case 1:
        case 2:
            /*
             * The three first states are the same.
             * XXX.XXX.XXX.xxx[:nnnnn]
             */
            if (is_digit)
            {
                octet = Char2Dec(octet, *p);
                has_digit = true;
            }
            else if (is_period)
            {
                if (address)
                {
                    address->octets[state] = octet;
                }
                state++;
                state_change = true;
            }
            else
            {
                state = 7;
                state_change = true;
            }
            break;
        case 3:
            /*
             * This case is different from the previous ones. A period here means error.
             * xxx.xxx.xxx.XXX[:nnnnn]
             */
            if (is_digit)
            {
                octet = Char2Dec(octet, *p);
                has_digit = true;
            }
            else if (is_port)
            {
                if (address)
                {
                    address->octets[state] = octet;
                }
                state = 5;
                state_change = true;
            }
            else
            {
                state = 7;
                state_change = true;
            }
            break;
        case 4:
            break;
        case 5:
            if (is_digit)
            {
                port = Char2Dec(port, *p);
            }
            else
            {
                state = 7;
                state_change = true;
            }
            break;
        case 6:
        default:
            return -1;
            break;
        }
        /*
         * It is important to the filtering before counting the characters.
         * Otherwise the counter will need to start from -1.
         */
        char_counter++;
        /*
         * Do some sanity checks, this should hold no matter
         * in which state of the state machine we are.
         */
        if (octet > 255)
        {
            return -1;
        }
        if (port > 65535)
        {
            return -1;
        }
        if (period_counter > 1)
        {
            return -1;
        }
        if (port_counter > 1)
        {
            return -1;
        }
        if (state_change)
        {
            /*
             * Check that we have digits, otherwise the transition is wrong.
             */
            if (!has_digit)
            {
                return -1;
            }
            /*
             * Reset all the variables.
             */
            char_counter = 0;
            octet = 0;
            port = 0;
            period_counter = 0;
            port_counter = 0;
            is_period = false;
            is_digit = false;
            is_port = false;
            has_digit = false;
            state_change = false;
        }
    }
    /*
     * These states are not end state, which mean we exited the loop because of an error
     */
    if ((state == 0) || (state == 1) || (state == 2))
    {
        return -1;
    }
    /*
     * If state is 3 then we exited the loop without copying the last octet.
     * This is because we didn't get to state 4.
     * Notice that we need to check if we had characters, it might be possible that we
     * have the following situation 'xxx.xxx.xxx.' which will fit the state change but not
     * produce a valid IP.
     */
    if (state == 3)
    {
        if (char_counter == 0)
        {
            return -1;
        }
        if (address)
        {
            address->octets[3] = octet;
        }
    }
    /*
     * If state is 5 then we exited the loop without copying the port.
     * This is because we hit a '\0'.
     * Notice that we need to check if we had characters, it might be possible that we
     * have the following situation 'xxx.xxx.xxx.xxx:' which will fit the state change but not
     * produce a valid IP.
     */
    if (state == 5)
    {
        if (char_counter == 0)
        {
            return -1;
        }
        if (address)
        {
            address->port = port;
        }
    }
    /*
     * If state is 6 then there was an error.
     */
    if (state == 6)
    {
        return -1;
    }
    return 0;
}