memcached.c
static enum try_read_result try_read_network(conn *c) {
    enum try_read_result gotdata = READ_NO_DATA_RECEIVED;
    int res;
    int num_allocs = 0;
    assert(c != NULL);

    if (c->rcurr != c->rbuf) {
        if (c->rbytes != 0) /* otherwise there's nothing to copy */
            memmove(c->rbuf, c->rcurr, c->rbytes);
        c->rcurr = c->rbuf;
    }

    while (1) {
        if (c->rbytes >= c->rsize) {
            if (num_allocs == 4) {
                return gotdata;
            }
            ++num_allocs;
            char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
            if (!new_rbuf) {
                if (settings.verbose > 0)
                    fprintf(stderr, "Couldn't realloc input buffer\n");
                c->rbytes = 0; /* ignore what we read */
                out_string(c, "SERVER_ERROR out of memory reading request");
                c->write_and_go = conn_closing;
                return READ_MEMORY_ERROR;
            }
            c->rcurr = c->rbuf = new_rbuf;
            c->rsize *= 2;
        }

        int avail = c->rsize - c->rbytes;
        res = read(c->sfd, c->rbuf + c->rbytes, avail);
        if (res > 0) {
            pthread_mutex_lock(&c->thread->stats.mutex);
            c->thread->stats.bytes_read += res;
            pthread_mutex_unlock(&c->thread->stats.mutex);
            gotdata = READ_DATA_RECEIVED;
            c->rbytes += res;
            if (res == avail) {
                continue;
            } else {
                break;
            }
        }
        if (res == 0) {
            return READ_ERROR;
        }
        if (res == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            }
            return READ_ERROR;
        }
    }
    return gotdata;
}
/*
 * read from network as much as we can, handle buffer overflow and connection
 * close.
 * before reading, move the remaining incomplete fragment of a command
 * (if any) to the beginning of the buffer.
 *
 * To protect us from someone flooding a connection with bogus data causing
 * the connection to eat up all available memory, break out and start looking
 * at the data I've got after a number of reallocs...
 *
 * @return enum try_read_result
 */
read from network as much as we can, handle buffer overflow and connection
close.
before reading, move the remaining incomplete fragment of a command
(if any) to the beginning of the buffer.

To protect us from someone flooding a connection with bogus data causing
the connection to eat up all available memory, break out and start looking
at the data I've got after a number of reallocs


read from network as much as we can handle buffer overflow and connection close . before reading move the remaining incomplete fragment of a command ( if any ) to the beginning of the buffer . To protect us from someone flooding a connection with bogus data causing the connection to eat up all available memory break out and start looking at the data I ' ve got after a number of reallocs
static enum try_read_result try_read_network(conn *c) {
    enum try_read_result gotdata = READ_NO_DATA_RECEIVED;
    int res;
    int num_allocs = 0;
    assert(c != NULL);
    if (c->rcurr != c->rbuf) {
        if (c->rbytes != 0) 
            memmove(c->rbuf, c->rcurr, c->rbytes);
        c->rcurr = c->rbuf;
    }
    while (1) {
        if (c->rbytes >= c->rsize) {
            if (num_allocs == 4) {
                return gotdata;
            }
            ++num_allocs;
            char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
            if (!new_rbuf) {
                if (settings.verbose > 0)
                    fprintf(stderr, "Couldn't realloc input buffer\n");
                c->rbytes = 0; 
                out_string(c, "SERVER_ERROR out of memory reading request");
                c->write_and_go = conn_closing;
                return READ_MEMORY_ERROR;
            }
            c->rcurr = c->rbuf = new_rbuf;
            c->rsize *= 2;
        }
        int avail = c->rsize - c->rbytes;
        res = read(c->sfd, c->rbuf + c->rbytes, avail);
        if (res > 0) {
            pthread_mutex_lock(&c->thread->stats.mutex);
            c->thread->stats.bytes_read += res;
            pthread_mutex_unlock(&c->thread->stats.mutex);
            gotdata = READ_DATA_RECEIVED;
            c->rbytes += res;
            if (res == avail) {
                continue;
            } else {
                break;
            }
        }
        if (res == 0) {
            return READ_ERROR;
        }
        if (res == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                break;
            }
            return READ_ERROR;
        }
    }
    return gotdata;
}
static enum try_read_result try_read_network ( conn * c ) { enum try_read_result gotdata = READ_NO_DATA_RECEIVED ; int res ; int num_allocs = 0 ; assert ( c != NULL ) ; if ( c -> rcurr != c -> rbuf ) { if ( c -> rbytes != 0 ) memmove ( c -> rbuf , c -> rcurr , c -> rbytes ) ; c -> rcurr = c -> rbuf ; } while ( 1 ) { if ( c -> rbytes >= c -> rsize ) { if ( num_allocs == 4 ) { return gotdata ; } ++ num_allocs ; char * new_rbuf = realloc ( c -> rbuf , c -> rsize * 2 ) ; if ( ! new_rbuf ) { if ( settings . verbose > 0 ) fprintf ( stderr , " \n " ) ; c -> rbytes = 0 ; out_string ( c , " " ) ; c -> write_and_go = conn_closing ; return READ_MEMORY_ERROR ; } c -> rcurr = c -> rbuf = new_rbuf ; c -> rsize *= 2 ; } int avail = c -> rsize - c -> rbytes ; res = read ( c -> sfd , c -> rbuf + c -> rbytes , avail ) ; if ( res > 0 ) { pthread_mutex_lock ( & c -> thread -> stats . mutex ) ; c -> thread -> stats . bytes_read += res ; pthread_mutex_unlock ( & c -> thread -> stats . mutex ) ; gotdata = READ_DATA_RECEIVED ; c -> rbytes += res ; if ( res == avail ) { continue ; } else { break ; } } if ( res == 0 ) { return READ_ERROR ; } if ( res == -1 ) { if ( errno == EAGAIN || errno == EWOULDBLOCK ) { break ; } return READ_ERROR ; } } return gotdata ; }
read from network as much as we can, handle buffer overflow and connection
 close.
read from network as much as we can handle buffer overflow and connection close .
/* otherwise there's nothing to copy */ /* ignore what we read */