Esempio n. 1
0
static int KprWebSocketServerValidateRequest(FskHeaders *requestHeaders, FskHeaders *responseHeaders)
{
	FskErr err;
	char *value;
	char *decoded = NULL;
	UInt32 len;
	int statusCode = 400;

	value = FskHeaderFind("Upgrade", requestHeaders);
	if (!value || FskStrCompareCaseInsensitive(value, "websocket") != 0) goto bail;

	value = FskHeaderFind("Connection", requestHeaders);
	if (!value || FskStrCompareCaseInsensitive(value, "Upgrade") != 0) goto bail;

	value = FskHeaderFind("Sec-WebSocket-Version", requestHeaders);
	if (!value || FskStrCompare(value, "13") != 0) {
		statusCode = 426;
		FskHeaderAddString("Sec-WebSocket-Version", "13", responseHeaders);
		goto bail;
	}

	value = FskHeaderFind("Sec-WebSocket-Key", requestHeaders);
	if (!value) goto bail;

	bailIfError(FskStrB64Decode(value, FskStrLen(value), &decoded, &len));
	if (len != 16) goto bail;

	statusCode = 101;

bail:
	FskMemPtrDispose(decoded);

	return statusCode;
}
Esempio n. 2
0
static void KprWebSocketServerPrepareResponseHeaders(KprWebSocketServerRequest request) {
	if (NULL == FskHeaderFind(kFskStrServer, request->responseHeaders))
		FskHeaderAddString(kFskStrServer, kWebSocketServerIdentifier, request->responseHeaders);

	if (NULL == FskHeaderFind(kFskStrContentLength, request->responseHeaders))
		FskHeaderAddString(kFskStrContentLength, "0", request->responseHeaders);

	if (NULL == FskHeaderFind(kFskStrDate, request->responseHeaders)) {
		char dateString[32];
		FskTimeMakeDate(dateString, 31);
		FskHeaderAddString(kFskStrDate, dateString, request->responseHeaders);
	}
}
Esempio n. 3
0
static Boolean KprWebSocketEndpointValidateResponse(KprWebSocketEndpoint self, FskHeaders *response)
{
	FskErr err;
	char *value;
	char *encoded = NULL;
	Boolean result = false;

	{
		FskHeaderIterator iter = FskHeaderIteratorNew(response);
		FskDebugStr("HANDSHAKE: response headers\n");
		while (iter) {
			FskDebugStr(">  %s: %s\n", iter->name, iter->value);
			iter = FskHeaderIteratorNext(iter);
		}
		FskHeaderIteratorDispose(iter);
	}
	
	if (response->responseCode != 101) return false;
	if (!KprWebSocketEndpointCheckHeaderValue(response, "Upgrade", "websocket")) return false;
	if (!KprWebSocketEndpointCheckHeaderValue(response, "Connection", "Upgrade")) return false;
	
	value = FskHeaderFind("Sec-WebSocket-Accept", response);
	if (!value) return false;

	bailIfError(KprWebSocketCalculateHash(self->key, &encoded));

	result = (FskStrCompare(value, encoded) == 0);
bail:
	if (encoded) FskMemPtrDispose(encoded);
	return result;
}
Esempio n. 4
0
static Boolean KprWebSocketEndpointCheckHeaderValue(FskHeaders *response, char *name, char *bingo)
{
	char *value;
	
	value = FskHeaderFind(name, response);
	if (!value) return false;
	
	return (FskStrCompareCaseInsensitive(value, bingo) == 0);
}
Esempio n. 5
0
static void KprWebSocketServerGenerateUpgradeResponse(KprWebSocketServerRequest request)
{
	FskHeaders *responseHeaders = request->responseHeaders;
	char *encoded = NULL;
	char *value;

	responseHeaders->responseCode = 101;

	FskHeaderAddString("Upgrade", "websocket", responseHeaders);
	FskHeaderAddString("Connection", "Upgrade", responseHeaders);

	value = FskHeaderFind("Sec-WebSocket-Key", request->requestHeaders);
	if (value) {
		KprWebSocketCalculateHash(value, &encoded);
		if (encoded) {
			FskHeaderAddString("Sec-WebSocket-Accept", encoded, responseHeaders);
			FskMemPtrDispose(encoded);
		}
	}
}
Esempio n. 6
0
FskErr mp3SpoolerCallback(void *clientRefCon, UInt32 operation, void *param)
{
	mp3Reader state = clientRefCon;
	FskErr err = kFskErrNone;

	switch (operation) {
		case kFskMediaSpoolerOperationDataReady:
			state->spoolerPosition += (UInt32)param;
			if (state->reader->mediaState < kFskMediaPlayerStateStopped) {
				if (state->id3.data) {
					UInt32 percent, bytesRead;
					void *buffer;

					if (state->id3.size != state->id3.offset) {
						err = FskMediaSpoolerRead(state->spooler, state->id3.offset, (UInt32)(state->id3.size - state->id3.offset), &buffer, &bytesRead);
						if (kFskErrNone == err) {
							FskMemMove((char *)state->id3.data + state->id3.offset, buffer, bytesRead);
							state->id3.offset += bytesRead;
						}
					}

					percent = (UInt32)((((float)state->id3.offset) / ((float)state->id3.size)) * 100.0);
					if (percent < 100)
						(state->reader->doSetState)(state->reader, kFskMediaPlayerStateInstantiatingProgress + percent);
					else
						err = mp3Instantiate(state);
				}
				else
					err = mp3Instantiate(state);
			}
			break;

		case kFskMediaSpoolerOperationSetHeaders: {
			FskHeaders *headers = param;
			FskHeaderAddString("icy-metadata", "1", headers);

			}
			break;

		case kFskMediaSpoolerOperationGetHeaders: {
			FskHeaders *headers = param;
			char *value = FskHeaderFind("icy-metaint", headers);
			state->icy.metaInt = (NULL != value) ? FskStrToNum(value) : 0;
			state->icy.nextMetaPosition = state->icy.metaInt;

			if ((NULL == state->mi.meta) || (kFskErrNone != FskMediaMetaDataGet(state->mi.meta, "FullName", 0, NULL, NULL))) {
				value = FskHeaderFind("icy-name", headers);
				if (NULL == value)
					value = FskHeaderFind("x-audiocast-name", headers);
				state->icy.title = FskStrDoCopy(value);
			}

			state->icy.isProtocol = 0 == FskStrCompare(headers->protocol, "ICY");

			value = FskHeaderFind("Server", headers);
			if (NULL != value) {
				if (0 == FskStrCompareWithLength("Orbiter", value, 7)) {
					if (!state->isOrbiter) {
						state->isOrbiter = true;
						state->reader->needsIdle = true;
						FskTimeGetNow(&state->orbStart);
					}
				}
			}

			if (state->icy.isNanocaster) {
				value = FskHeaderFind("icy-genre", headers);
				if ((NULL != value) && (0 == FskStrCompareCaseInsensitive(value, "error")))
					(state->reader->doSetState)(state->reader, kFskMediaPlayerStateFailed);
			}

            value = FskHeaderFind("availableSeekRange.dlna.org", headers);
            if (value && (0 == FskStrCompareWithLength("1 npt=", value, 6))) {
                char *dash = FskStrChr(value + 6, '-');
                double duration;
                if (dash && (kFskErrNone == FskMediaParseNPT(dash + 1, &duration)))
                    state->dlnaDuration = duration;
            }
			}
			break;

		case kFskMediaSpoolerOperationGetURI:
			state->spoolerPosition = ((FskMediaSpoolerGetURI)param)->position;
			break;
	}

	return err;
}
Esempio n. 7
0
static void httpPrepareResponseHeaders(FskHTTPServerRequest request) {
	char	*str;
	int		requestProtocolVersion;

	requestProtocolVersion = FskHeaderHTTPVersion(request->requestHeaders);

	if (NULL == FskHeaderFind(kFskStrServer, request->responseHeaders))
		FskHeaderAddString(kFskStrServer, kHTTPServerIdentifier, request->responseHeaders);

	str = FskHeaderFind(kFskStrConnection, request->responseHeaders);
	if (str && FskStrCompareCaseInsensitiveWithLength(str, kFskStrClose, 5) == 0)
		request->keepAlive = false;

	str = FskHeaderFind(kFskStrTransferEncoding, request->responseHeaders);
	if (str && (FskStrCompareCaseInsensitiveWithLength(str, kFskStrChunked, FskStrLen(kFskStrChunked)) == 0)) {
		request->transferEncoding = kFskTransferEncodingChunked;
	}
	else {
		request->transferEncoding = kFskTransferEncodingNone;
		str = FskHeaderFind(kFskStrContentLength, request->responseHeaders);
		if (str) {
			request->stats.expectedBodyToSend = FskStrToNum(str);
		}
		else if (requestProtocolVersion >= kFskHTTPVersion1dot1) {
			// DHWG 7.8.1 - if http server is responding to 1.1 requests,
			// it must use connection:close if there's no content length
			// or chunked encoding
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		}
	}
	
	if (requestProtocolVersion <= kFskHTTPVersion1dot0) {
		request->keepAlive = false;		// DHWG 7.8.21 (must ignore keepalive)
		FskHeaderRemove(kFskStrConnection, request->responseHeaders);
		FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		FskMemPtrDispose(request->requestHeaders->protocol);

		request->requestHeaders->protocol = FskStrDoCopy("HTTP/1.0");

		if (0 == FskStrCompareCaseInsensitiveWithLength(FskHeaderFind(kFskStrTransferEncoding, request->responseHeaders), kFskStrChunked, FskStrLen(kFskStrChunked))) {
			FskHeaderRemove(kFskStrTransferEncoding, request->responseHeaders);
			request->transferEncoding = kFskTransferEncodingNone;
		}
		if (request->stats.expectedBodyToSend == 0) {
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		}
	}

	if (request->requestHeaders->responseCode >= 400) {
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n", httpProtocolVersionString(request), request->requestHeaders->responseCode, FskFindResponse(request->requestHeaders->responseCode));
	}
	else if (request->responseHeaders->responseCode > 0) {
		str = FskFindResponse(request->responseHeaders->responseCode);
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n", httpProtocolVersionString(request), request->responseHeaders->responseCode, str ? str : "");
		if (request->keepAlive) {
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrKeepAlive, request->responseHeaders);
		}
	}
	else {
		request->responseHeaders->responseCode = 500;
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s 500 Internal Sever Error\r\n", httpProtocolVersionString(request));
	}

	if (NULL == FskHeaderFind(kFskStrDate, request->responseHeaders)) {
		char dateString[32];
		FskTimeMakeDate(dateString, 31);
		FskHeaderAddString(kFskStrDate, dateString, request->responseHeaders);
	}

	// *** generate the response
	request->out.max += FskHeaderGenerateOutputBlob(&request->out.buf[request->out.max], request->out.bufferSize - request->out.max, true, request->responseHeaders);

	if ((!request->keepAlive) || (request->responseHeaders->responseCode >= 400))
		request->nextState = kHTTPDone;
}
Esempio n. 8
0
static void httpProcessRequestHeaders(FskHTTPServerRequest request) {
	char 		*str;
	FskHeaders* headers = request->requestHeaders;
	UInt32 version = FskHeaderHTTPVersion(headers);
	char* host = FskHeaderFind(kFskStrHost, headers);
	char* uri = FskHeaderURI(headers);
	char* filename = FskHeaderFilename(headers);
	
	request->state = kHTTPReadRequestBody;

	if (FskStrCompareWithLength(uri, "http://", 7) == 0) {
		// remove host from filename
		char* p = FskStrStr(filename, "://") + 3;
		p = FskStrChr(p, '/') + 1;
		FskMemMove(filename, p, FskStrLen(p) + 1);
	}
	else {
		if (host) {
			if (FskMemPtrNewClear(FskStrLen(host) + FskStrLen(uri) + 9, &str) != kFskErrNone)
				headers->responseCode = 500;
			else {
				FskStrCat(str, "http://");
				FskStrCat(str, host);
				FskStrCat(str, "/");
				FskStrCat(str, headers->URI);
				FskMemPtrDispose(headers->URI);
				headers->URI = str;
			}
		}
		else if (version >= kFskHTTPVersion1dot1)
			headers->responseCode = 400;
		else if (version == kFskHTTPVersion1dot0) {
			if (FskMemPtrNewClear(FskStrLen(uri) + 9, &str) != kFskErrNone)
				headers->responseCode = 500;
			else {
				FskStrCat(str, "http:///");
				FskStrCat(str, headers->URI);
				FskMemPtrDispose(headers->URI);
				headers->URI = str;
			}
		}
	}
	
	str = FskHeaderFind(kFskStrConnection, request->requestHeaders);
	if (str && FskStrCompareCaseInsensitiveWithLength(str, kFskStrClose, 5) == 0) 
		request->keepAlive = false;
	else
		request->keepAlive = true;

	str = FskHeaderFind(kFskStrContentLength, request->requestHeaders);
	if (str) {
		request->requestBodyContentLength = FskStrToNum(str);
		request->stats.expectedBytesToReceive = FskStrToNum(str);
	}
	else
		request->stats.expectedBytesToReceive = 0;

	str = FskHeaderFind(kFskStrTransferEncoding, request->requestHeaders);
	if (str && (FskStrCompareCaseInsensitiveWithLength(str, kFskStrChunked, FskStrLen(kFskStrChunked)) == 0))
		request->requestBodyChunked = true;
	else
		request->requestBodyChunked = false;
	
	doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestReceivedRequestHeaders, request->refCon);

	if (NULL != (str = FskHeaderFind(kFskStrExpect, request->requestHeaders))) {
		if (0 == FskStrCompareCaseInsensitive(kFskStr100Continue, str))
			request->state = kHTTPFulfillExpectation;
		else
			request->state = kHTTPDenyExpectation;
	}
}