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; }
FskErr lpcmPacketParserCanHandle(SDPMediaDescription mediaDescription, const char *encodingName) { if (0 == FskStrCompareCaseInsensitive("L8", encodingName)) return 0; if (0 == FskStrCompareCaseInsensitive("L16", encodingName)) return 0; return kFskErrRTSPPacketParserUnsupportedFormat; }
FskErr h263PacketParserCanHandle(SDPMediaDescription mediaDescription, const char *encodingName) { if (0 == FskStrCompareCaseInsensitive("H263-1998", encodingName) || 0 == FskStrCompareCaseInsensitive("H263-2000", encodingName)) return 0; return kFskErrRTSPPacketParserUnsupportedFormat; }
FskErr KprCoAPClientSendRequest(KprCoAPClient self, KprCoAPMessage message) { FskErr err = kFskErrNone; const char *host = message->host; UInt16 port = message->port; KprCoAPClientResolver dest = self->resolvers; while (dest) { if (port == dest->port && FskStrCompareCaseInsensitive(host, dest->host) == 0) break; dest = dest->next; } if (dest) { if (KprCoAPClientResolverIsResolved(dest)) { err = KprCoAPClientStartRequest(self, dest->ipaddr, port, message); } else { err = KprCoAPClientResolverQueueMessage(dest, message); } } else { bailIfError(KprCoAPClientResolverNew(&dest, self, host, port, message)); FskListAppend(&self->resolvers, dest); } bail: return err; }
// ------------------------------------------------------------------------ void *FskAssociativeArrayElementGet(FskAssociativeArray array, const char *name, void **value, UInt32 *valueSize, SInt32 *valueType) { FskAssociativeArrayNameList list; if (!array || !name) return NULL; // try to find the list of values associated with name list = array->arrayHead; while (list) { if (FskStrCompareCaseInsensitive(name, list->name) == 0) { if (value) *value = list->value; if (valueSize) *valueSize = list->valueSize; if (valueType) *valueType = list->valueType; return list->value; } list = list->next; } if (value) *value = NULL; if (valueSize) *valueSize = 0; if (valueType) *valueType = kFskUnknownType; return NULL; }
Boolean amrReaderCanHandle(const char *mimeType) { if (0 == FskStrCompareCaseInsensitive("audio/AMR", mimeType)) return true; return false; }
FskErr latmPacketParserCanHandle(SDPMediaDescription mediaDescription, const char *encodingName) { Boolean canHandle = false; // We handle MP4A-LATM encoding if (0 != FskStrCompareCaseInsensitive("MP4A-LATM", encodingName)) goto bail; if (NULL != mediaDescription) { SDPAttribute attribute; attribute = SDPFindMediaAttribute(mediaDescription, "fmtp"); if (NULL != attribute) { char *attr; // The config string must be present in the SDP (i.e. out of band) if (NULL != copyAttributeValue(attribute->value, "cpresent", &attr)) { canHandle = (0 == FskStrToNum(attr)); FskMemPtrDispose(attr); } // Validate the configuration if (canHandle) { if (NULL != copyAttributeValue(attribute->value, "config", &attr)) { canHandle = validateConfig(attr, NULL, NULL, NULL, NULL, NULL); FskMemPtrDispose(attr); } else canHandle = false; } } } bail: return canHandle ? 0 : kFskErrRTSPPacketParserUnsupportedFormat; }
static Boolean KprWebSocketEndpointCheckHeaderValue(FskHeaders *response, char *name, char *bingo) { char *value; value = FskHeaderFind(name, response); if (!value) return false; return (FskStrCompareCaseInsensitive(value, bingo) == 0); }
KprDebugMachine KprDebugFindMachine(KprDebug self, char* address) { KprDebugMachine machine = NULL; for (machine = self->machine; machine; machine = machine->next) { if (!FskStrCompareCaseInsensitive(machine->address, address)) return machine; } return NULL; }
FskErr mp3ReaderGetFlags(void *readerState, void *track, UInt32 propertyID, FskMediaPropertyValue property) { mp3Reader state = readerState; FskMediaPropertyValueRecord value; property->type = kFskMediaPropertyTypeInteger; property->value.integer = kFskMediaPlayerFlagHasAudio; if (kFskErrNone == FskMediaMetaDataGet(state->mi.meta, "Genre", 0, &value, NULL)) { if (0 == FskStrCompareCaseInsensitive(value.value.str, "Audiobooks")) property->value.integer |= kFskMediaPlayerFlagHasAudioBook; } if (kFskErrNone == FskMediaMetaDataGet(state->mi.meta, "Album", 0, &value, NULL)) { if (NULL != FskStrStr(value.value.str, "Librivox")) property->value.integer |= kFskMediaPlayerFlagHasAudioBook; } return kFskErrNone; }
// ------------------------------------------------------------------------ void FskAssociativeArrayElementDispose(FskAssociativeArray array, const char *name) { FskAssociativeArrayNameList list, last = NULL; // try to find the list of values associated with name list = array->arrayHead; while (list) { if (FskStrCompareCaseInsensitive(name, list->name) == 0) { // kill existing list if (last) last->next = list->next; else array->arrayHead = list->next; FskMemPtrDispose(list); break; // while(list) } last = list; list = list->next; } }
Boolean FskSSLCheckServerCert(SSL *ssl, char *hostname) { long err; X509 *peer; char peer_CN[256]; err = SSL_get_verify_result(ssl); #if 0 if ((err != X509_V_OK) && (err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) && (err != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) { ERR_print_errors_fp(stderr); fprintf(stderr, "[%s] cert for %s didn't verify %d %s\n", threadTag(FskThreadGetCurrent()), hostname, err, X509_verify_cert_error_string(err)); #else if (err != X509_V_OK) { if ((NULL != FskStrStr(hostname, "google.com")) || (NULL != FskStrStr(hostname, "googleapis.com")) || (NULL != FskStrStr(hostname, "twitter.com")) || (NULL != FskStrStr(hostname, "yammer.com")) || (NULL != FskStrStr(hostname, "facebook.com")) || (NULL != FskStrStr(hostname, "foursquare.com")) || (NULL != FskStrStr(hostname, "akamaihd.net")) || (NULL != FskStrStr(hostname, "fbcdn.net")) || (NULL != FskStrStr(hostname, "radiotime.com")) || (NULL != FskStrStr(hostname, "s3.amazonaws.com")) || (NULL != FskStrStr(hostname, "orb.com"))) { if ((err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) && (err != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) { return false; } myprintf((stderr, "b) cert didn't verify because %d %s\n", err, X509_verify_cert_error_string(err))); myprintf((stderr, " but since it's %s we'll let it through\n", hostname)); } else { #endif return false; } } peer = SSL_get_peer_certificate(ssl); X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, peer_CN, 256); //fprintf(stderr, "comparing peer_CN %s with hostname %s\n", peer_CN, hostname); if (FskStrCompareCaseInsensitive(peer_CN, hostname)) { int pos, L, subL; char *match = peer_CN + 1; subL = FskStrLen(match); L = FskStrLen(hostname); if (peer_CN[0] == '*') { pos = L - subL; if (0 == FskStrCompareCaseInsensitive(match, hostname + pos)) { //fprintf(stderr, "Matched wildcard %s and %s\n", match, hostname + pos); return true; } } if ( (FskStrEndsWith(match, "akamaihd.net") && FskStrEndsWith(hostname, "akamai.net")) || (FskStrEndsWith(match, "akamai.net") && FskStrEndsWith(hostname, "akamaihd.net")) ) { return true; } myprintf((stderr, "cert common name %s and host %s don't match\n", peer_CN, hostname)); return false; } return true; } //SSL_CTX *FskSSLInitialize(char *keyfile, char *password) static SSL_CTX *FskOpenSSLInitialize(const char *calistpath) { SSL_METHOD *method; SSL_CTX *context; if (gSSLContext) { return gSSLContext; } else { SSL_library_init(); SSL_load_error_strings(); // not necessary, but useful } method = SSLv23_method(); context = SSL_CTX_new(method); #if 0 if (FskStrLen(keyfile) > 0) { keyfile = FskEnvironmentDoApply(FskStrDoCopy(keyfile)); if (!SSL_CTX_use_certificate_chain_file(context, keyfile)) doSSLError("Can't read certificate file"); fprintf(stderr, "keyfile is %s\n", keyfile); if (FskStrLen(password) > 0) { gSSLPassword = FskStrDoCopy(password); SSL_CTX_set_default_passwd_cb(context, passwordCallback); if (!SSL_CTX_use_PrivateKey_file(context, keyfile, SSL_FILETYPE_PEM)) doSSLError( "Can't read private keyfile"); } FskMemPtrDispose(keyfile); } #endif #if TARGET_OS_WIN32 { // try to make the path 8.3 safe to avoid nightmares with multibyte character paths, etc. UInt16 *nativePath; if (kFskErrNone == FskFilePathToNative(calistpath, (char **)&nativePath)) { DWORD shortLen; shortLen = GetShortPathNameW(nativePath, NULL, 0); if (0 != shortLen) { UInt16 *eightDotThree; if (kFskErrNone == FskMemPtrNewClear(shortLen * 2, (FskMemPtr *)&eightDotThree)) { if (0 != GetShortPathNameW(nativePath, eightDotThree, shortLen)) { char *utf8; UInt32 utf8Len; if (kFskErrNone == FskTextUnicode16LEToUTF8(eightDotThree, shortLen * 2, &utf8, &utf8Len)) { char *enc; if (kFskErrNone == FskTextToPlatform(utf8, utf8Len, &enc, NULL)) { FskMemPtrDispose(calistpath); calistpath = enc; } FskMemPtrDispose(utf8); } } FskMemPtrDispose(eightDotThree); } } FskMemPtrDispose(nativePath); } } #endif if (!(SSL_CTX_load_verify_locations(context, calistpath, 0))) { doSSLError("Can't read default CA list"); } SSL_CTX_set_verify_depth(context, 0); // SSL_CTX_set_verify(context, SSL_VERIFY_PEER, 0); gSSLContext = context; return context; }
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; }
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; } }