Exemple #1
0
/*
 * Consume bytes until the whole header is got (up to a "\r\n\r\n" sequence)
 * (Also unfold multi-line fields and strip '\r' chars from header)
 */
static int Cache_get_header(CacheEntry_t *entry,
                            const char *buf, size_t buf_size)
{
   size_t N, i;
   Dstr *hdr = entry->Header;

   /* Header finishes when N = 2 */
   N = (hdr->len && hdr->str[hdr->len - 1] == '\n');
   for (i = 0; i < buf_size && N < 2; ++i) {
      if (buf[i] == '\r' || !buf[i])
         continue;
      if (N == 1 && (buf[i] == ' ' || buf[i] == '\t')) {
         /* unfold multiple-line header */
         _MSG("Multiple-line header!\n");
         dStr_erase(hdr, hdr->len - 1, 1);
      }
      N = (buf[i] == '\n') ? N + 1 : 0;
      dStr_append_c(hdr, buf[i]);
   }

   if (N == 2) {
      /* Got whole header */
      _MSG("Header [buf_size=%d]\n%s", i, hdr->str);
      entry->Flags |= CA_GotHeader;
      dStr_fit(hdr);
      /* Return number of header bytes in 'buf' [1 based] */
      return i;
   }
   return 0;
}
Exemple #2
0
/*
 * Decode chunked data
 */
static Dstr *Decode_chunked(Decode *dc, const char *instr, int inlen)
{
   char *inputPtr, *eol;
   int inputRemaining;
   int chunkRemaining = *((int *)dc->state);
   Dstr *output = dStr_sized_new(inlen);

   dStr_append_l(dc->leftover, instr, inlen);
   inputPtr = dc->leftover->str;
   inputRemaining = dc->leftover->len;

   while (inputRemaining > 0) {
      if (chunkRemaining > 2) {
         /* chunk body to copy */
         int copylen = MIN(chunkRemaining - 2, inputRemaining);
         dStr_append_l(output, inputPtr, copylen);
         chunkRemaining -= copylen;
         inputRemaining -= copylen;
         inputPtr += copylen;
      }

      if ((chunkRemaining == 2) && (inputRemaining > 0)) {
         /* CR to discard */
         chunkRemaining--;
         inputRemaining--;
         inputPtr++;
      }
      if ((chunkRemaining == 1) && (inputRemaining > 0)) {
         /* LF to discard */
         chunkRemaining--;
         inputRemaining--;
         inputPtr++;
      }

      /*
       * A chunk has a one-line header that begins with the chunk length
       * in hexadecimal.
       */
      if (!(eol = (char *)memchr(inputPtr, '\n', inputRemaining))) {
         break;   /* We don't have the whole line yet. */
      }

      if (!(chunkRemaining = strtol(inputPtr, NULL, 0x10))) {
         break;   /* A chunk length of 0 means we're done! */
      }
      inputRemaining -= (eol - inputPtr) + 1;
      inputPtr = eol + 1;
      chunkRemaining += 2; /* CRLF at the end of every chunk */
   }

   /* If we have a partial chunk header, save it for next time. */
   dStr_erase(dc->leftover, 0, inputPtr - dc->leftover->str);

   *(int *)dc->state = chunkRemaining;
   return output;
}
Exemple #3
0
/*
 * Return a newlly allocated string with the next dpip token in the socket.
 * Return value: token string and length on success, NULL otherwise.
 * (useful for handling null characters in the data stream)
 */
char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize)
{
   char *p, *ret = NULL;
   *DataSize = 0;

   /* Read all available data without blocking */
   Dpip_dsh_read(dsh, 0);

   /* switch mode upon request */
   if (dsh->mode & DPIP_LAST_TAG)
      dsh->mode = DPIP_RAW;

   if (blocking) {
      if (dsh->mode & DPIP_TAG) {
         /* Only wait for data when the tag is incomplete */
         if (!strstr(dsh->rdbuf->str, DPIP_TAG_END)) {
             do {
                Dpip_dsh_read(dsh, 1);
                p = strstr(dsh->rdbuf->str, DPIP_TAG_END);
             } while (!p && dsh->status == EAGAIN);
         }

      } else if (dsh->mode & DPIP_RAW) {
         /* Wait for data when the buffer is empty and there's no ERR/EOF */
         while (dsh->rdbuf->len == 0 &&
                dsh->status != DPIP_ERROR && dsh->status != DPIP_EOF)
            Dpip_dsh_read(dsh, 1);
      }
   }

   if (dsh->mode & DPIP_TAG) {
      /* return a full tag */
      if ((p = strstr(dsh->rdbuf->str, DPIP_TAG_END))) {
         ret = dStrndup(dsh->rdbuf->str, p - dsh->rdbuf->str + 3);
         *DataSize = p - dsh->rdbuf->str + 3;
         dStr_erase(dsh->rdbuf, 0, p - dsh->rdbuf->str + 3);
         if (strstr(ret, DPIP_MODE_SWITCH_TAG))
            dsh->mode |= DPIP_LAST_TAG;
      }
   } else {
      /* raw mode, return what we have "as is" */
      if (dsh->rdbuf->len > 0) {
         ret = dStrndup(dsh->rdbuf->str, dsh->rdbuf->len);
         *DataSize = dsh->rdbuf->len;
         dStr_truncate(dsh->rdbuf, 0);
      }
   }

   return ret;
}
Exemple #4
0
/*
 * Return value: 0 on success or empty buffer,
 *               1..DataSize sent, -1 eagain, or -3 on big Error
 */
int a_Dpip_dsh_tryflush(Dsh *dsh)
{
   int st;

   if (dsh->wrbuf->len == 0) {
      st = 0;
   } else {
      st = Dpip_dsh_write(dsh, 1, dsh->wrbuf->str, dsh->wrbuf->len);
      if (st > 0) {
         /* update internal buffer */
         dStr_erase(dsh->wrbuf, 0, st);
      }
   }
   return (dsh->wrbuf->len == 0) ? 0 : st;
}
Exemple #5
0
/*
 * Translate to desired character set (UTF-8)
 */
static Dstr *Decode_charset(Decode *dc, const char *instr, int inlen)
{
   inbuf_t *inPtr;
   char *outPtr;
   size_t inLeft, outRoom;

   Dstr *output = dStr_new("");
   int rc = 0;

   dStr_append_l(dc->leftover, instr, inlen);
   inPtr = dc->leftover->str;
   inLeft = dc->leftover->len;

   while ((rc != EINVAL) && (inLeft > 0)) {

      outPtr = dc->buffer;
      outRoom = bufsize;

      rc = iconv((iconv_t)dc->state, &inPtr, &inLeft, &outPtr, &outRoom);

      // iconv() on success, number of bytes converted
      //         -1, errno == EILSEQ illegal byte sequence found
      //                      EINVAL partial character ends source buffer
      //                      E2BIG  destination buffer is full

      dStr_append_l(output, dc->buffer, bufsize - outRoom);

      if (rc == -1)
         rc = errno;
      if (rc == EILSEQ){
         inPtr++;
         inLeft--;
         dStr_append_l(output, utf8_replacement_char,
                       sizeof(utf8_replacement_char) - 1);
      }
   }
   dStr_erase(dc->leftover, 0, dc->leftover->len - inLeft);

   return output;
}