chttpchunked-encodingtransfer-encodinghttp-chunked

C parsing HTTP Chunked transfer encoding response


I am developing a client that needs to parse Chunked-type HTTP transfers. I've beat my head against the wall trying to figure out the error with the following, and would appreciate it if someone might be able to catch my error a bit quicker. To sum up the issue: it seems as though, the client does not receive ALL of the chunk, thereby screwing up the rest of the process. Thanks in advance!

 while(cflag){
    pfile_chunk = malloc(CHUNK_SIZE+1);
    memset(pfile_chunk, 0, CHUNK_SIZE);
    cPtr = pfile_chunk;
    cPtr2 = NULL;
    k=0;
    while(*(cPtr-1) != '\n'){
        k++;
        recv(sock, cPtr, 1, 0);
        cPtr = pfile_chunk+k;
    }
    cPtr2 = strchr(pfile_chunk, '\r');
    *cPtr2 = '\0';
    sscanf(pfile_chunk, "%x", &l);
    if(l == 0)
        break;
    printf("\nServer wants to deliver %ld bytes.\n", l);
    pfile_chunk = realloc(pfile_chunk, l+1);
    memset(pfile_chunk, 0, l);
    recv(sock, pfile_chunk, l, 0);
    fputs(pfile_chunk, f);
    printf("GOT THIS, SIZE %ld:\n%s\n", strlen(pfile_chunk), pfile_chunk);
    //get next \r\n bytes.
    recv(sock, NULL, 2, 0);
}

Solution

  • At the very least, you should check the return value of recv to see if you are getting the number of bytes you are expecting to get.

    A short read is definitely possible on the network, since the system call will return whatever is available in the socket receive buffer at the time you make the call.

    Implement a loop until you have read in your entire chunk, or pass the MSG_WAITALL flag to recv in the last parameter. However, you still need to check for an error from recv.

    ssize_t r = recv(sock, pfile_chunk, l, MSG_WAITALL);
    if (r < l) {
        /* check for errors ... */
    } else {
        /* got the data */
    }