From 683b5bd66c195469aaba76a4055855165d1e6c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= Date: Sat, 29 Sep 2007 10:55:14 +0000 Subject: [PATCH] New shiny HTTP header parser. --- protocolhttp.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++--- protocolhttp.h | 5 ++- 2 files changed, 107 insertions(+), 7 deletions(-) diff --git a/protocolhttp.c b/protocolhttp.c index 8b3c314..1a499f0 100644 --- a/protocolhttp.c +++ b/protocolhttp.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolhttp.c,v 1.6 2007/09/28 16:44:59 rahrenbe Exp $ + * $Id: protocolhttp.c,v 1.7 2007/09/29 10:55:14 ajhseppa Exp $ */ #include @@ -188,11 +188,9 @@ bool cIptvProtocolHttp::Connect(void) return false; } - // It would be a good idea to wait here for the reception to begin instead - // of blindly assuming that datastream is really active. - - // Also parsing the reply headers should happen here to see if the - // connection should be re-located etc. + // Now process headers + if (!ProcessHeaders()) + return false; // Update active flag isActive = true; @@ -213,6 +211,105 @@ bool cIptvProtocolHttp::Disconnect(void) return true; } +bool cIptvProtocolHttp::GetHeaderLine(char* dest, unsigned int destLen, + unsigned int &recvLen) +{ + debug("cIptvProtocolHttp::GetHeaderLine()\n"); + + bool linefeed = false; + bool newline = false; + char buf[256]; + //int bufferPosition = 0; + char *bufptr = buf; + memset(buf, '\0', sizeof(buf)); + recvLen = 0; + + while(!newline || !linefeed) { + + socklen_t addrlen = sizeof(sockAddr); + // Set argument point to read buffer + // Wait for data + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 500000; + // Use select + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(socketDesc, &rfds); + int retval = select(socketDesc + 1, &rfds, NULL, NULL, &tv); + // Check if error + if (retval < 0) { + char tmp[64]; + error("ERROR: select(): %s", strerror_r(errno, tmp, sizeof(tmp))); + return false; + } + // Check if data available + else if (retval) { + int retval = recvfrom(socketDesc, bufptr, 1, MSG_DONTWAIT, + (struct sockaddr *)&sockAddr, &addrlen); + + if (retval <= 0) + return false; + + // Parsing end conditions, if line ends with \r\n + if (linefeed && *bufptr == '\n') { + newline = true; + // First occurrence of \r seen + } else if (*bufptr == '\r') + linefeed = true; + // Saw just data or \r without \n + else { + linefeed = false; + ++recvLen; + } + + ++bufptr; + + // Check that buffers won't be exceeded + if (recvLen >= sizeof(buf) || recvLen >= destLen) { + error("Header wouldn't fit into buffer\n"); + return false; + } + + } else { + error("No HTTP response received\n"); + return false; + } + } + + memcpy(dest, buf, recvLen); + return true; + +} + +bool cIptvProtocolHttp::ProcessHeaders(void) +{ + debug("cIptvProtocolHttp::ProcessHeaders()\n"); + unsigned int lineLength = 0; + int response = 0; + bool responseFound = false; + char buf[256]; + + while(!responseFound || lineLength != 0) { + memset(buf, '\0', sizeof(buf)); + + if(!GetHeaderLine(buf, sizeof(buf), lineLength)) + return false; + + if (!responseFound && sscanf(buf, "HTTP/1.%*i %i ",&response) != 1) { + error("Expected HTTP -header not found\n"); + continue; + } else + responseFound = true; + + if (response != 200) { + error("ERROR: %s\n", buf); + return false; + } + } + return true; +} + int cIptvProtocolHttp::Read(unsigned char* *BufferAddr) { //debug("cIptvProtocolHttp::Read()\n"); diff --git a/protocolhttp.h b/protocolhttp.h index 01a42b3..c8ac542 100644 --- a/protocolhttp.h +++ b/protocolhttp.h @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: protocolhttp.h,v 1.5 2007/09/28 16:44:59 rahrenbe Exp $ + * $Id: protocolhttp.h,v 1.6 2007/09/29 10:55:14 ajhseppa Exp $ */ #ifndef __IPTV_PROTOCOLHTTP_H @@ -28,6 +28,9 @@ private: void CloseSocket(void); bool Connect(void); bool Disconnect(void); + bool GetHeaderLine(char* dest, unsigned int destLen, + unsigned int &recvLen); + bool ProcessHeaders(void); public: cIptvProtocolHttp();