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; }
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; }