コード例 #1
0
ファイル: webserver.c プロジェクト: philippe44/LMS-to-Cast
/*!
 * \brief Fills in the Offset, read size and contents to send out as an HTTP
 * Range Response.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_OK
 */
static int CreateHTTPRangeResponseHeader(
	/*! String containing the range. */
	char *ByteRangeSpecifier,
	/*! Length of the file. */
	off_t FileLength,
	/*! [out] SendInstruction object where the range operations will be stored. */
	struct SendInstruction *Instr)
{
	off_t FirstByte = 0, LastByte = 0;
	char *RangeInput;
	char *Ptr;
	int rc = 0;
	int RangeRC;

	Instr->IsRangeActive = 1;
	Instr->ReadSendSize = FileLength;
	if (!ByteRangeSpecifier)
		return HTTP_BAD_REQUEST;
	RangeInput = malloc(strlen(ByteRangeSpecifier) + 1);
	if (!RangeInput)
		return HTTP_INTERNAL_SERVER_ERROR;
	memset(RangeInput, 0, strlen(ByteRangeSpecifier) + 1);
	strncpy(RangeInput, ByteRangeSpecifier, strlen(ByteRangeSpecifier));
	/* CONTENT-RANGE: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
	if (StrStr(RangeInput, "bytes") == NULL ||
	    (Ptr = StrStr(RangeInput, "=")) == NULL) {
		free(RangeInput);
		Instr->IsRangeActive = 0;
		return HTTP_BAD_REQUEST;
	}
	/* Jump = */
	Ptr = Ptr + 1;
	RangeRC = GetNextRange(&Ptr, &FirstByte, &LastByte);
	if (FileLength < 0 && LastByte != -1 && LastByte != 1) {
		free(RangeInput);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}
	if (RangeRC != -1) {
		if (FileLength < FirstByte && FileLength > 0) {
			free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
		if (FirstByte >= 0 && LastByte == -1 && FileLength < 0) {
			Instr->RangeOffset = FirstByte;
			/* UPNP_INFINITE responds with a 200, no need of CONTENT-RANGE */
			/* UPNP_UNTIL_CLOSE headers are done in http_SendMessage */
			if (FileLength == UPNP_USING_CHUNKED) {
				rc = snprintf(Instr->RangeHeader,
					sizeof(Instr->RangeHeader),
					"CONTENT-RANGE: bytes %" PRId64
					"-" "*" "\r\n",
					(int64_t)FirstByte);
			}
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else if (FirstByte == 0 && LastByte == 1 && FileLength < 0) {
			/* client tries to guess length by getting 1 byte but file size is
			unknown or using chunked */
			Instr->RangeOffset = 0;
			Instr->ReadSendSize = 1;
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes 0-1/*" "\r\n");
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}

		} else if (FirstByte >= 0 && LastByte >= 0 && LastByte >= FirstByte) {
			if (LastByte >= FileLength)
				LastByte = FileLength - 1;
			Instr->RangeOffset = FirstByte;
			Instr->ReadSendSize = LastByte - FirstByte + 1;
			/* Data between two range. */
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes %" PRId64
				"-%" PRId64 "/%" PRId64 "\r\n",
				(int64_t)FirstByte,
				(int64_t)LastByte,
				(int64_t)FileLength);
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else if (FirstByte >= 0 && LastByte == -1
			   && FirstByte < FileLength) {
			Instr->RangeOffset = FirstByte;
			Instr->ReadSendSize = FileLength - FirstByte;
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes %" PRId64
				"-%" PRId64 "/%" PRId64 "\r\n",
				(int64_t)FirstByte,
				(int64_t)(FileLength - 1),
				(int64_t)FileLength);
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else if (FirstByte == -1 && LastByte > 0) {
			if (LastByte >= FileLength) {
				Instr->RangeOffset = 0;
				Instr->ReadSendSize = FileLength;
				rc = snprintf(Instr->RangeHeader,
					sizeof(Instr->RangeHeader),
					"CONTENT-RANGE: bytes 0-%" PRId64
					"/%" PRId64 "\r\n",
					(int64_t)(FileLength - 1),
					(int64_t)FileLength);
			} else {
				Instr->RangeOffset = FileLength - LastByte;
				Instr->ReadSendSize = LastByte;
				rc = snprintf(Instr->RangeHeader,
					sizeof(Instr->RangeHeader),
					"CONTENT-RANGE: bytes %" PRId64
					"-%" PRId64 "/%" PRId64 "\r\n",
					(int64_t)(FileLength - LastByte),
					(int64_t)FileLength - 1,
					(int64_t)FileLength);
			}
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else {
			free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
	} else {
		free(RangeInput);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}

	free(RangeInput);
	return HTTP_OK;
}
コード例 #2
0
ファイル: webserver.c プロジェクト: MaTriXy/libupnp
/*!
 * \brief Fills in the Offset, read size and contents to send out as an HTTP
 * Range Response.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_OK
 */
static int CreateHTTPRangeResponseHeader(
	/*! String containing the range. */
	char *ByteRangeSpecifier,
	/*! Length of the file. */
	off_t FileLength,
	/*! [out] SendInstruction object where the range operations will be stored. */
	struct SendInstruction *Instr)
{
	off_t FirstByte, LastByte;
	char *RangeInput;
	char *Ptr;
	int rc = 0;

	Instr->IsRangeActive = 1;
	Instr->ReadSendSize = FileLength;
	if (!ByteRangeSpecifier)
		return HTTP_BAD_REQUEST;
	RangeInput = malloc(strlen(ByteRangeSpecifier) + 1);
	if (!RangeInput)
		return HTTP_INTERNAL_SERVER_ERROR;
	memset(RangeInput, 0, strlen(ByteRangeSpecifier) + 1);
	strncpy(RangeInput, ByteRangeSpecifier, strlen(ByteRangeSpecifier));
	/* CONTENT-RANGE: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
	if (StrStr(RangeInput, "bytes") == NULL ||
	    (Ptr = StrStr(RangeInput, "=")) == NULL) {
		free(RangeInput);
		Instr->IsRangeActive = 0;
		return HTTP_BAD_REQUEST;
	}
	/* Jump = */
	Ptr = Ptr + 1;
	if (FileLength < 0) {
		free(RangeInput);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}
	if (GetNextRange(&Ptr, &FirstByte, &LastByte) != -1) {
		if (FileLength < FirstByte) {
			free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
		if (FirstByte >= 0 && LastByte >= 0 && LastByte >= FirstByte) {
			if (LastByte >= FileLength)
				LastByte = FileLength - 1;
			Instr->RangeOffset = FirstByte;
			Instr->ReadSendSize = LastByte - FirstByte + 1;
			/* Data between two range. */
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes %" PRId64
				"-%" PRId64 "/%" PRId64 "\r\n",
				(int64_t)FirstByte,
				(int64_t)LastByte,
				(int64_t)FileLength);
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else if (FirstByte >= 0 && LastByte == -1
			   && FirstByte < FileLength) {
			Instr->RangeOffset = FirstByte;
			Instr->ReadSendSize = FileLength - FirstByte;
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes %" PRId64
				"-%" PRId64 "/%" PRId64 "\r\n",
				(int64_t)FirstByte,
				(int64_t)(FileLength - 1),
				(int64_t)FileLength);
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else if (FirstByte == -1 && LastByte > 0) {
			if (LastByte >= FileLength) {
				Instr->RangeOffset = 0;
				Instr->ReadSendSize = FileLength;
				rc = snprintf(Instr->RangeHeader,
					sizeof(Instr->RangeHeader),
					"CONTENT-RANGE: bytes 0-%" PRId64
					"/%" PRId64 "\r\n",
					(int64_t)(FileLength - 1),
					(int64_t)FileLength);
			} else {
				Instr->RangeOffset = FileLength - LastByte;
				Instr->ReadSendSize = LastByte;
				rc = snprintf(Instr->RangeHeader,
					sizeof(Instr->RangeHeader),
					"CONTENT-RANGE: bytes %" PRId64
					"-%" PRId64 "/%" PRId64 "\r\n",
					(int64_t)(FileLength - LastByte),
					(int64_t)FileLength - 1,
					(int64_t)FileLength);
			}
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else {
			free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
	} else {
		free(RangeInput);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}

	free(RangeInput);
	return HTTP_OK;
}
コード例 #3
0
ファイル: webserver.c プロジェクト: dulton/hello-world
/*!
 * \brief Fills in the Offset, read size and contents to send out as an HTTP
 * Range Response.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_OK
 */
static int CreateHTTPRangeResponseHeader(
	/*! String containing the range. */
	char *ByteRangeSpecifier,
	/*! Length of the file. */
	off_t FileLength,
	/*! [out] SendInstruction object where the range operations will be stored. */
	struct SendInstruction *Instr)
{
	unsigned long FirstByte, LastByte;
	char *RangeInput;
	char *Ptr;
	int rc = 0;

	Instr->IsRangeActive = 1;
	Instr->ReadSendSize = FileLength;
	if (!ByteRangeSpecifier)
		return HTTP_BAD_REQUEST;
	RangeInput = osal_malloc(strlen(ByteRangeSpecifier) + 1);
	if (!RangeInput)
		return HTTP_INTERNAL_SERVER_ERROR;
	strcpy(RangeInput, ByteRangeSpecifier);
	/* CONTENT-RANGE: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
	if (StrStr(RangeInput, "bytes") == NULL ||
	    (Ptr = StrStr(RangeInput, "=")) == NULL) {
		osal_free(RangeInput);
		Instr->IsRangeActive = 0;
		return HTTP_BAD_REQUEST;
	}
	/* Jump = */
	Ptr = Ptr + 1;
	/*
	 * TODO: FileLength is an unsigned long, support ~4G (except -4(UPNP_UNTIL_CLOSE))
	if ((int)FileLength < 0) {
		osal_free(RangeInput);
		printc("BAD REQUEST: %s %d\r\n", __func__, __LINE__);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}
	*/
	if (GetNextRange(&Ptr, (off_t*)&FirstByte, (off_t*)&LastByte) != -1) {
		if (FileLength < FirstByte) {
			osal_free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
		if (LastByte >= FirstByte) {
			if (LastByte >= FileLength)
				LastByte = FileLength - 1;
			Instr->RangeOffset = FirstByte;
			Instr->ReadSendSize = LastByte - FirstByte + 1;
			/* Data between two range. */
			rc = snprintf(Instr->RangeHeader,
				sizeof(Instr->RangeHeader),
				"CONTENT-RANGE: bytes %" PRId64
				"-%" PRId64 "/%" PRId64 "\r\n",
				(int64_t)FirstByte,
				(int64_t)LastByte,
				(int64_t)FileLength);
			if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
				osal_free(RangeInput);
				return HTTP_INTERNAL_SERVER_ERROR;
			}
		} else {
			osal_free(RangeInput);
			return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
		}
	} else {
		osal_free(RangeInput);
		return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
	}

	osal_free(RangeInput);
	return HTTP_OK;
}