static FskErr KprWebSocketServerSendResponseHeader(KprWebSocketServerRequest request) {
	FskErr err = kFskErrNone;
	int sent;

	KprWebSocketServerPrepareResponseHeaders(request);

	request->out.length = snprintf((char *) request->out.buffer, request->out.size, "%s %d %s\r\n", "HTTP/1.1", request->responseHeaders->responseCode, FskFindResponse(request->responseHeaders->responseCode));
	request->out.length += FskHeaderGenerateOutputBlob((char *) &request->out.buffer[request->out.length], request->out.size - request->out.length, true, request->responseHeaders);

	err = FskNetSocketSendTCP(request->skt, request->out.buffer, request->out.length, &sent);

	return err;
}
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;
}
Beispiel #3
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;
}