Example #1
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);
	}
}
Example #2
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;
}
Example #3
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);
		}
	}
}
static FskErr KprWebSocketEndpointUpgradeConnection(KprWebSocketEndpoint self)
{
	FskErr err = kFskErrNone;
	FskHeaders *request;
	char buffer[1024], tmp[1024], portStr[10];
	int len, port;
	
	bailIfError(FskHeaderStructNew(&request));
	
	port = (self->parts->port ? port = self->parts->port : 80);
	
	if (port == 80) {
		FskHeaderAddString("Host", self->parts->host, request);
	} else {
		FskStrCopy(tmp, self->parts->host);
		FskStrCat(tmp, ":");
		FskStrNumToStr(port, portStr, 10);
		FskStrCat(tmp, portStr);
		FskHeaderAddString("Host", tmp, request);
	}
	
	if (self->origin) {
		FskHeaderAddString("Origin", self->origin, request);
	} else {
		FskStrCopy(tmp, "http://");
		FskStrCat(tmp, self->parts->host);
		FskHeaderAddString("Origin", tmp, request);
	}
	
	FskHeaderAddString("Upgrade", "websocket", request);
	FskHeaderAddString("Connection", "Upgrade", request);
	
	KprWebSocketCreateKey(&self->key);
	FskHeaderAddString("Sec-WebSocket-Key", self->key, request);
	FskHeaderAddInteger("Sec-WebSocket-Version", 13, request);
	
	FskStrCopy(buffer, "GET ");
	if (self->parts->path[0] != '/') FskStrCat(buffer, "/");
	FskStrCat(buffer, self->parts->path);
	FskStrCat(buffer, " HTTP/1.1\r\n");
	
	len = FskStrLen(buffer);
	FskHeaderGenerateOutputBlob(&buffer[len], 1024 - len, true, request);
	
	KprSocketWriterSendBytes(self->writer, buffer, FskStrLen(buffer));
	
bail:
	
	return err;
}
Example #5
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;
}
Example #6
0
FskErr KprLibraryServerRequestConditionCallback(FskHTTPServerRequest request, UInt32 condition, void *refCon)
{
    FskErr err = kFskErrNone;
    KprLibraryServer self = request->http->refCon;
    KprLibrarySession session = refCon;

    switch (condition) {
    case kFskHTTPConditionConnectionInitialized:
    case kFskHTTPConditionNoSocket:
    case kFskHTTPConditionRequestReceivedRequestHeaders:
        break;

    case kFskHTTPConditionRequestRequestFinished: {
        FskHeaders *headers;
        UInt32 queryIndex;
        KprLibraryQuery query;

        bailIfError(KprLibrarySessionNew(&session, request));
        FskInstrumentedItemSetOwner(session, self);

        headers = FskHTTPServerRequestGetRequestHeaders(request);
        queryIndex = FskStrToNum(headers->filename);
        FskMutexAcquire(self->queryMutex);
        query = self->queries[queryIndex % kQueryCount];
        if (query && (query->index == queryIndex)) {
            session->info = FskStrDoCopy(query->info);
            session->kind = query->kind;
            session->mime = FskStrDoCopy(query->mime);
            session->url = FskStrDoCopy(query->url);
            if (query->authorization)
                session->authorization = FskStrDoCopy(query->authorization);
        }
        else
            err = kFskErrNotFound;
        FskMutexRelease(self->queryMutex);

        if (kFskErrNone == err) {
            KprURLSplit(session->url, &session->parts);
            if (0 == FskStrCompareWithLength(session->url, "file", 4))
                err = KprFileServerOpen(session);
            else if (0 == FskStrCompareWithLength(session->url, "http", 4)) {
                session->http.location = FskStrDoCopy(session->url);
                err = KprProxyServerOpen(session);
            }
            else
                err = KprDataServerOpen(session);
        }
        if (kFskErrNeedMoreTime == err)
            FskHTTPServerRequestSuspend(request);
        else
            session->error = err;

        err = kFskErrNone;
    }
    break;

    case kFskHTTPConditionRequestGenerateResponseHeaders:
        if (session) {
            FskHeaders *responseHeaders = FskHTTPServerRequestGetResponseHeaders(request);
            if (session->error) {
                if (kFskErrNotFound == session->error)
                    responseHeaders->responseCode = 404;
                else
                    responseHeaders->responseCode = 500;
                FskHeaderAddString(kFskStrContentLength, "0", responseHeaders);
                FskInstrumentedItemPrintfNormal(session, "response headers error %ld", session->error);
            }
            else if (session->file.file)
                KprFileServerGenerateResponseHeaders(session, responseHeaders);
            else if (session->http.client)
                KprProxyServerGenerateResponseHeaders(session, responseHeaders);
            else
                KprDataServerGenerateResponseHeaders(session, responseHeaders);
        }
        break;

    case kFskHTTPConditionConnectionTerminating:
        err = kFskErrUnimplemented;     //@@ or hang on exit... weird.
    case kFskHTTPConditionRequestResponseFinished:
    case kFskHTTPConditionRequestErrorAbort:
        if (session)
            KprLibrarySessionDispose(session);
        break;

    default:
        err = kFskErrUnimplemented;
        break;
    }

bail:
    return err;
}
Example #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;
}