FskErr KprQuerySerialize(FskAssociativeArray array, char** it) { FskErr err = kFskErrNone; FskAssociativeArrayIterator iterate = FskAssociativeArrayIteratorNew(array); SInt32 length = 0; char* p; while (iterate) { if (length) length++; length += FskStrLen(iterate->name); length++; length += FskStrLen(iterate->value); } length++; FskAssociativeArrayIteratorDispose(iterate); iterate = NULL; bailIfError(FskMemPtrNew(length, it)); iterate = FskAssociativeArrayIteratorNew(array); p = *it; *p = 0; while (iterate) { if (*p) *p++ = '&'; FskStrCopy(p, iterate->name); p += FskStrLen(iterate->name); *p++ = '='; FskStrCopy(p, iterate->value); p += FskStrLen(iterate->value); } *p = 0; FskAssociativeArrayIteratorDispose(iterate); bail: return err; }
FskErr KprZeroconfPlatformAdvertisementStart(KprZeroconfAdvertisement self) { FskErr err = kFskErrNone; char* txt = NULL; UInt32 size = 0, offset = 0, length; KprZeroconfPlatformAdvertisement advertisement = self->platform; if (!advertisement->service) { DNSServiceErrorType error; DNSServiceRef serviceRef; FskAssociativeArrayIterator iterator = FskAssociativeArrayIteratorNew(self->txt); FskInstrumentedItemPrintfDebug(advertisement, "DNSServiceRegister %s %s %d\n", self->serviceName, self->serviceType, self->port); while (iterator) { UInt32 nameLength = FskStrLen(iterator->name); UInt32 valueLength = FskStrLen(iterator->value); length = nameLength + 1 + valueLength; if (length <= 255) { size += length + 1; err = txt ? FskMemPtrRealloc(size + 1, &txt) : FskMemPtrNew(size + 1, &txt); if (err) size -= length + 1; else { txt[offset++] = (char)length; FskStrCopy(txt + offset, iterator->name); offset += nameLength; txt[offset++] = '='; FskStrCopy(txt + offset, iterator->value); offset += valueLength; txt[offset] = 0; } } iterator = FskAssociativeArrayIteratorNext(iterator); } FskAssociativeArrayIteratorDispose(iterator); error = DNSServiceRegister(&serviceRef, 0, 0, self->serviceName, self->serviceType, "", NULL, // use default host name htons(self->port), txt ? FskStrLen(txt) : 0, txt, KprZeroconfPlatformAdvertisementProcess, self); if (error != kDNSServiceErr_NoError) { FskInstrumentedItemPrintfDebug(advertisement, "DNSServiceRegister error %d\n", error); bailIfError(kFskErrNetworkErr); } bailIfError(KprZeroconfPlatformServiceNew(&advertisement->service, NULL, serviceRef, NULL, 0)); } bail: FskMemPtrDispose(txt); return err; }
FskErr KprHTTPClientReadCache(KprMessage message, KprHTTPCacheValue cached) { FskErr err = kFskErrNone; FskAssociativeArrayIterator iterate = NULL; bailIfError(KprHTTPCacheValueReadData(cached)); iterate = FskAssociativeArrayIteratorNew(cached->headers); while (iterate) { bailIfError(KprMessageSetResponseHeader(message, iterate->name, iterate->value)); iterate = FskAssociativeArrayIteratorNext(iterate); } message->response.body = cached->body; cached->body = NULL; message->response.size = cached->size; message->status = cached->status; bail: FskAssociativeArrayIteratorDispose(iterate); if (err) KprMemPtrDisposeAt(&cached->body); return err; }
// ------------------------------------------------------------------------ void FskHeaderIteratorDispose(FskHeaderIterator iter) { FskAssociativeArrayIteratorDispose(iter); }
Boolean KprHTTPClientPutTargetCache(KprHTTPTarget target) { FskErr err = kFskErrNone; char* control = NULL; KprHTTPClient self = gKprHTTPClient; KprMessage message = target->message; UInt32 date = 0; UInt32 maxAge = 0; UInt32 lifetime = 0; char* start; char* next; char* end; Boolean foundAge = false; Boolean revalidate = false; KprHTTPCacheValue cached = NULL; bailIfError(message->error || !FskStrCompareCaseInsensitiveWithLength(message->url, "https://", 8) || ((message->status != 200) && (message->status != 203)) || (message->method && FskStrCompare(message->method, "GET")) // only caching GET method || (message->user != NULL) // do not cache request with credentials || (message->password != NULL) // do not cache request with credentials || (message->response.size == 0) // only caching something || (message->response.size > 384000)); // not caching big files if ((control = KprMessageGetResponseHeader(message, kFskStrCacheControl))) { start = control; end = control + FskStrLen(control); // split while (start < end) { if (*start == ',') *start = 0; start++; } start = control; while (start <= end) { next = start + FskStrLen(start) + 1; start = FskStrStripHeadSpace(start); if (!FskStrCompareCaseInsensitiveWithLength(start, "max-age", 7)) { bailIfError(!(start = FskStrStripHeadSpace(start + 7))); bailIfError(*start != '='); bailIfError(!(start = FskStrStripHeadSpace(start + 1))); maxAge = FskStrToNum(start); foundAge = true; } else if (!FskStrCompareCaseInsensitiveWithLength(start, "no-cache", 8)) { revalidate = true; } else if (!FskStrCompareCaseInsensitiveWithLength(start, "no-store", 8)) { BAIL(kFskErrInvalidParameter); } else if (!FskStrCompareCaseInsensitiveWithLength(start, "must-revalidate", 15)) { revalidate = true; } start = next; } } KprDateFromHTTP(KprMessageGetResponseHeader(message, kprHTTPHeaderDate), &date); if (foundAge) lifetime = maxAge; else { UInt32 expire = 0; KprDateFromHTTP(KprMessageGetResponseHeader(message, kFskStrExpires), &expire); if (date && expire) lifetime = (expire > date) ? expire - date : 0; else if (!KprMessageGetResponseHeader(message, kprHTTPHeaderETag) && !KprMessageGetResponseHeader(message, kprHTTPHeaderLastModified)) BAIL(kFskErrInvalidParameter); // not cached } if (KprMessageGetResponseHeader(message, kprHTTPHeaderVary)) revalidate = true; if (!revalidate) lifetime += 180; // guess 3 minutes // put in cache // fprintf(stderr, "%p: CACHE %s for %d (%d)\n", message, message->url, lifetime, revalidate); bailIfError(KprHTTPCacheValueNew(&cached)); KprDateFromHTTP(KprMessageGetResponseHeader(message, kprHTTPHeaderAge), &cached->age); cached->date = date; cached->lifetime = lifetime; cached->requestDate = target->requestDate; cached->responseDate = target->responseDate; cached->status = message->status; cached->headers = FskAssociativeArrayNew(); { FskAssociativeArrayIterator iterate = FskAssociativeArrayIteratorNew(message->response.headers); while (iterate) { FskAssociativeArrayElementSet(cached->headers, iterate->name, iterate->value, 0, kFskStringType); iterate = FskAssociativeArrayIteratorNext(iterate); } FskAssociativeArrayIteratorDispose(iterate); } KprHTTPCacheValueCleanupHeaders(cached); cached->size = message->response.size; cached->body = message->response.body; target->cached = cached; bailIfError(KprHTTPCachePut(self->cache, message->url, cached)); bail: if (control) { // unsplit start = control; while (start < end) { if (*start == 0) *start = ','; start++; } } if (err == kFskErrNone) return true; target->cached = NULL; if (cached) KprMemPtrDispose(cached); return false; }