00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <time.h>
00021 #include <sys/time.h>
00022 #include <sys/types.h>
00023 #include <unistd.h>
00024
00025 #include <string.h>
00026 #include <string>
00027
00028 #include <wwwsys.h>
00029 #include <WWWUtil.h>
00030 #include <WWWCore.h>
00031 #include <WWWInit.h>
00032 #include <HTReqMan.h>
00033 #include <HTTimer.h>
00034 #include <HTEvent.h>
00035 #include <HTEvtLst.h>
00036 #include <HTDialog.h>
00037
00038 #include <archon/util/logger.H>
00039 #include <archon/util/text.H>
00040 #include <archon/util/uri.H>
00041 #include <archon/util/pipe.H>
00042 #include <archon/util/web_client.H>
00043
00044 namespace Archon
00045 {
00046 namespace Utilities
00047 {
00048 namespace Web
00049 {
00050 using namespace std;
00051
00052 namespace
00053 {
00054 struct SockEvents
00055 {
00056 SOCKET s;
00057 HTEvent *events[HTEvent_TYPES];
00058 HTTimer *timeouts[HTEvent_TYPES];
00059 };
00060
00061 struct EventOrder
00062 {
00063 HTEvent *event;
00064 SOCKET s;
00065 HTEventType type;
00066 HTPriority skipped;
00067 };
00068
00069 enum SockEvents_action
00070 {
00071 SockEvents_mayCreate,
00072 SockEvents_find
00073 };
00074
00075 fd_set FdArray[HTEvent_TYPES];
00076 SOCKET maxSocket = 0;
00077 const int eventsToExecute = 10;
00078 HTList *hashTable[HT_M_HASH_SIZE];
00079 HTList *eventOrderList = 0;
00080
00081
00082 SockEvents *getSockEvents(SOCKET s, SockEvents_action action)
00083 {
00084 long v = s % HT_M_HASH_SIZE;
00085 HTList *cur;
00086 SockEvents *pres;
00087
00088
00089 if(s == INVSOC) return 0;
00090
00091 if(hashTable[v] == 0) hashTable[v] = HTList_new();
00092 cur = hashTable[v];
00093 while((pres = static_cast<SockEvents *>(HTList_nextObject(cur))))
00094 if(pres->s == s) return pres;
00095
00096 if(action == SockEvents_mayCreate)
00097 {
00098 if((pres = static_cast<SockEvents *>(HT_CALLOC(1, sizeof(SockEvents)))) == 0)
00099 HT_OUTOFMEM("HTEventList_register");
00100 pres->s = s;
00101 HTList_addObject(hashTable[v], static_cast<void *>(pres));
00102 return pres;
00103 }
00104 return 0;
00105 }
00106
00107 int remainingEventTypes(SockEvents *pres)
00108 {
00109 int ret = 0;
00110 for(int i = 0; i < HTEvent_TYPES; ++i)
00111 if(pres->events[i] != 0) ret |= 1<<i;
00112 return ret;
00113 }
00114
00115
00116
00117
00118
00119
00120 int eventTimeoutHandler(HTTimer *timer, void *param, HTEventType type)
00121 {
00122 SockEvents *sockp = static_cast<SockEvents *>(param);
00123 HTEvent *event = 0;
00124
00125
00126 if(sockp->timeouts[HTEvent_INDEX(HTEvent_READ)] == timer)
00127 {
00128 event = sockp->events[HTEvent_INDEX(HTEvent_READ)];
00129 HTTRACE(THD_TRACE, "Event....... READ timed out on %d.\n" _ sockp->s);
00130 return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
00131 }
00132
00133
00134 if(sockp->timeouts[HTEvent_INDEX(HTEvent_WRITE)] == timer)
00135 {
00136 event = sockp->events[HTEvent_INDEX(HTEvent_WRITE)];
00137 HTTRACE(THD_TRACE, "Event....... WRITE timed out on %d.\n" _ sockp->s);
00138 return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
00139 }
00140
00141
00142 if(sockp->timeouts[HTEvent_INDEX(HTEvent_OOB)] == timer)
00143 {
00144 event = sockp->events[HTEvent_INDEX(HTEvent_OOB)];
00145 HTTRACE(THD_TRACE, "Event....... OOB timed out on %d.\n" _ sockp->s);
00146 return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
00147 }
00148 HTTRACE(THD_TRACE, "Event....... No event for timer %p with context %p\n" _ timer _ param);
00149 return HT_ERROR;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 int registerEvent(SOCKET s, HTEventType type, HTEvent *event)
00161 {
00162 int newset = 0;
00163 SockEvents *sockp;
00164 HTTRACE(THD_TRACE, "Event....... Register socket %d, request %p handler %p type %s at priority %d\n" _
00165 s _ reinterpret_cast<unsigned>(event->request) _
00166 reinterpret_cast<unsigned>(event->cbf) _ HTEvent_type2str(type) _
00167 static_cast<unsigned>(event->priority));
00168 if(s==INVSOC || HTEvent_INDEX(type) >= HTEvent_TYPES) return 0;
00169
00170
00171
00172
00173
00174 HTTRACE(THD_TRACE, "Event....... Registering socket for %s\n" _ HTEvent_type2str(type));
00175 sockp = getSockEvents(s, SockEvents_mayCreate);
00176 sockp->s = s;
00177 sockp->events[HTEvent_INDEX(type)] = event;
00178 newset = remainingEventTypes(sockp);
00179 FD_SET(s, FdArray+HTEvent_INDEX(type));
00180
00181 HTTRACEDATA(reinterpret_cast<char *>(FdArray)+HTEvent_INDEX(type), 8, "HTEventList_register: (s:%d)" _ s);
00182
00183 if(s > maxSocket)
00184 {
00185 maxSocket = s ;
00186 HTTRACE(THD_TRACE, "Event....... New value for maxSocket is %d\n" _ maxSocket);
00187 }
00188
00189
00190
00191
00192
00193 if(event->millis >= 0)
00194 {
00195 sockp->timeouts[HTEvent_INDEX(type)] =
00196 HTTimer_new(sockp->timeouts[HTEvent_INDEX(type)],
00197 eventTimeoutHandler, sockp, event->millis, YES, YES);
00198 }
00199
00200 return HT_OK;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 int unregisterEvent(SOCKET s, HTEventType type)
00210 {
00211 long v = s % HT_M_HASH_SIZE;
00212 HTList *cur = hashTable[v];
00213 HTList *last = cur;
00214 SockEvents *pres;
00215 int ret = HT_ERROR;
00216
00217
00218 if(s == INVSOC) return HT_OK;
00219
00220 while(cur && (pres = static_cast<SockEvents *>(HTList_nextObject(cur))))
00221 {
00222 if(pres->s == s)
00223 {
00224 int remaining = 0;
00225
00226
00227
00228
00229 pres->events[HTEvent_INDEX(type)] = 0;
00230 remaining = remainingEventTypes(pres);
00231
00232
00233
00234
00235
00236 {
00237 HTTimer *timer = pres->timeouts[HTEvent_INDEX(type)];
00238 if(timer) HTTimer_delete(timer);
00239 pres->timeouts[HTEvent_INDEX(type)] = 0;
00240 }
00241
00242 FD_CLR(s, FdArray+HTEvent_INDEX(type));
00243
00244 HTTRACEDATA(reinterpret_cast<char *>(FdArray)+HTEvent_INDEX(type), 8, "HTEventList_unregister: (s:%d)" _ s);
00245
00246
00247
00248
00249
00250 if(remaining == 0)
00251 {
00252 HTList *doomed = cur;
00253 HTTRACE(THD_TRACE, "Event....... No more events registered for socket %d\n" _ s);
00254 HT_FREE(pres);
00255 pres = static_cast<SockEvents *>(HTList_nextObject(cur));
00256 HTList_quickRemoveElement(doomed, last);
00257 }
00258 ret = HT_OK;
00259
00260 HTTRACE(THD_TRACE, "Event....... Socket %d unregistered for %s\n" _ s _
00261 HTEvent_type2str(type));
00262
00263
00264 break;
00265 }
00266 last = cur;
00267 }
00268 if(THD_TRACE)
00269 {
00270 if(ret == HT_ERROR)
00271 HTTRACE(THD_TRACE, "Event....... Couldn't find socket %d. Can't unregister type %s\n" _
00272 s _ HTEvent_type2str(type));
00273 }
00274 return ret;
00275 }
00276
00277
00278 int addEvent(SOCKET s, HTEventType type, ms_t now)
00279 {
00280 EventOrder *pres;
00281 HTList *cur = eventOrderList;
00282 HTList *insertAfter = cur;
00283 SockEvents *sockp = getSockEvents(s, SockEvents_find);
00284 HTEvent *event;
00285
00286 if(sockp == 0 || (event = sockp->events[HTEvent_INDEX(type)]) == 0)
00287 {
00288 HTTRACE(THD_TRACE, "EventOrder.. no event found for socket %d, type %s.\n" _
00289 s _ HTEvent_type2str(type));
00290 return HT_ERROR;
00291 }
00292
00293
00294 if(sockp->timeouts[HTEvent_INDEX(type)])
00295 HTTimer_refresh(sockp->timeouts[HTEvent_INDEX(type)], now);
00296
00297
00298 while((pres = static_cast<EventOrder *>(HTList_nextObject(cur))))
00299 {
00300 if(pres->s == s && pres->event == event && pres->type == type)
00301 {
00302 ++*(reinterpret_cast<int *>(&(pres->skipped)));
00303 return HT_OK;
00304 }
00305 if(pres->event->priority+pres->skipped > event->priority)
00306 insertAfter = cur;
00307 }
00308
00309
00310 if((pres = static_cast<EventOrder *>(HT_CALLOC(1, sizeof(EventOrder)))) == 0)
00311 HT_OUTOFMEM("EventOrder_add");
00312 pres->event = event;
00313 pres->s = s;
00314 pres->type = type;
00315 HTList_addObject(insertAfter, static_cast<void *>(pres));
00316 return HT_OK;
00317 }
00318
00319 int executeAndDeleteEvents()
00320 {
00321 HTList *cur = eventOrderList;
00322 EventOrder *pres;
00323 int i = 0;
00324 HTTRACE(THD_TRACE, "EventOrder.. execute ordered events\n");
00325 if(cur == 0) return NO;
00326 while((pres = static_cast<EventOrder *>(HTList_removeLastObject(cur))) && i<eventsToExecute)
00327 {
00328 HTEvent *event = pres->event;
00329 int ret;
00330 HTTRACE(THD_TRACE, "EventList... calling socket %d, request %p handler %p type %s\n" _
00331 pres->s _ reinterpret_cast<unsigned>(event->request) _
00332 reinterpret_cast<unsigned>(event->cbf) _ HTEvent_type2str(pres->type));
00333 ret = (*pres->event->cbf)(pres->s, pres->event->param, pres->type);
00334 HT_FREE(pres);
00335 if(ret != HT_OK) return ret;
00336 i++;
00337 }
00338 return HT_OK;
00339 }
00340
00341 bool clearAllEvents()
00342 {
00343 HTList *cur = eventOrderList;
00344 EventOrder *pres;
00345 HTTRACE(THD_TRACE, "EventOrder.. Clearing all ordered events\n");
00346 if(cur)
00347 {
00348 while((pres = static_cast<EventOrder *>(HTList_nextObject(cur))))
00349 HT_FREE(pres);
00350 return true;
00351 }
00352 return false;
00353 }
00354
00355 int printer(const char *fmt, va_list pArgs) throw()
00356 {
00357 return HT_OK;
00358 }
00359
00360 int tracer(const char *fmt, va_list pArgs) throw()
00361 {
00362 return HT_OK;
00363 }
00364 }
00365
00366 Mutex clientExistsMutex;
00367 bool clientExists = false;
00368
00369 struct DefaultClient: Client
00370 {
00371 string applicationName;
00372 string applicationVersion;
00373 string cacheRootPath;
00374 long cacheSize;
00375 int maxSockets;
00376 Time eventHandlerMaxIdle;
00377
00378 Mutex mutex;
00379 bool libwwwInitialized;
00380
00381 bool eventHandlerActive;
00382 unsigned numberOfRequests;
00383 bool terminate;
00384
00385 Condition requestChange;
00386 Condition eventHandlerQuit;
00387
00388 DefaultClient(string applicationName, string applicationVersion,
00389 string cacheRootPath, long cacheSize,
00390 int maxSockets) throw(UnexpectedException):
00391 applicationName(applicationName),
00392 applicationVersion(applicationVersion),
00393 cacheRootPath(cacheRootPath),
00394 cacheSize(cacheSize),
00395 maxSockets(maxSockets),
00396 eventHandlerMaxIdle(10.0),
00397 libwwwInitialized(false),
00398 eventHandlerActive(false),
00399 numberOfRequests(0),
00400 terminate(false),
00401 requestChange(mutex),
00402 eventHandlerQuit(mutex)
00403 {
00404 Mutex::Lock l(clientExistsMutex);
00405 if(clientExists)
00406 ARCHON_THROW1(ResourceException,
00407 "Only one client may exist at a time");
00408 clientExists = true;
00409 }
00410
00411 ~DefaultClient()
00412 {
00413 {
00414 Mutex::Lock l(mutex);
00415 if(libwwwInitialized)
00416 {
00417
00418 HTNet_killAll();
00419
00420
00421 terminate = true;
00422 requestChange.notifyAll();
00423 while(eventHandlerActive) eventHandlerQuit.wait();
00424
00425 clearAllEvents();
00426
00427
00428 HTCacheTerminate();
00429
00430
00431 HTFormat_deleteAll();
00432
00433
00434 HTBind_deleteAll();
00435
00436
00437 HTLibTerminate();
00438
00439 libwwwInitialized = false;
00440 }
00441 }
00442 {
00443 Mutex::Lock l(clientExistsMutex);
00444 clientExists = false;
00445 }
00446 }
00447
00448 Ref<Response> request(Ref<Request>) throw(RequestException);
00449 };
00450
00451 Ref<Client> Client::get(string applicationName,
00452 string applicationVersion, int maxSockets)
00453 throw(UnexpectedException)
00454 {
00455 return new DefaultClient(applicationName, applicationVersion,
00456 "", -1, maxSockets);
00457 }
00458
00459 Ref<Client> Client::get(string applicationName,
00460 string applicationVersion,
00461 string cacheRootPath, long cacheSize,
00462 int maxSockets)
00463 throw(UnexpectedException)
00464 {
00465 return new DefaultClient(applicationName, applicationVersion,
00466 cacheRootPath, cacheSize, maxSockets);
00467 }
00468
00469 struct DefaultRequest: Client::Request
00470 {
00471 DefaultRequest(const Uri &uri): Client::Request(uri) {}
00472 };
00473
00474 Ref<Client::Request> Client::Request::get(const Uri &uri)
00475 {
00476 return new DefaultRequest(uri);
00477 }
00478
00479 HTErrorMessage libwwwErrors[HTERR_ELEMENTS] = {HTERR_ENGLISH_INITIALIZER};
00480
00481 struct DefaultResponse: Client::Response, Stream::Pipe
00482 {
00483 DefaultResponse(DefaultClient *client):
00484 Stream::Pipe(4096, true), client(client),
00485 setupDone(false), setup(*this) {}
00486
00487 string getContentType()
00488 {
00489 return contentType;
00490 }
00491
00495 void doSetup(HTRequest *request)
00496 {
00497 HTParentAnchor *anchor = HTRequest_anchor(request);
00498 HTFormat format = HTAnchor_format(anchor);
00499 {
00500 Mutex::Lock l(*this);
00501 contentType = HTAtom_name(format);
00502 setupDone = true;
00503 }
00504 setup.notifyAll();
00505 }
00506
00510 void setError(HTRequest *request, int status)
00511 {
00512 string m;
00513 if(HTList *l = HTRequest_error(request))
00514 while(HTError *e = (HTError *)HTList_nextObject(l))
00515 {
00516 if(m.size()) m += ", ";
00517 HTErrorMessage &n = libwwwErrors[HTError_index(e)];
00518 if(n.code) m += Text::toString(n.code) + " - ";
00519 m += n.msg;
00520 break;
00521 }
00522 if(!m.size()) m += Text::toString(status);
00523 {
00524 Mutex::Lock l(*this);
00525 error = m;
00526 setupDone = true;
00527 }
00528 setup.notifyAll();
00529 }
00530
00531 void waitForSetup()
00532 {
00533 Mutex::Lock l(*this);
00534 while(!setupDone) setup.wait();
00535 }
00536
00537 DefaultClient *client;
00538
00539 string error;
00540 string contentType;
00541
00542 bool setupDone;
00543 Condition setup;
00544
00545 void refDispose(Mutex::Lock &l)
00546 {
00547 Stream::Pipe::refDispose(l);
00548 }
00549 };
00550
00551
00552
00553 namespace
00554 {
00555 struct LibwwwStream;
00556
00557 struct LibwwwStreamClass
00558 {
00559 char *name;
00560 int (*flush)(LibwwwStream *);
00561 int (*_free)(LibwwwStream *);
00562 int (*abort)(LibwwwStream *, HTList *errorlist);
00563 int (*put_character)(LibwwwStream *, char);
00564 int (*put_string)(LibwwwStream *, const char *);
00565 int (*put_block)(LibwwwStream *, const char *, int);
00566 };
00567
00568 struct LibwwwStream
00569 {
00570 const LibwwwStreamClass *isa;
00571 HTRequest *request;
00572 Ref<Stream::Writer> writer;
00573 DefaultResponse *response;
00574 bool setupDone;
00575
00576 LibwwwStream(HTRequest *request,
00577 Ref<Stream::Writer> writer,
00578 DefaultResponse *response);
00579 };
00580
00581 int libwwwFlush(LibwwwStream *) throw() { return HT_OK; }
00582 int libwwwFree(LibwwwStream *) throw() { return HT_OK; }
00583
00587 int libwwwAbort(LibwwwStream *, HTList *errorlist) throw()
00588 {
00589 cerr << "Libwww::Stream::ABORT\n"; return HT_ERROR;
00590 }
00591
00595 void doSetup(LibwwwStream *stream)
00596 {
00597 stream->response->doSetup(stream->request);
00598 stream->setupDone = true;
00599 }
00600
00604 int libwwwPutCharacter(LibwwwStream *stream, char c) throw()
00605 {
00606 if(!stream->setupDone) doSetup(stream);
00607 try
00608 {
00609 stream->response->write(&c, 1);
00610 }
00611 catch(Stream::WriteException &) { return HT_ERROR; }
00612 catch(ThreadTerminatedException &) { return HT_ERROR; }
00613 return HT_OK;
00614 }
00615
00619 int libwwwPutString(LibwwwStream *stream, const char *s) throw()
00620 {
00621 if(!stream->setupDone) doSetup(stream);
00622 try
00623 {
00624 stream->response->writeAll(s, strlen(s));
00625 }
00626 catch(Stream::WriteException &) { return HT_ERROR; }
00627 catch(ThreadTerminatedException &) { return HT_ERROR; }
00628 return HT_OK;
00629 }
00630
00636 int libwwwPutBlock(LibwwwStream *stream, const char *b, int l) throw()
00637 {
00638 if(!stream->setupDone) doSetup(stream);
00639 try
00640 {
00641 stream->response->writeAll(b, l);
00642 }
00643 catch(Stream::WriteException &) { return HT_ERROR; }
00644 catch(ThreadTerminatedException &) { return HT_ERROR; }
00645 return HT_OK;
00646 }
00647
00648 const LibwwwStreamClass libwwwRequestContextClass =
00649 {
00650 "libwwwStream",
00651 libwwwFlush,
00652 libwwwFree,
00653 libwwwAbort,
00654 libwwwPutCharacter,
00655 libwwwPutString,
00656 libwwwPutBlock
00657 };
00658
00659 LibwwwStream::LibwwwStream(HTRequest *request,
00660 Ref<Stream::Writer> writer,
00661 DefaultResponse *response):
00662 isa(&libwwwRequestContextClass),
00663 request(request), writer(writer), response(response),
00664 setupDone(false) {}
00665
00666
00667
00668 int terminateConnection(HTRequest *request, HTResponse *response,
00669 void *param, int status) throw()
00670 {
00671 LibwwwStream *stream =
00672 static_cast<LibwwwStream *>(HTRequest_context(request));
00673
00674 if(!stream->setupDone)
00675 {
00676 if(status == 200) stream->response->doSetup(request);
00677 else stream->response->setError(request, status);
00678 }
00679
00680 --stream->response->client->numberOfRequests;
00681
00682 delete stream;
00683
00684
00685 return HT_OK;
00686 }
00687
00688
00689 void libwwwEventHandler(DefaultClient *client)
00690 {
00691
00692
00693 Mutex::Lock l(client->mutex);
00694
00695 for(;;)
00696 {
00697 ms_t timeout;
00698 fd_set treadset;
00699 fd_set twriteset;
00700 fd_set texceptset;
00701 int maxfds;
00702
00703 Time wakeup = Time::now();
00704 wakeup += client->eventHandlerMaxIdle;
00705
00706
00707
00708 for(;;)
00709 {
00710 if(!client->terminate)
00711 {
00712 if(client->numberOfRequests) break;
00713 if(!client->requestChange.timedWait(wakeup)) continue;
00714 }
00715
00716
00717 client->eventHandlerActive = false;
00718
00719 client->eventHandlerQuit.notifyAll();
00720 l.release();
00721 return;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 if(HTTimer_next(&timeout))
00733 ARCHON_THROW1(InternalException,
00734 "HTTimer_next failed");
00735
00736
00737
00738
00739 treadset = FdArray[HTEvent_INDEX(HTEvent_READ)];
00740 twriteset = FdArray[HTEvent_INDEX(HTEvent_WRITE)];
00741 texceptset = FdArray[HTEvent_INDEX(HTEvent_OOB)];
00742
00743
00744 maxfds = maxSocket;
00745
00746 wakeup = Time::now();
00747 wakeup.addMilliSeconds(timeout);
00748 int activeSockets = client->requestChange.select(maxfds+1, &treadset, &twriteset, &texceptset, wakeup);
00749 if(activeSockets <= 0) continue;
00750
00751 unsigned long now = HTGetTimeInMillis();
00752
00753
00754 for(SOCKET s = 0; s <= maxfds; ++s)
00755 {
00756 if(FD_ISSET(s, &texceptset) && addEvent(s, HTEvent_OOB, now) != HT_OK)
00757 ARCHON_THROW1(InternalException,
00758 "addEvent failed");
00759 if(FD_ISSET(s, &twriteset) && addEvent(s, HTEvent_WRITE, now) != HT_OK)
00760 ARCHON_THROW1(InternalException,
00761 "addEvent failed");
00762 if(FD_ISSET(s, &treadset) && addEvent(s, HTEvent_READ, now) != HT_OK)
00763 ARCHON_THROW1(InternalException,
00764 "addEvent failed");
00765 }
00766 if(executeAndDeleteEvents() != HT_OK)
00767 ARCHON_THROW1(InternalException,
00768 "executeAndDeleteEvents failed");
00769 }
00770 }
00771 }
00772
00773
00783 Ref<Client::Response> DefaultClient::request(Ref<Request> request) throw(RequestException)
00784 {
00785 bool startEventHandler = false;
00786
00787 Mutex::Lock l(mutex);
00788
00789 if(!libwwwInitialized)
00790 {
00791
00792 HTLibInit(applicationName.c_str(), applicationVersion.c_str());
00793
00794
00795 HTAlertInit();
00796 HTAlert_setInteractive(YES);
00797
00798
00799 HTTransportInit();
00800
00801
00802
00803 HTProtocolInit();
00804
00805
00806 HTBind_init();
00807
00808
00809 HTNet_setMaxSocket(maxSockets);
00810
00811
00812 if(cacheSize > 0) HTCacheInit(cacheRootPath.c_str(), cacheSize);
00813
00814
00815 HTNetInit();
00816
00817
00818 HTAAInit();
00819
00820
00821 HTProxy_getEnvVar();
00822
00823 HTList *converters = HTList_new();
00824
00825
00826 HTConverterInit(converters);
00827
00828
00829
00830
00831
00832 HTFormat_setConversion(converters);
00833
00834
00835
00836 HTList *transferEncodings = HTList_new();
00837 HTTransferEncoderInit(transferEncodings);
00838 HTFormat_setTransferCoding(transferEncodings);
00839
00840
00841 HTList *contentEncodings = HTList_new();
00842 HTContentEncoderInit(contentEncodings);
00843 if(HTList_count(contentEncodings) > 0)
00844 HTFormat_setContentCoding(contentEncodings);
00845 else
00846 {
00847 HTList_delete(contentEncodings);
00848 contentEncodings = 0;
00849 }
00850
00851
00852 HTMIMEInit();
00853
00854
00855 HTFileInit();
00856
00857
00858 HTIconInit(0);
00859
00860
00861 HTEvent_setRegisterCallback(registerEvent);
00862 HTEvent_setUnregisterCallback(unregisterEvent);
00863
00864
00865 HTPrint_setCallback(printer);
00866 HTTrace_setCallback(tracer);
00867
00868 HTSetTraceMessageMask("");
00869
00870
00871 HTNet_addAfter(terminateConnection, 0, 0, HT_ALL, HT_FILTER_LAST);
00872
00873 eventOrderList = HTList_new();
00874
00875 libwwwInitialized = true;
00876 }
00877
00878
00879 DefaultResponse *defaultResponse = new DefaultResponse(this);
00880 Ref<Response> response(defaultResponse);
00881 Ref<Stream::Writer> writer(defaultResponse);
00882
00883 HTRequest *htRequest = HTRequest_new();
00884
00885 LibwwwStream *stream = new LibwwwStream(htRequest, writer, defaultResponse);
00886
00887
00888 HTRequest_setOutputStream(htRequest, reinterpret_cast<HTStream *>(stream));
00889 HTRequest_setOutputFormat(htRequest, WWW_SOURCE);
00890
00891
00892 HTRequest_setContext(htRequest, stream);
00893
00894
00895 HTRequest_setPreemptive(htRequest, NO);
00896
00897 HTAnchor *anchor = HTAnchor_findAddress(request->getUri().toString().c_str());
00898
00899 ++numberOfRequests;
00900
00901 if(!eventHandlerActive) eventHandlerActive = startEventHandler = true;
00902
00903 HTLoadAnchor(anchor, htRequest);
00904
00905 l.release();
00906
00907 if(startEventHandler) Thread::run(libwwwEventHandler, this);
00908 else requestChange.notifyAll();
00909
00910 defaultResponse->waitForSetup();
00911 if(defaultResponse->error.size())
00912 ARCHON_THROW1(RequestException, defaultResponse->error);
00913
00914 return response;
00915 }
00916 }
00917 }
00918 }