+/* essentially memmem */
+void *lookfor(const void *buf, size_t buflen, const void *pattern, size_t len) {
+ const char *bf = buf;
+ const char *pt = pattern;
+ const char *p = bf;
+
+ while (len <= (buflen - (p - bf))) {
+ if ((p = memchr(p, *pt, buflen - (p - bf))) != 0) {
+ if (memcmp(p, pattern, len) == 0) {
+ return (void *)p;
+ } else {
+ p++;
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+/* returns read chunksize, unshifts the line */
+ssize_t read_chunksize(struct io *io) {
+ char *cr;
+ ssize_t cs;
+
+ //fwrite(io->chunkbuf.buffer, io->chunkbuf.len, 1, stderr);
+
+ /* there could be up to two leading bytes */
+ if (io->chunkbuf.len >= 2 && io->chunkbuf.buffer[0] == '\r' && io->chunkbuf.buffer[1] == '\n') {
+ tls_buffer_shift(&io->chunkbuf, 2);
+ }
+
+ cr = lookfor(io->chunkbuf.buffer, io->chunkbuf.len, "\r\n", 2);
+
+ if (cr == 0) {
+ return -1;
+ }
+
+ cs = strtol(io->chunkbuf.buffer, 0, 16);
+ tls_buffer_shift(&io->chunkbuf, cr - io->chunkbuf.buffer + 2);
+
+ return cs;
+}
+
+/* unchunk's job is to move bytes from the chunk buf to the response buf */
+/* return bytes from chunk, 0 if unable. once last chunk, changed chunked
+ * to 0?
+ */
+ssize_t unchunk(struct io *io) {
+ ssize_t bytes_to_move = 0;
+ ssize_t chunksize;
+
+ if (!io || !io->chunked) {
+ return 0;
+ }
+
+ if (io->chunkleft == 0) {
+ chunksize = read_chunksize(io);
+ if (chunksize == -1) {
+ return 0;
+ }
+ io->chunksize = chunksize;
+ if (io->chunksize == 0) {
+ /* end of chunked data */
+ io->chunked = 0;
+ return 0;
+ }
+ io->chunknum++;
+ io->chunkleft = io->chunksize;
+ io->chunktotal += io->chunksize;
+ }
+
+ if (io->chunkbuf.len == 0) {
+ /* need more bytes */
+ return 0;
+ }
+
+ bytes_to_move = io->chunkbuf.len < io->chunkleft ? io->chunkbuf.len : io->chunkleft;
+
+ tls_buffer_append(&io->response, io->chunkbuf.buffer, bytes_to_move);
+ io->chunkleft -= bytes_to_move;
+ io->chunkbytesread += bytes_to_move;
+
+ /* chunk is terminated with a crlf */
+ //tls_buffer_shift(&io->chunkbuf, bytes_to_move + io->chunkleft ? 0 : 2);
+ tls_buffer_shift(&io->chunkbuf, bytes_to_move);
+
+ return bytes_to_move;
+}
+