/* Single-Instance methods get exactly one queue per URI. This is
also used for the Access queue method */
if (Config->SingleInstance == true || QueueMode == QueueAccess)
- return U.Access;
+ return U.Access;
+ string name(U.Access + ':' + U.Host);
- return U.Access + ':' + U.Host;
+ int parallel(_config->FindI("Acquire::"+U.Access+"::MaxParallel",0));
+ if (parallel <= 0)
+ return name;
+
+ typedef map<string, int> indexmap;
+ static indexmap indices;
+
+ pair<indexmap::iterator, bool> cache(indices.insert(indexmap::value_type(name, -1)));
+ if (cache.second || cache.first->second == -1) {
+ int &index(indices[U.Access]);
+ if (index >= parallel)
+ index = 0;
+ cache.first->second = index++;
+ }
+
+ ostringstream value;
+ value << U.Access << "::" << cache.first->second;
+ return value.str();
}
/*}}}*/
// Acquire::GetConfig - Fetch the configuration information /*{{{*/
return 0;
/* if a method uses DownloadLimit, we switch to SingleInstance mode */
- if(_config->FindI("Acquire::"+Access+"::DlLimit",0) > 0)
+ if(_config->FindI("Acquire::"+Access+"::Dl-Limit",0) > 0)
Conf->SingleInstance = true;
return Conf;
#include <string.h>
#include <iostream>
#include <apti18n.h>
+#include <set>
// Internet stuff
#include <netdb.h>
}
/*}}}*/
+static const CFOptionFlags kNetworkEvents =
+ kCFStreamEventOpenCompleted |
+ kCFStreamEventHasBytesAvailable |
+ kCFStreamEventEndEncountered |
+ kCFStreamEventErrorOccurred |
+0;
+
+static void CFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType event, void *arg) {
+ switch (event) {
+ case kCFStreamEventOpenCompleted:
+ break;
+
+ case kCFStreamEventHasBytesAvailable:
+ case kCFStreamEventEndEncountered:
+ *reinterpret_cast<int *>(arg) = 1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
+
+ case kCFStreamEventErrorOccurred:
+ *reinterpret_cast<int *>(arg) = -1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
+ }
+}
+
+/* http://lists.apple.com/archives/Macnetworkprog/2006/Apr/msg00014.html */
+int CFReadStreamOpen(CFReadStreamRef stream, double timeout) {
+ CFStreamClientContext context;
+ int value(0);
+
+ memset(&context, 0, sizeof(context));
+ context.info = &value;
+
+ if (CFReadStreamSetClient(stream, kNetworkEvents, CFReadStreamCallback, &context)) {
+ CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ if (CFReadStreamOpen(stream))
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false);
+ else
+ value = -1;
+ CFReadStreamSetClient(stream, kCFStreamEventNone, NULL, NULL);
+ }
+
+ return value;
+}
+
// HttpMethod::SendReq - Send the HTTP request /*{{{*/
// ---------------------------------------------------------------------
/* This places the http request in the outbound buffer */
signal(SIGINT,SigTerm);
Server = 0;
+
+ std::set<std::string> cached;
int FailCounter = 0;
while (1)
URI uri = std::string(url);
std::string hs = uri.Host;
+ if (cached.find(hs) != cached.end()) {
+ _error->Error("Cached Failure");
+ Fail(true);
+ free(url);
+ FailCounter = 0;
+ continue;
+ }
+
std::string urs = uri;
for (;;) {
if (UniqueID_ != NULL)
CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Unique-ID"), UniqueID_);
- CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.484"));
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.534"));
CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm);
CFRelease(hm);
+#define _kCFStreamPropertyReadTimeout CFSTR("_kCFStreamPropertyReadTimeout")
+#define _kCFStreamPropertyWriteTimeout CFSTR("_kCFStreamPropertyWriteTimeout")
+#define _kCFStreamPropertySocketImmediateBufferTimeOut CFSTR("_kCFStreamPropertySocketImmediateBufferTimeOut")
+
+ /*SInt32 to(TimeOut);
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &to));*/
+ double to(TimeOut);
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &to));
+
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyReadTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyWriteTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertySocketImmediateBufferTimeOut, nm);
+ CFRelease(nm);
+
CFDictionaryRef dr = SCDynamicStoreCopyProxies(NULL);
CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPProxy, dr);
CFRelease(dr);
Status("Connecting to %s", hs.c_str());
- if (!CFReadStreamOpen(rs)) {
- CfrsError("Open", rs);
- Fail(true);
+ switch (CFReadStreamOpen(rs, to)) {
+ case -1:
+ CfrsError("Open", rs);
+ goto fail;
+
+ case 0:
+ _error->Error("Host Unreachable");
+ cached.insert(hs);
+ goto fail;
+
+ case 1:
+ /* success */
+ break;
+
+ fail:
+ Fail(true);
goto done;
}
if (rd == -1) {
CfrsError(uri.Host.c_str(), rs);
+ cached.insert(hs);
Fail(true);
goto done;
}
}
}
+ if (sc < 200 || sc >= 300 && sc != 304) {
+ sr = CFHTTPMessageCopyResponseStatusLine(hm);
+
+ size_t ln = CFStringGetLength(sr) + 1;
+ char cr[ln];
+
+ if (!CFStringGetCString(sr, cr, ln, se)) {
+ Fail();
+ goto done;
+ }
+
+ CFRelease(sr);
+
+ _error->Error("%s", cr);
+
+ Fail();
+ goto done_;
+ }
+
CFRelease(hm);
if (sc == 304) {
Res.IMSHit = true;
Res.LastModified = Queue->LastModified;
URIDone(Res);
- } else if (sc < 200 || sc >= 300)
- Fail();
- else {
+ } else {
Hashes hash;
File = new FileFd(Queue->DestFile, FileFd::WriteAny);
#include <string.h>
#include <iostream>
#include <apti18n.h>
+#include <set>
// Internet stuff
#include <netdb.h>
}
/*}}}*/
+static const CFOptionFlags kNetworkEvents =
+ kCFStreamEventOpenCompleted |
+ kCFStreamEventHasBytesAvailable |
+ kCFStreamEventEndEncountered |
+ kCFStreamEventErrorOccurred |
+0;
+
+static void CFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType event, void *arg) {
+ switch (event) {
+ case kCFStreamEventOpenCompleted:
+ break;
+
+ case kCFStreamEventHasBytesAvailable:
+ case kCFStreamEventEndEncountered:
+ *reinterpret_cast<int *>(arg) = 1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
+
+ case kCFStreamEventErrorOccurred:
+ *reinterpret_cast<int *>(arg) = -1;
+ CFRunLoopStop(CFRunLoopGetCurrent());
+ break;
+ }
+}
+
+/* http://lists.apple.com/archives/Macnetworkprog/2006/Apr/msg00014.html */
+int CFReadStreamOpen(CFReadStreamRef stream, double timeout) {
+ CFStreamClientContext context;
+ int value(0);
+
+ memset(&context, 0, sizeof(context));
+ context.info = &value;
+
+ if (CFReadStreamSetClient(stream, kNetworkEvents, CFReadStreamCallback, &context)) {
+ CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ if (CFReadStreamOpen(stream))
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false);
+ else
+ value = -1;
+ CFReadStreamSetClient(stream, kCFStreamEventNone, NULL, NULL);
+ }
+
+ return value;
+}
+
// HttpMethod::SendReq - Send the HTTP request /*{{{*/
// ---------------------------------------------------------------------
/* This places the http request in the outbound buffer */
signal(SIGINT,SigTerm);
Server = 0;
+
+ std::set<std::string> cached;
int FailCounter = 0;
while (1)
URI uri = std::string(url);
std::string hs = uri.Host;
+ if (cached.find(hs) != cached.end()) {
+ _error->Error("Cached Failure");
+ Fail(true);
+ free(url);
+ FailCounter = 0;
+ continue;
+ }
+
std::string urs = uri;
for (;;) {
if (UniqueID_ != NULL)
CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Unique-ID"), UniqueID_);
- CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.484"));
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.534"));
CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm);
CFRelease(hm);
+#define _kCFStreamPropertyReadTimeout CFSTR("_kCFStreamPropertyReadTimeout")
+#define _kCFStreamPropertyWriteTimeout CFSTR("_kCFStreamPropertyWriteTimeout")
+#define _kCFStreamPropertySocketImmediateBufferTimeOut CFSTR("_kCFStreamPropertySocketImmediateBufferTimeOut")
+
+ /*SInt32 to(TimeOut);
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &to));*/
+ double to(TimeOut);
+ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &to));
+
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyReadTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertyWriteTimeout, nm);
+ CFReadStreamSetProperty(rs, _kCFStreamPropertySocketImmediateBufferTimeOut, nm);
+ CFRelease(nm);
+
CFDictionaryRef dr = SCDynamicStoreCopyProxies(NULL);
CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPProxy, dr);
CFRelease(dr);
Status("Connecting to %s", hs.c_str());
- if (!CFReadStreamOpen(rs)) {
- CfrsError("Open", rs);
- Fail(true);
+ switch (CFReadStreamOpen(rs, to)) {
+ case -1:
+ CfrsError("Open", rs);
+ goto fail;
+
+ case 0:
+ _error->Error("Host Unreachable");
+ cached.insert(hs);
+ goto fail;
+
+ case 1:
+ /* success */
+ break;
+
+ fail:
+ Fail(true);
goto done;
}
if (rd == -1) {
CfrsError(uri.Host.c_str(), rs);
+ cached.insert(hs);
Fail(true);
goto done;
}
}
}
+ if (sc < 200 || sc >= 300 && sc != 304) {
+ sr = CFHTTPMessageCopyResponseStatusLine(hm);
+
+ size_t ln = CFStringGetLength(sr) + 1;
+ char cr[ln];
+
+ if (!CFStringGetCString(sr, cr, ln, se)) {
+ Fail();
+ goto done;
+ }
+
+ CFRelease(sr);
+
+ _error->Error("%s", cr);
+
+ Fail();
+ goto done_;
+ }
+
CFRelease(hm);
if (sc == 304) {
Res.IMSHit = true;
Res.LastModified = Queue->LastModified;
URIDone(Res);
- } else if (sc < 200 || sc >= 300)
- Fail();
- else {
+ } else {
Hashes hash;
File = new FileFd(Queue->DestFile, FileFd::WriteAny);