 // -----------------------
 
 
+// get a character
+//
+// Get a character from the client, with timeout and disconnect checks.
+// Returns the character, or -1 if unsuccessful.
+//
+// To protect against clients that connect and send nothing this bails
+// out after "too long". No "real" browser ever causes this but you can
+// test it by telnetting to port 80, entering at least one character and
+// then just waiting.
+//
+
+#define HTTPPARSE_TIMEOUT_SECONDS    20L
+#define HTTPPARSE_TIMEOUT            (HTTPPARSE_TIMEOUT_SECONDS * 1000L)
+
+int
+clientgetc(EthernetClient &ec, unsigned long t0)
+{
+    // NOTE that this is in fact a busy loop, but in practice there should
+    //      already be data when we are here. In any case it's not like we
+    //      have anything else to do and the TIMEOUT eventually applies.
+
+    while ((elapsed_time(t0) <= HTTPPARSE_TIMEOUT) && ec.connected()) {
+        if (ec.available())
+            return ec.read();
+    }
+    return -1;
+}
+
+// get n characters from the client
+// buf must be n+1 long (NUL added, which may or may not make sense but
+// it is always added at the end nevertheless)
+int
+clientgetn(EthernetClient &ec, char *buf, int n, unsigned long t0)
+{
+    for ( ; n > 0 ; --n) {
+        int i = clientgetc(ec, t0);
+
+        if (i == -1)
+            return -1;
+
+        *buf++ = (char)i;
+    }
+    *buf = '\0';
+    return 0;
+}
+
+
 // eatline - consume characters until LF
 //
 // Strictly speaking we should be looking for CRLF but

    }
}

// ---------------
//  JSMN helpers
// ---------------

    c = (char)i;
    if (c == 'G') {
        rp->operation = HTTPPARSE_GET;
        qq = "ET";
    } else if (c == 'P') {
        // if PUT becomes an option, add more logic here; for now...
        rp->operation = HTTPPARSE_POST;
        qq = "OST";
    } else
        return -1;

    // at this point we are looking for the rest of GET/POST (or disconnected)
    while (*qq != '\0') {
        if ((i = clientgetc(rp->client, rp->t0)) == -1)
            return -1;
        c = (char)i;
        if (c != *qq++)        // i.e., not matching expected GET or POST
            return -1;
    }

