server.c 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895
  1. /*
  2. Copyright (c) 2003-2006 by Juliusz Chroboczek
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "polipo.h"
  20. int serverExpireTime = 24 * 60 * 60;
  21. int smallRequestTime = 10;
  22. int replyUnpipelineTime = 20;
  23. int replyUnpipelineSize = 1024 * 1024;
  24. int pipelineAdditionalRequests = 1;
  25. int maxPipelineTrain = 10;
  26. AtomPtr parentProxy = NULL;
  27. AtomPtr parentHost = NULL;
  28. int parentPort = -1;
  29. int pmmFirstSize = 0, pmmSize = 0;
  30. int serverSlots = 2;
  31. int serverSlots1 = 4;
  32. int serverMaxSlots = 8;
  33. int dontCacheRedirects = 0;
  34. int maxSideBuffering = 1500;
  35. int maxConnectionAge = 1260;
  36. int maxConnectionRequests = 400;
  37. int alwaysAddNoTransform = 0;
  38. static HTTPServerPtr servers = 0;
  39. static int httpServerContinueConditionHandler(int, ConditionHandlerPtr);
  40. static int initParentProxy(void);
  41. static int parentProxySetter(ConfigVariablePtr var, void *value);
  42. static void httpServerDelayedFinish(HTTPConnectionPtr);
  43. static int allowUnalignedRangeRequests = 0;
  44. void
  45. preinitServer(void)
  46. {
  47. CONFIG_VARIABLE_SETTABLE(parentProxy, CONFIG_ATOM_LOWER, parentProxySetter,
  48. "Parent proxy (host:port).");
  49. CONFIG_VARIABLE(serverExpireTime, CONFIG_TIME,
  50. "Time during which server data is valid.");
  51. CONFIG_VARIABLE_SETTABLE(smallRequestTime, CONFIG_TIME, configIntSetter,
  52. "Estimated time for a small request.");
  53. CONFIG_VARIABLE_SETTABLE(replyUnpipelineTime, CONFIG_TIME, configIntSetter,
  54. "Estimated time for a pipeline break.");
  55. CONFIG_VARIABLE_SETTABLE(replyUnpipelineSize, CONFIG_INT, configIntSetter,
  56. "Size for a pipeline break.");
  57. CONFIG_VARIABLE_SETTABLE(pipelineAdditionalRequests, CONFIG_TRISTATE,
  58. configIntSetter,
  59. "Pipeline requests on an active connection.");
  60. CONFIG_VARIABLE_SETTABLE(maxPipelineTrain, CONFIG_INT,
  61. configIntSetter,
  62. "Maximum number of requests "
  63. "pipelined at a time.");
  64. CONFIG_VARIABLE(pmmFirstSize, CONFIG_INT,
  65. "The size of the first PMM chunk.");
  66. CONFIG_VARIABLE(pmmSize, CONFIG_INT,
  67. "The size of a PMM chunk.");
  68. CONFIG_VARIABLE(serverSlots, CONFIG_INT,
  69. "Maximum number of connections per server.");
  70. CONFIG_VARIABLE(serverSlots1, CONFIG_INT,
  71. "Maximum number of connections per HTTP/1.0 server.");
  72. CONFIG_VARIABLE(serverMaxSlots, CONFIG_INT,
  73. "Maximum number of connections per broken server.");
  74. CONFIG_VARIABLE(dontCacheRedirects, CONFIG_BOOLEAN,
  75. "If true, don't cache redirects.");
  76. CONFIG_VARIABLE_SETTABLE(allowUnalignedRangeRequests,
  77. CONFIG_BOOLEAN, configIntSetter,
  78. "Allow unaligned range requests (unreliable).");
  79. CONFIG_VARIABLE_SETTABLE(maxSideBuffering,
  80. CONFIG_INT, configIntSetter,
  81. "Maximum buffering for PUT and POST requests.");
  82. CONFIG_VARIABLE_SETTABLE(maxConnectionAge,
  83. CONFIG_TIME, configIntSetter,
  84. "Maximum age of a server-side connection.");
  85. CONFIG_VARIABLE_SETTABLE(maxConnectionRequests,
  86. CONFIG_INT, configIntSetter,
  87. "Maximum number of requests on a server-side connection.");
  88. CONFIG_VARIABLE(alwaysAddNoTransform, CONFIG_BOOLEAN,
  89. "If true, add a no-transform directive to all requests.");
  90. }
  91. static int
  92. parentProxySetter(ConfigVariablePtr var, void *value)
  93. {
  94. configAtomSetter(var, value);
  95. initParentProxy();
  96. return 1;
  97. }
  98. static void
  99. discardServer(HTTPServerPtr server)
  100. {
  101. HTTPServerPtr previous;
  102. assert(!server->request);
  103. if(server == servers)
  104. servers = server->next;
  105. else {
  106. previous = servers;
  107. while(previous->next != server)
  108. previous = previous->next;
  109. previous->next = server->next;
  110. }
  111. if(server->connection)
  112. free(server->connection);
  113. if(server->idleHandler)
  114. free(server->idleHandler);
  115. if(server->name)
  116. free(server->name);
  117. free(server);
  118. }
  119. static int
  120. httpServerIdle(HTTPServerPtr server)
  121. {
  122. int i;
  123. if(server->request)
  124. return 0;
  125. for(i = 0; i < server->maxslots; i++)
  126. if(server->connection[i])
  127. return 0;
  128. return 1;
  129. }
  130. static int
  131. expireServersHandler(TimeEventHandlerPtr event)
  132. {
  133. HTTPServerPtr server, next;
  134. TimeEventHandlerPtr e;
  135. server = servers;
  136. while(server) {
  137. next = server->next;
  138. if(httpServerIdle(server) &&
  139. server->time + serverExpireTime < current_time.tv_sec)
  140. discardServer(server);
  141. server = next;
  142. }
  143. e = scheduleTimeEvent(serverExpireTime / 60 + 60,
  144. expireServersHandler, 0, NULL);
  145. if(!e) {
  146. do_log(L_ERROR, "Couldn't schedule server expiry.\n");
  147. polipoExit();
  148. }
  149. return 1;
  150. }
  151. static int
  152. roundSize(int size)
  153. {
  154. return (size + CHUNK_SIZE - 1) / CHUNK_SIZE * CHUNK_SIZE;
  155. }
  156. static int
  157. initParentProxy()
  158. {
  159. AtomPtr host, port_atom;
  160. int rc, port;
  161. if(parentHost) {
  162. releaseAtom(parentHost);
  163. parentHost = NULL;
  164. }
  165. if(parentPort >= 0)
  166. parentPort = -1;
  167. if(parentProxy != NULL && parentProxy->length == 0) {
  168. releaseAtom(parentProxy);
  169. parentProxy = NULL;
  170. }
  171. if(parentProxy == NULL)
  172. return 1;
  173. rc = atomSplit(parentProxy, ':', &host, &port_atom);
  174. if(rc <= 0) {
  175. do_log(L_ERROR, "Couldn't parse parentProxy.");
  176. releaseAtom(parentProxy);
  177. parentProxy = NULL;
  178. return -1;
  179. }
  180. port = atoi(port_atom->string);
  181. if(port <= 0 || port >= 0x10000) {
  182. releaseAtom(host);
  183. releaseAtom(port_atom);
  184. do_log(L_ERROR, "Couldn't parse parentProxy.");
  185. releaseAtom(parentProxy);
  186. parentProxy = NULL;
  187. return -1;
  188. }
  189. parentHost = host;
  190. parentPort = port;
  191. return 1;
  192. }
  193. void
  194. initServer(void)
  195. {
  196. TimeEventHandlerPtr event;
  197. servers = NULL;
  198. if(pmmFirstSize || pmmSize) {
  199. if(pmmSize == 0) pmmSize = pmmFirstSize;
  200. if(pmmFirstSize == 0) pmmFirstSize = pmmSize;
  201. pmmSize = roundSize(pmmSize);
  202. pmmFirstSize = roundSize(pmmFirstSize);
  203. }
  204. if(serverMaxSlots < 1)
  205. serverMaxSlots = 1;
  206. if(serverSlots < 1)
  207. serverSlots = 1;
  208. if(serverSlots > serverMaxSlots)
  209. serverSlots = serverMaxSlots;
  210. if(serverSlots1 < serverSlots)
  211. serverSlots1 = serverSlots;
  212. if(serverSlots1 > serverMaxSlots)
  213. serverSlots1 = serverMaxSlots;
  214. initParentProxy();
  215. event = scheduleTimeEvent(serverExpireTime / 60 + 60, expireServersHandler,
  216. 0, NULL);
  217. if(event == NULL) {
  218. do_log(L_ERROR, "Couldn't schedule server expiry.\n");
  219. exit(1);
  220. }
  221. }
  222. static HTTPServerPtr
  223. getServer(char *name, int port, int proxy)
  224. {
  225. HTTPServerPtr server;
  226. int i;
  227. server = servers;
  228. while(server) {
  229. if(strcmp(server->name, name) == 0 && server->port == port &&
  230. server->isProxy == proxy) {
  231. if(httpServerIdle(server) &&
  232. server->time + serverExpireTime < current_time.tv_sec) {
  233. discardServer(server);
  234. server = NULL;
  235. break;
  236. } else {
  237. server->time = current_time.tv_sec;
  238. return server;
  239. }
  240. }
  241. server = server->next;
  242. }
  243. server = malloc(sizeof(HTTPServerRec));
  244. if(server == NULL) {
  245. do_log(L_ERROR, "Couldn't allocate server.\n");
  246. return NULL;
  247. }
  248. server->connection = malloc(serverMaxSlots * sizeof(HTTPConnectionPtr));
  249. if(server->connection == NULL) {
  250. do_log(L_ERROR, "Couldn't allocate server.\n");
  251. free(server);
  252. return NULL;
  253. }
  254. server->idleHandler = malloc(serverMaxSlots * sizeof(FdEventHandlerPtr));
  255. if(server->connection == NULL) {
  256. do_log(L_ERROR, "Couldn't allocate server.\n");
  257. free(server->connection);
  258. free(server);
  259. return NULL;
  260. }
  261. server->maxslots = serverMaxSlots;
  262. server->name = strdup(name);
  263. if(server->name == NULL) {
  264. do_log(L_ERROR, "Couldn't allocate server name.\n");
  265. free(server);
  266. return NULL;
  267. }
  268. server->port = port;
  269. server->addrindex = 0;
  270. server->isProxy = proxy;
  271. server->version = HTTP_UNKNOWN;
  272. server->persistent = 0;
  273. server->pipeline = 0;
  274. server->time = current_time.tv_sec;
  275. server->rtt = -1;
  276. server->rate = -1;
  277. server->numslots = MIN(serverSlots, server->maxslots);
  278. for(i = 0; i < server->maxslots; i++) {
  279. server->connection[i] = NULL;
  280. server->idleHandler[i] = NULL;
  281. }
  282. server->request = NULL;
  283. server->request_last = NULL;
  284. server->lies = 0;
  285. server->next = servers;
  286. servers = server;
  287. return server;
  288. }
  289. int
  290. httpServerQueueRequest(HTTPServerPtr server, HTTPRequestPtr request)
  291. {
  292. assert(request->request && request->request->request == request);
  293. assert(request->connection == NULL);
  294. if(server->request) {
  295. server->request_last->next = request;
  296. server->request_last = request;
  297. } else {
  298. server->request_last = request;
  299. server->request = request;
  300. }
  301. return 1;
  302. }
  303. void
  304. httpServerAbort(HTTPConnectionPtr connection, int fail,
  305. int code, AtomPtr message)
  306. {
  307. HTTPRequestPtr request = connection->request;
  308. if(request) {
  309. if(request->request) {
  310. httpClientError(request->request, code, retainAtom(message));
  311. }
  312. if(fail) {
  313. request->object->flags |= OBJECT_FAILED;
  314. if(request->object->flags & OBJECT_INITIAL)
  315. abortObject(request->object, code, retainAtom(message));
  316. notifyObject(request->object);
  317. }
  318. }
  319. releaseAtom(message);
  320. if(!connection->connecting)
  321. httpServerFinish(connection, 1, 0);
  322. }
  323. void
  324. httpServerAbortRequest(HTTPRequestPtr request, int fail,
  325. int code, AtomPtr message)
  326. {
  327. if(request->connection && request == request->connection->request) {
  328. httpServerAbort(request->connection, fail, code, message);
  329. } else {
  330. HTTPRequestPtr requestor = request->request;
  331. if(requestor) {
  332. requestor->request = NULL;
  333. request->request = NULL;
  334. httpClientError(requestor, code, retainAtom(message));
  335. }
  336. if(fail) {
  337. request->object->flags |= OBJECT_FAILED;
  338. if(request->object->flags & OBJECT_INITIAL)
  339. abortObject(request->object, code, retainAtom(message));
  340. notifyObject(request->object);
  341. }
  342. releaseAtom(message);
  343. }
  344. }
  345. void
  346. httpServerClientReset(HTTPRequestPtr request)
  347. {
  348. if(request->connection &&
  349. request->connection->fd >= 0 &&
  350. !request->connection->connecting &&
  351. request->connection->request == request)
  352. pokeFdEvent(request->connection->fd, -ECLIENTRESET, POLLIN | POLLOUT);
  353. }
  354. int
  355. httpMakeServerRequest(char *name, int port, ObjectPtr object,
  356. int method, int from, int to, HTTPRequestPtr requestor)
  357. {
  358. HTTPServerPtr server;
  359. HTTPRequestPtr request;
  360. int rc;
  361. assert(!(object->flags & OBJECT_INPROGRESS));
  362. if(parentHost) {
  363. server = getServer(parentHost->string, parentPort, 1);
  364. } else {
  365. server = getServer(name, port, 0);
  366. }
  367. if(server == NULL) return -1;
  368. object->flags |= OBJECT_INPROGRESS;
  369. object->requestor = requestor;
  370. request = httpMakeRequest();
  371. if(!request) {
  372. do_log(L_ERROR, "Couldn't allocate request.\n");
  373. return -1;
  374. }
  375. /* Because we allocate objects in chunks, we cannot have data that
  376. doesn't start at a chunk boundary. */
  377. if(from % CHUNK_SIZE != 0) {
  378. if(allowUnalignedRangeRequests) {
  379. objectFillFromDisk(object, from / CHUNK_SIZE * CHUNK_SIZE, 1);
  380. if(objectHoleSize(object, from - 1) != 0)
  381. from = from / CHUNK_SIZE * CHUNK_SIZE;
  382. } else {
  383. from = from / CHUNK_SIZE * CHUNK_SIZE;
  384. }
  385. }
  386. request->object = retainObject(object);
  387. request->method = method;
  388. if(method == METHOD_CONDITIONAL_GET) {
  389. if(server->lies > 0)
  390. request->method = METHOD_HEAD;
  391. }
  392. request->flags =
  393. REQUEST_PERSISTENT |
  394. (expectContinue ? (requestor->flags & REQUEST_WAIT_CONTINUE) : 0);
  395. request->from = from;
  396. request->to = to;
  397. request->request = requestor;
  398. requestor->request = request;
  399. request->cache_control = requestor->cache_control;
  400. request->time0 = null_time;
  401. request->time1 = null_time;
  402. rc = httpServerQueueRequest(server, request);
  403. if(rc < 0) {
  404. do_log(L_ERROR, "Couldn't queue request.\n");
  405. request->request = NULL;
  406. requestor->request = NULL;
  407. object->flags &= ~(OBJECT_INPROGRESS | OBJECT_VALIDATING);
  408. releaseNotifyObject(object);
  409. httpDestroyRequest(request);
  410. return 1;
  411. }
  412. if(request->flags & REQUEST_WAIT_CONTINUE) {
  413. if(server->version == HTTP_10) {
  414. httpServerAbortRequest(request, 1,
  415. 417, internAtom("Expectation failed"));
  416. return 1;
  417. }
  418. } else if(expectContinue >= 2 && server->version == HTTP_11) {
  419. if(request->method == METHOD_POST || request->method == METHOD_PUT ||
  420. request->method == METHOD_OPTIONS || request->method == METHOD_DELETE)
  421. request->flags |= REQUEST_WAIT_CONTINUE;
  422. }
  423. again:
  424. rc = httpServerTrigger(server);
  425. if(rc < 0) {
  426. /* We must be very short on memory. If there are any requests
  427. queued, we abort one and try again. If there aren't, we
  428. give up. */
  429. do_log(L_ERROR, "Couldn't trigger server -- out of memory?\n");
  430. if(server->request) {
  431. httpServerAbortRequest(server->request, 1, 503,
  432. internAtom("Couldn't trigger server"));
  433. goto again;
  434. }
  435. }
  436. return 1;
  437. }
  438. int
  439. httpServerConnection(HTTPServerPtr server)
  440. {
  441. HTTPConnectionPtr connection;
  442. int i;
  443. connection = httpMakeConnection();
  444. if(connection == NULL) {
  445. do_log(L_ERROR, "Couldn't allocate server connection.\n");
  446. return -1;
  447. }
  448. connection->server = server;
  449. for(i = 0; i < server->numslots; i++) {
  450. if(!server->connection[i]) {
  451. server->connection[i] = connection;
  452. break;
  453. }
  454. }
  455. assert(i < server->numslots);
  456. connection->request = NULL;
  457. connection->request_last = NULL;
  458. do_log(D_SERVER_CONN, "C... %s:%d.\n",
  459. scrub(connection->server->name), connection->server->port);
  460. httpSetTimeout(connection, serverTimeout);
  461. if(socksParentProxy) {
  462. connection->connecting = CONNECTING_SOCKS;
  463. do_socks_connect(server->name, connection->server->port,
  464. httpServerSocksHandler, connection);
  465. } else {
  466. connection->connecting = CONNECTING_DNS;
  467. do_gethostbyname(server->name, 0,
  468. httpServerConnectionDnsHandler,
  469. connection);
  470. }
  471. return 1;
  472. }
  473. int
  474. httpServerConnectionDnsHandler(int status, GethostbynameRequestPtr request)
  475. {
  476. HTTPConnectionPtr connection = request->data;
  477. httpSetTimeout(connection, -1);
  478. if(status <= 0) {
  479. AtomPtr message;
  480. message = internAtomF("Host %s lookup failed: %s",
  481. request->name ?
  482. request->name->string : "(unknown)",
  483. request->error_message ?
  484. request->error_message->string :
  485. pstrerror(-status));
  486. do_log(L_ERROR, "Host %s lookup failed: %s (%d).\n",
  487. request->name ?
  488. scrub(request->name->string) : "(unknown)",
  489. request->error_message ?
  490. request->error_message->string :
  491. pstrerror(-status), -status);
  492. connection->connecting = 0;
  493. if(connection->server->request)
  494. httpServerAbortRequest(connection->server->request, 1, 504,
  495. retainAtom(message));
  496. httpServerAbort(connection, 1, 502, message);
  497. return 1;
  498. }
  499. if(request->addr->string[0] == DNS_CNAME) {
  500. if(request->count > 10) {
  501. AtomPtr message = internAtom("DNS CNAME loop");
  502. do_log(L_ERROR, "DNS CNAME loop.\n");
  503. connection->connecting = 0;
  504. if(connection->server->request)
  505. httpServerAbortRequest(connection->server->request, 1, 504,
  506. retainAtom(message));
  507. httpServerAbort(connection, 1, 504, message);
  508. return 1;
  509. }
  510. httpSetTimeout(connection, serverTimeout);
  511. do_gethostbyname(request->addr->string + 1, request->count + 1,
  512. httpServerConnectionDnsHandler,
  513. connection);
  514. return 1;
  515. }
  516. connection->connecting = CONNECTING_CONNECT;
  517. httpSetTimeout(connection, serverTimeout);
  518. do_connect(retainAtom(request->addr), connection->server->addrindex,
  519. connection->server->port,
  520. httpServerConnectionHandler, connection);
  521. return 1;
  522. }
  523. int
  524. httpServerConnectionHandler(int status,
  525. FdEventHandlerPtr event,
  526. ConnectRequestPtr request)
  527. {
  528. HTTPConnectionPtr connection = request->data;
  529. assert(connection->fd < 0);
  530. if(request->fd >= 0) {
  531. int rc;
  532. connection->fd = request->fd;
  533. connection->server->addrindex = request->index;
  534. rc = setNodelay(connection->fd, 1);
  535. if(rc < 0)
  536. do_log_error(L_WARN, errno, "Couldn't disable Nagle's algorithm");
  537. }
  538. return httpServerConnectionHandlerCommon(status, connection);
  539. }
  540. int
  541. httpServerSocksHandler(int status, SocksRequestPtr request)
  542. {
  543. HTTPConnectionPtr connection = request->data;
  544. assert(connection->fd < 0);
  545. if(request->fd >= 0) {
  546. connection->fd = request->fd;
  547. connection->server->addrindex = 0;
  548. }
  549. return httpServerConnectionHandlerCommon(status, connection);
  550. }
  551. int
  552. httpServerConnectionHandlerCommon(int status, HTTPConnectionPtr connection)
  553. {
  554. httpSetTimeout(connection, -1);
  555. if(status < 0) {
  556. AtomPtr message =
  557. internAtomError(-status, "Connect to %s:%d failed",
  558. connection->server->name,
  559. connection->server->port);
  560. if(status != -ECLIENTRESET)
  561. do_log_error(L_ERROR, -status, "Connect to %s:%d failed",
  562. scrub(connection->server->name),
  563. connection->server->port);
  564. connection->connecting = 0;
  565. if(connection->server->request)
  566. httpServerAbortRequest(connection->server->request,
  567. status != -ECLIENTRESET, 504,
  568. retainAtom(message));
  569. httpServerAbort(connection, status != -ECLIENTRESET, 504, message);
  570. return 1;
  571. }
  572. do_log(D_SERVER_CONN, "C %s:%d.\n",
  573. scrub(connection->server->name), connection->server->port);
  574. connection->connecting = 0;
  575. /* serverTrigger will take care of inserting any timeouts */
  576. httpServerTrigger(connection->server);
  577. return 1;
  578. }
  579. int
  580. httpServerIdleHandler(int a, FdEventHandlerPtr event)
  581. {
  582. HTTPConnectionPtr connection = *(HTTPConnectionPtr*)event->data;
  583. HTTPServerPtr server = connection->server;
  584. int i;
  585. assert(!connection->request);
  586. do_log(D_SERVER_CONN, "Idle connection to %s:%d died.\n",
  587. scrub(connection->server->name), connection->server->port);
  588. for(i = 0; i < server->maxslots; i++) {
  589. if(connection == server->connection[i]) {
  590. server->idleHandler[i] = NULL;
  591. break;
  592. }
  593. }
  594. assert(i < server->maxslots);
  595. httpServerAbort(connection, 1, 504, internAtom("Timeout"));
  596. return 1;
  597. }
  598. /* Discard aborted requests at the head of the queue. */
  599. static void
  600. httpServerDiscardRequests(HTTPServerPtr server)
  601. {
  602. HTTPRequestPtr request;
  603. while(server->request && !server->request->request) {
  604. request = server->request;
  605. server->request = request->next;
  606. request->next = NULL;
  607. if(server->request == NULL)
  608. server->request_last = NULL;
  609. request->object->flags &= ~(OBJECT_INPROGRESS | OBJECT_VALIDATING);
  610. releaseNotifyObject(request->object);
  611. request->object = NULL;
  612. httpDestroyRequest(request);
  613. }
  614. }
  615. static int
  616. pipelineIsSmall(HTTPConnectionPtr connection)
  617. {
  618. HTTPRequestPtr request = connection->request;
  619. if(pipelineAdditionalRequests <= 0)
  620. return 0;
  621. else if(pipelineAdditionalRequests >= 2)
  622. return 1;
  623. if(!request)
  624. return 1;
  625. if(request->next || !(request->flags & REQUEST_PERSISTENT))
  626. return 0;
  627. if(request->method == METHOD_HEAD ||
  628. request->method == METHOD_CONDITIONAL_GET)
  629. return 1;
  630. if(request->to >= 0 && connection->server->rate > 0 &&
  631. request->to - request->from < connection->server->rate *
  632. smallRequestTime)
  633. return 1;
  634. return 0;
  635. }
  636. static int
  637. numRequests(HTTPServerPtr server)
  638. {
  639. int n = 0;
  640. HTTPRequestPtr request = server->request;
  641. while(request) {
  642. n++;
  643. request = request->next;
  644. }
  645. return n;
  646. }
  647. HTTPConnectionPtr
  648. httpServerGetConnection(HTTPServerPtr server, int *idle_return)
  649. {
  650. int i, j;
  651. int connecting = 0, empty = 0, idle = 0;
  652. j = -1;
  653. /* Try to find an idle connection */
  654. for(i = 0; i < server->numslots; i++) {
  655. if(server->connection[i]) {
  656. if(!server->connection[i]->connecting) {
  657. if(!server->connection[i]->request) {
  658. if(server->idleHandler[i])
  659. unregisterFdEvent(server->idleHandler[i]);
  660. server->idleHandler[i] = NULL;
  661. if(j < 0) j = i;
  662. idle++;
  663. }
  664. } else
  665. connecting++;
  666. } else
  667. empty++;
  668. }
  669. if(j >= 0) {
  670. *idle_return = idle;
  671. return server->connection[j];
  672. }
  673. /* If there's an empty slot, schedule connection creation */
  674. if(empty) {
  675. /* Don't open a connection if there are already enough in
  676. progress, except if the server doesn't do persistent
  677. connections and there's only one in progress. */
  678. if((connecting == 0 || (server->persistent <= 0 && connecting <= 1)) ||
  679. connecting < numRequests(server)) {
  680. httpServerConnection(server);
  681. }
  682. }
  683. /* Find a connection that can accept additional requests */
  684. if(server->version == HTTP_11 && server->pipeline >= 4) {
  685. for(i = 0; i < serverSlots; i++) {
  686. if(server->connection[i] && !server->connection[i]->connecting &&
  687. pipelineIsSmall(server->connection[i])) {
  688. if(server->idleHandler[i])
  689. unregisterFdEvent(server->idleHandler[i]);
  690. server->idleHandler[i] = NULL;
  691. *idle_return = 0;
  692. return server->connection[i];
  693. }
  694. }
  695. }
  696. *idle_return = idle;
  697. return NULL;
  698. }
  699. int
  700. httpServerTrigger(HTTPServerPtr server)
  701. {
  702. HTTPConnectionPtr connection;
  703. HTTPRequestPtr request;
  704. int idle, n, i, rc, numidle;
  705. while(server->request) {
  706. httpServerDiscardRequests(server);
  707. if(!server->request)
  708. break;
  709. if(REQUEST_SIDE(server->request)) {
  710. rc = httpServerSideRequest(server);
  711. /* If rc is 0, httpServerSideRequest didn't dequeue this
  712. request. Go through the scheduling loop again, come
  713. back later. */
  714. if(rc <= 0) break;
  715. continue;
  716. }
  717. connection = httpServerGetConnection(server, &numidle);
  718. if(!connection) break;
  719. /* If server->pipeline <= 0, we don't do pipelining. If
  720. server->pipeline is 1, then we are ready to start probing
  721. for pipelining on the server; we then send exactly two
  722. requests in what is hopefully a single packet to check
  723. whether the server has the nasty habit of discarding its
  724. input buffers after each request.
  725. If server->pipeline is 2 or 3, the pipelining probe is in
  726. progress on this server, and we don't pipeline anything
  727. until it succeeds. When server->pipeline >= 4, pipelining
  728. is believed to work on this server. */
  729. if(server->version != HTTP_11 || server->pipeline <= 0 ||
  730. server->pipeline == 2 || server->pipeline == 3) {
  731. if(connection->pipelined == 0)
  732. n = 1;
  733. else
  734. n = 0;
  735. } else if(server->pipeline == 1) {
  736. if(connection->pipelined == 0)
  737. n = MIN(2, maxPipelineTrain);
  738. else
  739. n = 0;
  740. } else {
  741. n = maxPipelineTrain;
  742. }
  743. /* Don't pipeline if there are more idle connections */
  744. if(numidle >= 2)
  745. n = MIN(n, 1);
  746. idle = !connection->pipelined;
  747. i = 0;
  748. while(server->request && connection->pipelined < n) {
  749. httpServerDiscardRequests(server);
  750. if(!server->request) break;
  751. request = server->request;
  752. assert(request->request->request == request);
  753. rc = httpWriteRequest(connection, request, -1);
  754. if(rc < 0) {
  755. if(i == 0)
  756. httpServerAbortRequest(request, rc != -ECLIENTRESET, 502,
  757. internAtom("Couldn't "
  758. "write request"));
  759. break;
  760. }
  761. do_log(D_SERVER_CONN, "W: ");
  762. do_log_n(D_SERVER_CONN,
  763. request->object->key, request->object->key_size);
  764. do_log(D_SERVER_CONN, " (%d)\n", request->method);
  765. if(connection->pipelined > 0)
  766. request->flags |= REQUEST_PIPELINED;
  767. request->time0 = current_time;
  768. i++;
  769. server->request = request->next;
  770. request->next = NULL;
  771. if(server->request == NULL)
  772. server->request_last = NULL;
  773. httpQueueRequest(connection, request);
  774. connection->pipelined++;
  775. }
  776. if(server->persistent > 0 && server->pipeline == 1 && i >= 2)
  777. server->pipeline = 2;
  778. if(i > 0) httpServerSendRequest(connection);
  779. if(idle && connection->pipelined > 0)
  780. httpServerReply(connection, 0);
  781. if(i == 0) break;
  782. }
  783. for(i = 0; i < server->maxslots; i++) {
  784. if(server->connection[i] &&
  785. !server->connection[i]->connecting &&
  786. !server->connection[i]->request) {
  787. /* Artificially age any fresh connections that aren't used
  788. straight away; this is necessary for the logic for POST and
  789. the logic that determines whether a given request should be
  790. restarted. */
  791. if(server->connection[i]->serviced == 0)
  792. server->connection[i]->serviced = 1;
  793. if(!server->idleHandler[i])
  794. server->idleHandler[i] =
  795. registerFdEvent(server->connection[i]->fd, POLLIN,
  796. httpServerIdleHandler,
  797. sizeof(HTTPConnectionPtr),
  798. &server->connection[i]);
  799. if(!server->idleHandler[i]) {
  800. do_log(L_ERROR, "Couldn't register idle handler.\n");
  801. httpServerFinish(server->connection[i], 1, 0);
  802. }
  803. httpSetTimeout(server->connection[i], serverIdleTimeout);
  804. }
  805. }
  806. return 1;
  807. }
  808. int
  809. httpServerSideRequest(HTTPServerPtr server)
  810. {
  811. HTTPRequestPtr request = server->request;
  812. HTTPConnectionPtr connection;
  813. HTTPRequestPtr requestor = request->request;
  814. HTTPConnectionPtr client = requestor->connection;
  815. int rc, i, freeslots, idle, connecting;
  816. assert(REQUEST_SIDE(request));
  817. connection = NULL;
  818. freeslots = 0;
  819. idle = -1;
  820. connecting = 0;
  821. /* Find a fresh connection */
  822. for(i = 0; i < server->numslots; i++) {
  823. if(!server->connection[i])
  824. freeslots++;
  825. else if(!server->connection[i]->connecting) {
  826. if(!server->connection[i]->request) {
  827. if(server->connection[i]->serviced == 0) {
  828. if(server->idleHandler[i])
  829. unregisterFdEvent(server->idleHandler[i]);
  830. server->idleHandler[i] = NULL;
  831. connection = server->connection[i];
  832. break;
  833. } else {
  834. idle = i;
  835. }
  836. }
  837. } else {
  838. connecting++;
  839. }
  840. }
  841. if(!connection) {
  842. /* Make sure that a fresh connection will be established at some
  843. point, then wait until httpServerTrigger calls us again. */
  844. if(freeslots) {
  845. httpServerConnection(server);
  846. } else {
  847. if(idle >= 0) {
  848. /* Shutdown a random idle connection */
  849. pokeFdEvent(server->connection[idle]->fd,
  850. -EDOSHUTDOWN, POLLIN | POLLOUT);
  851. }
  852. }
  853. return 0;
  854. }
  855. rc = httpWriteRequest(connection, request, client->bodylen);
  856. if(rc < 0) {
  857. do_log(L_ERROR, "Couldn't write POST or PUT request.\n");
  858. httpServerAbortRequest(request, rc != -ECLIENTRESET, 502,
  859. internAtom("Couldn't write request"));
  860. return 0;
  861. }
  862. server->request = request->next;
  863. request->next = NULL;
  864. if(server->request == NULL)
  865. server->request_last = NULL;
  866. httpQueueRequest(connection, request);
  867. connection->pipelined = 1;
  868. request->time0 = current_time;
  869. connection->reqoffset = 0;
  870. connection->bodylen = client->bodylen;
  871. httpServerDoSide(connection);
  872. return 1;
  873. }
  874. int
  875. httpServerDoSide(HTTPConnectionPtr connection)
  876. {
  877. HTTPRequestPtr request = connection->request;
  878. HTTPRequestPtr requestor = request->request;
  879. HTTPConnectionPtr client = requestor->connection;
  880. int len = MIN(client->reqlen - client->reqbegin,
  881. connection->bodylen - connection->reqoffset);
  882. int doflush =
  883. len > 0 &&
  884. (len >= maxSideBuffering ||
  885. client->reqbegin > 0 ||
  886. (connection->reqoffset + client->reqlen - client->reqbegin) >=
  887. connection->bodylen);
  888. int done = connection->reqoffset >= connection->bodylen;
  889. assert(connection->bodylen >= 0);
  890. httpSetTimeout(connection, 60);
  891. if(connection->reqlen > 0) {
  892. /* Send the headers, but don't send any part of the body if
  893. we're in wait_continue. */
  894. do_stream_2(IO_WRITE,
  895. connection->fd, 0,
  896. connection->reqbuf, connection->reqlen,
  897. client->reqbuf + client->reqbegin,
  898. (request->flags & REQUEST_WAIT_CONTINUE) ? 0 : len,
  899. httpServerSideHandler2, connection);
  900. httpServerReply(connection, 0);
  901. } else if(request->object->flags & OBJECT_ABORTED) {
  902. if(connection->reqbuf)
  903. dispose_chunk(connection->reqbuf);
  904. connection->reqbuf = NULL;
  905. connection->reqlen = 0;
  906. pokeFdEvent(connection->fd, -ESHUTDOWN, POLLIN);
  907. if(client->flags & CONN_READER) {
  908. client->flags |= CONN_SIDE_READER;
  909. do_stream(IO_READ | IO_IMMEDIATE | IO_NOTNOW,
  910. client->fd, 0, NULL, 0,
  911. httpClientSideHandler, client);
  912. }
  913. } else if(!(request->flags & REQUEST_WAIT_CONTINUE) && doflush) {
  914. /* Make sure there's a reqbuf, as httpServerFinish uses
  915. it to determine if there's a writer. */
  916. if(connection->reqbuf == NULL)
  917. connection->reqbuf = get_chunk();
  918. assert(connection->reqbuf != NULL);
  919. do_stream(IO_WRITE,
  920. connection->fd, 0,
  921. client->reqbuf + client->reqbegin, len,
  922. httpServerSideHandler, connection);
  923. } else {
  924. if(connection->reqbuf) {
  925. httpConnectionDestroyReqbuf(connection);
  926. connection->reqlen = 0;
  927. }
  928. if(request->flags & REQUEST_WAIT_CONTINUE) {
  929. ConditionHandlerPtr chandler;
  930. do_log(D_SERVER_CONN, "W... %s:%d.\n",
  931. scrub(connection->server->name), connection->server->port);
  932. chandler =
  933. conditionWait(&request->object->condition,
  934. httpServerContinueConditionHandler,
  935. sizeof(connection), &connection);
  936. if(chandler)
  937. return 1;
  938. else
  939. do_log(L_ERROR, "Couldn't register condition handler.\n");
  940. /* Fall through -- the client side will clean up. */
  941. }
  942. client->flags |= CONN_SIDE_READER;
  943. do_stream(IO_READ | (done ? IO_IMMEDIATE : 0 ) | IO_NOTNOW,
  944. client->fd, client->reqlen,
  945. client->reqbuf, CHUNK_SIZE,
  946. httpClientSideHandler, client);
  947. }
  948. return 1;
  949. }
  950. static int
  951. httpClientDelayedDoSideHandler(TimeEventHandlerPtr event)
  952. {
  953. HTTPConnectionPtr connection = *(HTTPConnectionPtr*)event->data;
  954. httpServerDoSide(connection);
  955. return 1;
  956. }
  957. static int
  958. httpServerDelayedDoSide(HTTPConnectionPtr connection)
  959. {
  960. TimeEventHandlerPtr handler;
  961. handler = scheduleTimeEvent(0, httpClientDelayedDoSideHandler,
  962. sizeof(connection), &connection);
  963. if(!handler) {
  964. do_log(L_ERROR, "Couldn't schedule DoSide -- freeing memory.\n");
  965. free_chunk_arenas();
  966. handler = scheduleTimeEvent(0, httpClientDelayedDoSideHandler,
  967. sizeof(connection), &connection);
  968. if(!handler)
  969. do_log(L_ERROR, "Couldn't schedule DoSide.\n");
  970. /* Somebody will hopefully end up timing out. */
  971. return 1;
  972. }
  973. return 1;
  974. }
  975. static int
  976. httpServerSideHandlerCommon(int kind, int status,
  977. FdEventHandlerPtr event,
  978. StreamRequestPtr srequest)
  979. {
  980. HTTPConnectionPtr connection = srequest->data;
  981. HTTPRequestPtr request = connection->request;
  982. HTTPRequestPtr requestor = request->request;
  983. HTTPConnectionPtr client = requestor->connection;
  984. int bodylen;
  985. assert(request->object->flags & OBJECT_INPROGRESS);
  986. if(status) {
  987. do_log_error(L_ERROR, -status, "Couldn't write to server");
  988. httpConnectionDestroyReqbuf(connection);
  989. if(status != -ECLIENTRESET)
  990. shutdown(connection->fd, 2);
  991. abortObject(request->object, 502,
  992. internAtom("Couldn't write to server"));
  993. /* Let the read side handle the error */
  994. httpServerDoSide(connection);
  995. return 1;
  996. }
  997. assert(srequest->offset > 0);
  998. if(kind == 2) {
  999. if(srequest->offset < connection->reqlen)
  1000. return 0;
  1001. bodylen = srequest->offset - connection->reqlen;
  1002. connection->reqlen = 0;
  1003. httpConnectionDestroyReqbuf(connection);
  1004. } else {
  1005. bodylen = srequest->offset;
  1006. }
  1007. assert(client->reqbegin + bodylen <= client->reqlen);
  1008. if(client->reqlen > client->reqbegin + bodylen)
  1009. memmove(client->reqbuf, client->reqbuf + client->reqbegin + bodylen,
  1010. client->reqlen - client->reqbegin - bodylen);
  1011. client->reqlen -= bodylen + client->reqbegin;
  1012. client->reqbegin = 0;
  1013. connection->reqoffset += bodylen;
  1014. httpServerDoSide(connection);
  1015. return 1;
  1016. }
  1017. int
  1018. httpServerSideHandler(int status,
  1019. FdEventHandlerPtr event,
  1020. StreamRequestPtr srequest)
  1021. {
  1022. return httpServerSideHandlerCommon(1, status, event, srequest);
  1023. }
  1024. int
  1025. httpServerSideHandler2(int status,
  1026. FdEventHandlerPtr event,
  1027. StreamRequestPtr srequest)
  1028. {
  1029. return httpServerSideHandlerCommon(2, status, event, srequest);
  1030. }
  1031. static int
  1032. httpServerContinueConditionHandler(int status, ConditionHandlerPtr chandler)
  1033. {
  1034. HTTPConnectionPtr connection = *(HTTPConnectionPtr*)chandler->data;
  1035. if(connection->request->flags & REQUEST_WAIT_CONTINUE)
  1036. return 0;
  1037. httpServerDelayedDoSide(connection);
  1038. return 1;
  1039. }
  1040. /* s is 0 to keep the connection alive, 1 to shutdown the connection */
  1041. void
  1042. httpServerFinish(HTTPConnectionPtr connection, int s, int offset)
  1043. {
  1044. HTTPServerPtr server = connection->server;
  1045. HTTPRequestPtr request = connection->request;
  1046. int i;
  1047. if(request) {
  1048. assert(connection->pipelined >= 1);
  1049. assert((connection->pipelined > 1) == (request->next != NULL));
  1050. } else {
  1051. assert(connection->pipelined == 0);
  1052. }
  1053. if(!s && (!connection->request ||
  1054. !(connection->request->flags & REQUEST_PERSISTENT)))
  1055. s = 1;
  1056. if(connection->serviced >= maxConnectionRequests ||
  1057. connection->time < current_time.tv_sec - maxConnectionAge)
  1058. s = 1;
  1059. if(connection->reqbuf) {
  1060. /* As most normal requests go out in a single packet, this is
  1061. extremely unlikely to happen. As for POST/PUT requests,
  1062. they are not pipelined, so this can only happen if the
  1063. server sent an error reply early. */
  1064. assert(connection->fd >= 0);
  1065. shutdown(connection->fd, 1);
  1066. pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLOUT);
  1067. httpServerDelayedFinish(connection);
  1068. goto done;
  1069. }
  1070. if(request) {
  1071. /* Update statistics about the server */
  1072. int size = -1, d = -1, rtt = -1, rate = -1;
  1073. if(connection->offset > 0 && request->from >= 0)
  1074. size = connection->offset - request->from;
  1075. if(request->time1.tv_sec != null_time.tv_sec) {
  1076. d = timeval_minus_usec(&current_time, &request->time1);
  1077. if(!(request->flags & REQUEST_PIPELINED) &&
  1078. request->time0.tv_sec != null_time.tv_sec)
  1079. rtt = timeval_minus_usec(&request->time1, &request->time0);
  1080. if(size >= 8192 && d > 50000)
  1081. rate = ((double)size / (double)d) * 1000000.0 + 0.5;
  1082. }
  1083. request->time0 = null_time;
  1084. request->time1 = null_time;
  1085. if(rtt >= 0) {
  1086. if(server->rtt >= 0)
  1087. server->rtt = (3 * server->rtt + rtt + 2) / 4;
  1088. else
  1089. server->rtt = rtt;
  1090. }
  1091. if(rate >= 0) {
  1092. if(server->rate >= 0)
  1093. server->rate = (3 * server->rate + rate + 2) / 4;
  1094. else
  1095. server->rate = rate;
  1096. }
  1097. httpDequeueRequest(connection);
  1098. connection->pipelined--;
  1099. request->object->flags &= ~(OBJECT_INPROGRESS | OBJECT_VALIDATING);
  1100. if(request->request) {
  1101. request->request->request = NULL;
  1102. request->request = NULL;
  1103. }
  1104. releaseNotifyObject(request->object);
  1105. request->object = NULL;
  1106. httpDestroyRequest(request);
  1107. }
  1108. do_log(D_SERVER_CONN, "Done with server %s:%d connection (%d)\n",
  1109. scrub(connection->server->name), connection->server->port, s);
  1110. assert(offset <= connection->len);
  1111. if(!s) {
  1112. if(offset < connection->len) {
  1113. assert(connection->buf != NULL);
  1114. if(!connection->pipelined) {
  1115. do_log(L_WARN,
  1116. "Closing connection to %s:%d: "
  1117. "%d stray bytes of data.\n",
  1118. scrub(server->name), server->port,
  1119. connection->len - offset);
  1120. s = 1;
  1121. } else {
  1122. memmove(connection->buf, connection->buf + offset,
  1123. connection->len - offset);
  1124. connection->len = connection->len - offset;
  1125. if((connection->flags & CONN_BIGBUF) &&
  1126. connection->len <= CHUNK_SIZE)
  1127. httpConnectionUnbigify(connection);
  1128. }
  1129. } else {
  1130. connection->len = 0;
  1131. }
  1132. }
  1133. connection->server->time = current_time.tv_sec;
  1134. connection->serviced++;
  1135. if(s) {
  1136. if(connection->timeout)
  1137. cancelTimeEvent(connection->timeout);
  1138. connection->timeout = NULL;
  1139. httpConnectionDestroyBuf(connection);
  1140. if(connection->fd >= 0)
  1141. CLOSE(connection->fd);
  1142. connection->fd = -1;
  1143. server->persistent -= 1;
  1144. if(server->persistent < -5)
  1145. server->numslots = MIN(server->maxslots, serverMaxSlots);
  1146. if(connection->request) {
  1147. HTTPRequestPtr req;
  1148. do_log(D_SERVER_CONN, "Restarting pipeline to %s:%d.\n",
  1149. scrub(server->name), server->port);
  1150. if(server->pipeline == 2)
  1151. server->pipeline -= 20;
  1152. else
  1153. server->pipeline -= 5;
  1154. req = connection->request;
  1155. while(req) {
  1156. req->connection = NULL;
  1157. req = req->next;
  1158. }
  1159. if(server->request)
  1160. connection->request_last->next = server->request;
  1161. else
  1162. server->request_last = connection->request_last;
  1163. server->request = connection->request;
  1164. connection->request = NULL;
  1165. connection->request_last = NULL;
  1166. }
  1167. /* Make sure we don't get confused into thinking a probe
  1168. is in progress. */
  1169. if(server->pipeline == 2 || server->pipeline == 3)
  1170. server->pipeline = 1;
  1171. for(i = 0; i < server->maxslots; i++)
  1172. if(connection == server->connection[i])
  1173. break;
  1174. assert(i < server->maxslots);
  1175. if(server->idleHandler[i])
  1176. unregisterFdEvent(server->idleHandler[i]);
  1177. server->idleHandler[i] = NULL;
  1178. server->connection[i] = NULL;
  1179. free(connection);
  1180. } else {
  1181. server->persistent += 1;
  1182. if(server->persistent > 0)
  1183. server->numslots = MIN(server->maxslots,
  1184. server->version == HTTP_10 ?
  1185. serverSlots1 : serverSlots);
  1186. httpSetTimeout(connection, serverTimeout);
  1187. /* See httpServerTrigger */
  1188. if(connection->pipelined ||
  1189. (server->version == HTTP_11 && server->pipeline <= 0) ||
  1190. (server->pipeline == 3)) {
  1191. server->pipeline++;
  1192. }
  1193. if(connection->pipelined) {
  1194. httpServerReply(connection, 1);
  1195. } else {
  1196. httpConnectionDestroyBuf(connection);
  1197. }
  1198. }
  1199. done:
  1200. httpServerTrigger(server);
  1201. }
  1202. static int
  1203. httpServerDelayedFinishHandler(TimeEventHandlerPtr event)
  1204. {
  1205. HTTPConnectionPtr connection = *(HTTPConnectionPtr*)event->data;
  1206. httpServerFinish(connection, 1, 0);
  1207. return 1;
  1208. }
  1209. static void
  1210. httpServerDelayedFinish(HTTPConnectionPtr connection)
  1211. {
  1212. TimeEventHandlerPtr handler;
  1213. handler = scheduleTimeEvent(1, httpServerDelayedFinishHandler,
  1214. sizeof(connection), &connection);
  1215. if(!handler) {
  1216. do_log(L_ERROR,
  1217. "Couldn't schedule delayed finish -- freeing memory.");
  1218. free_chunk_arenas();
  1219. handler = scheduleTimeEvent(1, httpServerDelayedFinishHandler,
  1220. sizeof(connection), &connection);
  1221. if(!handler) {
  1222. do_log(L_ERROR,
  1223. "Couldn't schedule delayed finish -- aborting.\n");
  1224. polipoExit();
  1225. }
  1226. }
  1227. }
  1228. void
  1229. httpServerReply(HTTPConnectionPtr connection, int immediate)
  1230. {
  1231. assert(connection->pipelined > 0);
  1232. if(connection->request->request == NULL) {
  1233. do_log(L_WARN, "Aborting pipeline on %s:%d.\n",
  1234. scrub(connection->server->name), connection->server->port);
  1235. httpServerFinish(connection, 1, 0);
  1236. return;
  1237. }
  1238. do_log(D_SERVER_CONN, "R: %s (%d)\n",
  1239. scrub(connection->request->object->key),
  1240. connection->request->method);
  1241. if(connection->len == 0)
  1242. httpConnectionDestroyBuf(connection);
  1243. httpSetTimeout(connection, serverTimeout);
  1244. do_stream_buf(IO_READ | (immediate ? IO_IMMEDIATE : 0) | IO_NOTNOW,
  1245. connection->fd, connection->len,
  1246. &connection->buf, CHUNK_SIZE,
  1247. httpServerReplyHandler, connection);
  1248. }
  1249. int
  1250. httpConnectionPipelined(HTTPConnectionPtr connection)
  1251. {
  1252. HTTPRequestPtr request = connection->request;
  1253. int i = 0;
  1254. while(request) {
  1255. i++;
  1256. request = request->next;
  1257. }
  1258. return i;
  1259. }
  1260. void
  1261. httpServerUnpipeline(HTTPRequestPtr request)
  1262. {
  1263. HTTPConnectionPtr connection = request->connection;
  1264. HTTPServerPtr server = connection->server;
  1265. request->flags &= ~REQUEST_PERSISTENT;
  1266. if(request->next) {
  1267. HTTPRequestPtr req;
  1268. do_log(L_WARN,
  1269. "Restarting pipeline to %s:%d.\n",
  1270. scrub(connection->server->name), connection->server->port);
  1271. req = request->next;
  1272. while(req) {
  1273. req->connection = NULL;
  1274. req = req->next;
  1275. }
  1276. if(server->request)
  1277. connection->request_last->next = server->request;
  1278. else
  1279. server->request_last = connection->request_last;
  1280. server->request = request->next;
  1281. request->next = NULL;
  1282. connection->request_last = request;
  1283. }
  1284. connection->pipelined = httpConnectionPipelined(connection);
  1285. }
  1286. void
  1287. httpServerRestart(HTTPConnectionPtr connection)
  1288. {
  1289. HTTPServerPtr server = connection->server;
  1290. HTTPRequestPtr request = connection->request;
  1291. if(request) {
  1292. HTTPRequestPtr req;
  1293. if(request->next)
  1294. do_log(L_WARN,
  1295. "Restarting pipeline to %s:%d.\n",
  1296. scrub(connection->server->name), connection->server->port);
  1297. req = request;
  1298. while(req) {
  1299. req->connection = NULL;
  1300. req = req->next;
  1301. }
  1302. if(server->request)
  1303. connection->request_last->next = server->request;
  1304. else
  1305. server->request_last = connection->request_last;
  1306. server->request = request;
  1307. connection->request = NULL;
  1308. connection->request_last = NULL;
  1309. }
  1310. connection->pipelined = 0;
  1311. httpServerFinish(connection, 1, 0);
  1312. }
  1313. int
  1314. httpServerRequest(ObjectPtr object, int method, int from, int to,
  1315. HTTPRequestPtr requestor, void *closure)
  1316. {
  1317. int rc;
  1318. char name[132];
  1319. int port;
  1320. int x, y, z;
  1321. assert(from >= 0 && (to < 0 || to > from));
  1322. assert(closure == NULL);
  1323. assert(!(object->flags & OBJECT_LOCAL));
  1324. assert(object->type == OBJECT_HTTP);
  1325. if(object->flags & OBJECT_INPROGRESS)
  1326. return 1;
  1327. if(requestor->flags & REQUEST_REQUESTED)
  1328. return 0;
  1329. assert(requestor->request == NULL);
  1330. if(proxyOffline)
  1331. return -1;
  1332. rc = parseUrl(object->key, object->key_size, &x, &y, &port, &z);
  1333. if(rc < 0 || x < 0 || y < 0 || y - x > 131) {
  1334. do_log(L_ERROR, "Couldn't parse URL %s\n", scrub(object->key));
  1335. abortObject(object, 400, internAtom("Couldn't parse URL"));
  1336. notifyObject(object);
  1337. return 1;
  1338. }
  1339. if(!intListMember(port, allowedPorts)) {
  1340. do_log(L_ERROR, "Attempted connection to port %d.\n", port);
  1341. abortObject(object, 403, internAtom("Forbidden port"));
  1342. notifyObject(object);
  1343. return 1;
  1344. }
  1345. memcpy(name, ((char*)object->key) + x, y - x);
  1346. name[y - x] = '\0';
  1347. requestor->flags |= REQUEST_REQUESTED;
  1348. rc = httpMakeServerRequest(name, port, object, method, from, to,
  1349. requestor);
  1350. if(rc < 0) {
  1351. abortObject(object,
  1352. 503, internAtom("Couldn't schedule server request"));
  1353. notifyObject(object);
  1354. return 1;
  1355. }
  1356. return 1;
  1357. }
  1358. int
  1359. httpWriteRequest(HTTPConnectionPtr connection, HTTPRequestPtr request,
  1360. int bodylen)
  1361. {
  1362. ObjectPtr object = request->object;
  1363. int from = request->from, to = request->to, method = request->method;
  1364. char *url = object->key, *m;
  1365. int url_size = object->key_size;
  1366. int x, y, port, z, location_size;
  1367. char *location;
  1368. int l, n, rc, bufsize;
  1369. assert(method != METHOD_NONE);
  1370. if(request->method == METHOD_GET ||
  1371. request->method == METHOD_CONDITIONAL_GET) {
  1372. if(to >= 0) {
  1373. assert(to >= from);
  1374. if(to == from) {
  1375. do_log(L_ERROR, "Requesting empty segment?\n");
  1376. return -1;
  1377. }
  1378. }
  1379. if(object->flags & OBJECT_DYNAMIC) {
  1380. from = 0;
  1381. to = -1;
  1382. } else {
  1383. objectFillFromDisk(object, from / CHUNK_SIZE * CHUNK_SIZE, 1);
  1384. l = objectHoleSize(request->object, from);
  1385. if(l > 0) {
  1386. if(to <= 0 || to > from + l)
  1387. to = from + l;
  1388. }
  1389. if(pmmSize && connection->server->pipeline >= 4) {
  1390. if(from == 0)
  1391. to = to < 0 ? pmmFirstSize : MIN(to, pmmFirstSize);
  1392. else
  1393. to = to < 0 ? from + pmmSize : MIN(to, from + pmmSize);
  1394. }
  1395. if(from % CHUNK_SIZE != 0)
  1396. if(objectHoleSize(object, from - 1) != 0)
  1397. from = from / CHUNK_SIZE * CHUNK_SIZE;
  1398. }
  1399. }
  1400. rc = parseUrl(url, url_size, &x, &y, &port, &z);
  1401. if(rc < 0 || x < 0 || y < 0) {
  1402. return -1;
  1403. }
  1404. if(connection->reqbuf == NULL) {
  1405. connection->reqbuf = get_chunk();
  1406. if(connection->reqbuf == NULL)
  1407. return -1;
  1408. connection->reqlen = 0;
  1409. }
  1410. if(method == METHOD_CONDITIONAL_GET &&
  1411. object->last_modified < 0 && object->etag == NULL)
  1412. method = request->method = METHOD_GET;
  1413. again:
  1414. bufsize =
  1415. (connection->flags & CONN_BIGREQBUF) ? bigBufferSize : CHUNK_SIZE;
  1416. n = connection->reqlen;
  1417. switch(method) {
  1418. case METHOD_GET:
  1419. case METHOD_CONDITIONAL_GET: m = "GET"; break;
  1420. case METHOD_HEAD: m = "HEAD"; break;
  1421. case METHOD_POST: m = "POST"; break;
  1422. case METHOD_PUT: m = "PUT"; break;
  1423. case METHOD_OPTIONS: m = "OPTIONS"; break;
  1424. case METHOD_DELETE: m = "DELETE"; break;
  1425. default: abort();
  1426. }
  1427. n = snnprintf(connection->reqbuf, n, bufsize, "%s ", m);
  1428. if(connection->server->isProxy) {
  1429. n = snnprint_n(connection->reqbuf, n, bufsize,
  1430. url, url_size);
  1431. } else {
  1432. if(url_size - z == 0) {
  1433. location = "/";
  1434. location_size = 1;
  1435. } else {
  1436. location = url + z;
  1437. location_size = url_size - z;
  1438. }
  1439. n = snnprint_n(connection->reqbuf, n, bufsize,
  1440. location, location_size);
  1441. }
  1442. do_log(D_SERVER_REQ, "Server request: ");
  1443. do_log_n(D_SERVER_REQ, url + x, y - x);
  1444. do_log(D_SERVER_REQ, ": ");
  1445. do_log_n(D_SERVER_REQ, connection->reqbuf, n);
  1446. do_log(D_SERVER_REQ, " (method %d from %d to %d, 0x%lx for 0x%lx)\n",
  1447. method, from, to,
  1448. (unsigned long)connection, (unsigned long)object);
  1449. n = snnprintf(connection->reqbuf, n, bufsize, " HTTP/1.1");
  1450. n = snnprintf(connection->reqbuf, n, bufsize, "\r\nHost: ");
  1451. n = snnprint_n(connection->reqbuf, n, bufsize, url + x, y - x);
  1452. if(port != 80)
  1453. n = snnprintf(connection->reqbuf, n, bufsize, ":%d", port);
  1454. if(connection->server->isProxy && parentAuthCredentials) {
  1455. n = buildServerAuthHeaders(connection->reqbuf, n, bufsize,
  1456. parentAuthCredentials);
  1457. }
  1458. if(bodylen >= 0)
  1459. n = snnprintf(connection->reqbuf, n, bufsize,
  1460. "\r\nContent-Length: %d", bodylen);
  1461. if(request->flags & REQUEST_WAIT_CONTINUE)
  1462. n = snnprintf(connection->reqbuf, n, bufsize,
  1463. "\r\nExpect: 100-continue");
  1464. if(method != METHOD_HEAD && (from > 0 || to >= 0)) {
  1465. if(to >= 0) {
  1466. n = snnprintf(connection->reqbuf, n, bufsize,
  1467. "\r\nRange: bytes=%d-%d", from, to - 1);
  1468. } else {
  1469. n = snnprintf(connection->reqbuf, n, bufsize,
  1470. "\r\nRange: bytes=%d-", from);
  1471. }
  1472. }
  1473. if(method == METHOD_GET && object->etag && (from > 0 || to >= 0)) {
  1474. if(request->request && request->request->request == request &&
  1475. request->request->from == 0 && request->request->to == -1 &&
  1476. pmmSize == 0 && pmmFirstSize == 0)
  1477. n = snnprintf(connection->reqbuf, n, bufsize,
  1478. "\r\nIf-Range: \"%s\"", object->etag);
  1479. }
  1480. if(method == METHOD_CONDITIONAL_GET) {
  1481. if(object->last_modified >= 0) {
  1482. n = snnprintf(connection->reqbuf, n, bufsize,
  1483. "\r\nIf-Modified-Since: ");
  1484. n = format_time(connection->reqbuf, n, bufsize,
  1485. object->last_modified);
  1486. }
  1487. if(object->etag) {
  1488. n = snnprintf(connection->reqbuf, n, bufsize,
  1489. "\r\nIf-None-Match: \"%s\"", object->etag);
  1490. }
  1491. }
  1492. n = httpPrintCacheControl(connection->reqbuf, n, bufsize,
  1493. alwaysAddNoTransform ? CACHE_NO_TRANSFORM : 0,
  1494. &request->cache_control);
  1495. if(n < 0)
  1496. goto fail;
  1497. if(request->request && request->request->headers) {
  1498. n = snnprint_n(connection->reqbuf, n, bufsize,
  1499. request->request->headers->string,
  1500. request->request->headers->length);
  1501. }
  1502. if(!disableVia) {
  1503. if(request->request && request->request->via) {
  1504. n = snnprintf(connection->reqbuf, n, bufsize,
  1505. "\r\nVia: %s, 1.1 %s",
  1506. request->request->via->string, proxyName->string);
  1507. } else {
  1508. n = snnprintf(connection->reqbuf, n, bufsize,
  1509. "\r\nVia: 1.1 %s",
  1510. proxyName->string);
  1511. }
  1512. }
  1513. n = snnprintf(connection->reqbuf, n, bufsize,
  1514. "\r\nConnection: %s\r\n\r\n",
  1515. (request->flags & REQUEST_PERSISTENT) ?
  1516. "keep-alive" : "close");
  1517. if(n < 0 || n >= bufsize - 1)
  1518. goto fail;
  1519. connection->reqlen = n;
  1520. return n;
  1521. fail:
  1522. rc = 0;
  1523. if(!(connection->flags & CONN_BIGREQBUF))
  1524. rc = httpConnectionBigifyReqbuf(connection);
  1525. if(rc == 1)
  1526. goto again;
  1527. return -1;
  1528. }
  1529. int
  1530. httpServerHandler(int status,
  1531. FdEventHandlerPtr event,
  1532. StreamRequestPtr srequest)
  1533. {
  1534. HTTPConnectionPtr connection = srequest->data;
  1535. assert(connection->request->object->flags & OBJECT_INPROGRESS);
  1536. if(connection->reqlen == 0) {
  1537. do_log(D_SERVER_REQ, "Writing aborted on 0x%lx\n",
  1538. (unsigned long)connection);
  1539. goto fail;
  1540. }
  1541. if(status == 0 && !streamRequestDone(srequest)) {
  1542. httpSetTimeout(connection, serverTimeout);
  1543. return 0;
  1544. }
  1545. httpConnectionDestroyReqbuf(connection);
  1546. if(status) {
  1547. if(connection->serviced >= 1) {
  1548. httpServerRestart(connection);
  1549. return 1;
  1550. }
  1551. if(status < 0 && status != -ECONNRESET && status != -EPIPE)
  1552. do_log_error(L_ERROR, -status,
  1553. "Couldn't send request to server");
  1554. goto fail;
  1555. }
  1556. return 1;
  1557. fail:
  1558. httpConnectionDestroyReqbuf(connection);
  1559. shutdown(connection->fd, 2);
  1560. pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLIN);
  1561. httpSetTimeout(connection, 60);
  1562. return 1;
  1563. }
  1564. int
  1565. httpServerSendRequest(HTTPConnectionPtr connection)
  1566. {
  1567. assert(connection->server);
  1568. if(connection->reqlen == 0) {
  1569. do_log(D_SERVER_REQ,
  1570. "Writing aborted on 0x%lx\n", (unsigned long)connection);
  1571. httpConnectionDestroyReqbuf(connection);
  1572. shutdown(connection->fd, 2);
  1573. pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLIN | POLLOUT);
  1574. return -1;
  1575. }
  1576. httpSetTimeout(connection, serverTimeout);
  1577. do_stream(IO_WRITE, connection->fd, 0,
  1578. connection->reqbuf, connection->reqlen,
  1579. httpServerHandler, connection);
  1580. return 1;
  1581. }
  1582. int
  1583. httpServerReplyHandler(int status,
  1584. FdEventHandlerPtr event,
  1585. StreamRequestPtr srequest)
  1586. {
  1587. HTTPConnectionPtr connection = srequest->data;
  1588. HTTPRequestPtr request = connection->request;
  1589. int i, body;
  1590. int bufsize =
  1591. (connection->flags & CONN_BIGBUF) ? bigBufferSize : CHUNK_SIZE;
  1592. assert(request->object->flags & OBJECT_INPROGRESS);
  1593. if(status < 0) {
  1594. if(connection->serviced >= 1) {
  1595. httpServerRestart(connection);
  1596. return 1;
  1597. }
  1598. if(status != -ECLIENTRESET)
  1599. do_log_error(L_ERROR, -status, "Read from server failed");
  1600. httpServerAbort(connection, status != -ECLIENTRESET, 502,
  1601. internAtomError(-status, "Read from server failed"));
  1602. return 1;
  1603. }
  1604. i = findEndOfHeaders(connection->buf, 0, srequest->offset, &body);
  1605. connection->len = srequest->offset;
  1606. if(i >= 0) {
  1607. request->time1 = current_time;
  1608. return httpServerHandlerHeaders(status, event, srequest, connection);
  1609. }
  1610. if(status) {
  1611. if(connection->serviced >= 1) {
  1612. httpServerRestart(connection);
  1613. return 1;
  1614. }
  1615. if(status < 0) {
  1616. do_log(L_ERROR,
  1617. "Error reading server headers: %d\n", -status);
  1618. httpServerAbort(connection, status != -ECLIENTRESET, 502,
  1619. internAtomError(-status,
  1620. "Error reading server headers"));
  1621. } else
  1622. httpServerAbort(connection, 1, 502,
  1623. internAtom("Server dropped connection"));
  1624. return 1;
  1625. }
  1626. if(connection->len >= bufsize) {
  1627. int rc = 0;
  1628. if(!(connection->flags & CONN_BIGBUF))
  1629. rc = httpConnectionBigify(connection);
  1630. if(rc == 0) {
  1631. do_log(L_ERROR, "Couldn't find end of server's headers.\n");
  1632. httpServerAbort(connection, 1, 502,
  1633. internAtom("Couldn't find end "
  1634. "of server's headers"));
  1635. return 1;
  1636. } else if(rc < 0) {
  1637. do_log(L_ERROR, "Couldn't allocate big buffer.\n");
  1638. httpServerAbort(connection, 1, 500,
  1639. internAtom("Couldn't allocate big buffer"));
  1640. return 1;
  1641. }
  1642. /* Can't just return 0 -- buf has moved. */
  1643. do_stream(IO_READ,
  1644. connection->fd, connection->len,
  1645. connection->buf, bigBufferSize,
  1646. httpServerReplyHandler, connection);
  1647. return 1;
  1648. }
  1649. return 0;
  1650. }
  1651. int
  1652. httpServerHandlerHeaders(int eof,
  1653. FdEventHandlerPtr event,
  1654. StreamRequestPtr srequest,
  1655. HTTPConnectionPtr connection)
  1656. {
  1657. HTTPRequestPtr request = connection->request;
  1658. ObjectPtr object = request->object;
  1659. int rc;
  1660. int code, version;
  1661. int full_len;
  1662. AtomPtr headers;
  1663. int len;
  1664. int te;
  1665. CacheControlRec cache_control;
  1666. int age = -1;
  1667. time_t date, last_modified, expires;
  1668. struct timeval *init_time;
  1669. char *etag;
  1670. AtomPtr via, new_via;
  1671. int expect_body;
  1672. HTTPRangeRec content_range;
  1673. ObjectPtr new_object = NULL, old_object = NULL;
  1674. int supersede = 0;
  1675. AtomPtr message = NULL;
  1676. int suspectDynamic;
  1677. AtomPtr url = NULL;
  1678. assert(request->object->flags & OBJECT_INPROGRESS);
  1679. assert(eof >= 0);
  1680. httpSetTimeout(connection, -1);
  1681. if(request->flags & REQUEST_WAIT_CONTINUE) {
  1682. do_log(D_SERVER_CONN, "W %s:%d.\n",
  1683. connection->server->name, connection->server->port);
  1684. request->flags &= ~REQUEST_WAIT_CONTINUE;
  1685. }
  1686. rc = httpParseServerFirstLine(connection->buf, &code, &version, &message);
  1687. if(rc <= 0) {
  1688. do_log(L_ERROR, "Couldn't parse server status line.\n");
  1689. httpServerAbort(connection, 1, 502,
  1690. internAtom("Couldn't parse server status line"));
  1691. return 1;
  1692. }
  1693. do_log(D_SERVER_REQ, "Server status: ");
  1694. do_log_n(D_SERVER_REQ, connection->buf,
  1695. connection->buf[rc - 1] == '\r' ? rc - 2 : rc - 2);
  1696. do_log(D_SERVER_REQ, " (0x%lx for 0x%lx)\n",
  1697. (unsigned long)connection, (unsigned long)object);
  1698. if(version != HTTP_10 && version != HTTP_11) {
  1699. do_log(L_ERROR, "Unknown server HTTP version\n");
  1700. httpServerAbort(connection, 1, 502,
  1701. internAtom("Unknown server HTTP version"));
  1702. releaseAtom(message);
  1703. return 1;
  1704. }
  1705. connection->version = version;
  1706. connection->server->version = version;
  1707. request->flags |= REQUEST_PERSISTENT;
  1708. url = internAtomN(object->key, object->key_size);
  1709. rc = httpParseHeaders(0, url, connection->buf, rc, request,
  1710. &headers, &len, &cache_control, NULL, &te,
  1711. &date, &last_modified, &expires, NULL, NULL, NULL,
  1712. &age, &etag, NULL, NULL, &content_range,
  1713. NULL, &via, NULL);
  1714. if(rc < 0) {
  1715. do_log(L_ERROR, "Couldn't parse server headers\n");
  1716. releaseAtom(url);
  1717. releaseAtom(message);
  1718. httpServerAbort(connection, 1, 502,
  1719. internAtom("Couldn't parse server headers"));
  1720. return 1;
  1721. }
  1722. if(date < 0)
  1723. date = current_time.tv_sec;
  1724. if(code == 100) {
  1725. releaseAtom(url);
  1726. releaseAtom(message);
  1727. /* We've already reset wait_continue above, but we must still
  1728. ensure that the writer notices. */
  1729. notifyObject(request->object);
  1730. connection->len -= rc;
  1731. if(connection->len > 0)
  1732. memmove(connection->buf, connection->buf + rc, connection->len);
  1733. httpServerReply(connection, 1);
  1734. return 1;
  1735. }
  1736. if(code == 101) {
  1737. httpServerAbort(connection, 1, 501,
  1738. internAtom("Upgrade not implemented"));
  1739. goto fail;
  1740. }
  1741. if(via && !checkVia(proxyName, via)) {
  1742. httpServerAbort(connection, 1, 504, internAtom("Proxy loop detected"));
  1743. goto fail;
  1744. }
  1745. full_len = content_range.full_length;
  1746. if(code == 206) {
  1747. if(content_range.from == -1 || content_range.to == -1) {
  1748. do_log(L_ERROR, "Partial content without range.\n");
  1749. httpServerAbort(connection, 1, 502,
  1750. internAtom("Partial content without range"));
  1751. goto fail;
  1752. }
  1753. if(len >= 0 && len != content_range.to - content_range.from) {
  1754. do_log(L_ERROR, "Inconsistent partial content.\n");
  1755. httpServerAbort(connection, 1, 502,
  1756. internAtom("Inconsistent partial content"));
  1757. goto fail;
  1758. }
  1759. } else if(code < 400 &&
  1760. (content_range.from >= 0 || content_range.to >= 0 ||
  1761. content_range.full_length >= 0)) {
  1762. do_log(L_WARN, "Range without partial content.\n");
  1763. /* Damn anakata. */
  1764. content_range.from = -1;
  1765. content_range.to = -1;
  1766. content_range.full_length = -1;
  1767. } else if(code != 304 && code != 412) {
  1768. full_len = len;
  1769. }
  1770. if(te != TE_IDENTITY && te != TE_CHUNKED) {
  1771. do_log(L_ERROR, "Unsupported transfer-encoding\n");
  1772. httpServerAbort(connection, 1, 502,
  1773. internAtom("Unsupported transfer-encoding"));
  1774. goto fail;
  1775. }
  1776. if(code == 304) {
  1777. if(request->method != METHOD_CONDITIONAL_GET) {
  1778. do_log(L_ERROR, "Unexpected \"not changed\" reply from server\n");
  1779. httpServerAbort(connection, 1, 502,
  1780. internAtom("Unexpected \"not changed\" "
  1781. "reply from server"));
  1782. goto fail;
  1783. }
  1784. if(object->etag && !etag) {
  1785. /* RFC 2616 10.3.5. Violated by some front-end proxies. */
  1786. do_log(L_WARN, "\"Not changed\" reply with no ETag.\n");
  1787. }
  1788. }
  1789. if(code == 412) {
  1790. if(request->method != METHOD_CONDITIONAL_GET ||
  1791. (!object->etag && !object->last_modified)) {
  1792. do_log(L_ERROR,
  1793. "Unexpected \"precondition failed\" reply from server.\n");
  1794. httpServerAbort(connection, 1, 502,
  1795. internAtom("Unexpected \"precondition failed\" "
  1796. "reply from server"));
  1797. goto fail;
  1798. }
  1799. }
  1800. releaseAtom(url);
  1801. /* Okay, we're going to accept this reply. */
  1802. if((code == 200 || code == 206 || code == 304 || code == 412) &&
  1803. (cache_control.flags & (CACHE_NO | CACHE_NO_STORE) ||
  1804. cache_control.max_age == 0 ||
  1805. (cacheIsShared && cache_control.s_maxage == 0) ||
  1806. (expires >= 0 && expires <= object->age))) {
  1807. do_log(L_UNCACHEABLE, "Uncacheable object %s (%d)\n",
  1808. scrub(object->key), cache_control.flags);
  1809. }
  1810. if(request->time0.tv_sec != null_time.tv_sec)
  1811. init_time = &request->time0;
  1812. else
  1813. init_time = &current_time;
  1814. age = MIN(init_time->tv_sec - age, init_time->tv_sec);
  1815. if(request->method == METHOD_HEAD ||
  1816. code < 200 || code == 204 || code == 304)
  1817. expect_body = 0;
  1818. else if(te == TE_IDENTITY)
  1819. expect_body = (len != 0);
  1820. else
  1821. expect_body = 1;
  1822. connection->chunk_remaining = -1;
  1823. connection->te = te;
  1824. old_object = object;
  1825. connection->server->lies--;
  1826. if(object->cache_control & CACHE_MISMATCH)
  1827. supersede = 1;
  1828. if(code == 304 || code == 412) {
  1829. if((object->etag && etag && strcmp(object->etag, etag) != 0) ||
  1830. (object->last_modified >= 0 && last_modified >= 0 &&
  1831. object->last_modified != last_modified)) {
  1832. do_log(L_ERROR, "Inconsistent \"%s\" reply for %s\n",
  1833. code == 304 ? "not changed":"precondition failed",
  1834. scrub(object->key));
  1835. object->flags |= OBJECT_DYNAMIC;
  1836. supersede = 1;
  1837. }
  1838. } else if(!(object->flags & OBJECT_INITIAL)) {
  1839. if((object->last_modified < 0 || last_modified < 0) &&
  1840. (!object->etag || !etag))
  1841. supersede = 1;
  1842. else if(object->last_modified != last_modified)
  1843. supersede = 1;
  1844. else if(object->etag || etag) {
  1845. /* We need to be permissive here so as to deal with some
  1846. front-end proxies that discard ETags on partial
  1847. replies but not on full replies. */
  1848. if(etag && object->etag && strcmp(object->etag, etag) != 0)
  1849. supersede = 1;
  1850. else if(!object->etag)
  1851. supersede = 1;
  1852. }
  1853. if(!supersede && (object->cache_control & CACHE_VARY) &&
  1854. dontTrustVaryETag >= 1) {
  1855. /* Check content-type to work around mod_gzip bugs */
  1856. if(!httpHeaderMatch(atomContentType, object->headers, headers) ||
  1857. !httpHeaderMatch(atomContentEncoding, object->headers, headers))
  1858. supersede = 1;
  1859. }
  1860. if(full_len < 0 && te == TE_IDENTITY) {
  1861. /* It's an HTTP/1.0 CGI. Be afraid. */
  1862. if(expect_body && content_range.from < 0 && content_range.to < 0)
  1863. supersede = 1;
  1864. }
  1865. if(!supersede && object->length >= 0 && full_len >= 0 &&
  1866. object->length != full_len) {
  1867. do_log(L_WARN, "Inconsistent length.\n");
  1868. supersede = 1;
  1869. }
  1870. if(!supersede &&
  1871. ((object->last_modified >= 0 && last_modified >= 0) ||
  1872. (object->etag && etag))) {
  1873. if(request->method == METHOD_CONDITIONAL_GET) {
  1874. do_log(L_WARN, "Server ignored conditional request.\n");
  1875. connection->server->lies += 10;
  1876. /* Drop the connection? */
  1877. }
  1878. }
  1879. } else if(code == 416) {
  1880. do_log(L_ERROR, "Unexpected \"range not satisfiable\" reply\n");
  1881. httpServerAbort(connection, 1, 502,
  1882. internAtom("Unexpected \"range not satisfiable\" "
  1883. "reply"));
  1884. /* The object may be superseded. Make sure the next request
  1885. won't be partial. */
  1886. abortObject(object, 502,
  1887. internAtom("Unexpected \"range not satisfiable\" reply"));
  1888. return 1;
  1889. }
  1890. if(object->flags & OBJECT_INITIAL)
  1891. supersede = 0;
  1892. if(supersede) {
  1893. do_log(L_SUPERSEDED,
  1894. "Superseding object %s (%d %d %d %s -> %d %d %d %s)\n",
  1895. scrub(old_object->key),
  1896. object->code, object->length, (int)object->last_modified,
  1897. object->etag ? object->etag : "(none)",
  1898. code, full_len, (int)last_modified,
  1899. etag ? etag : "(none)");
  1900. privatiseObject(old_object, 0);
  1901. new_object = makeObject(object->type, object->key,
  1902. object->key_size, 1, 0,
  1903. object->request, NULL);
  1904. if(new_object == NULL) {
  1905. do_log(L_ERROR, "Couldn't allocate object\n");
  1906. httpServerAbort(connection, 1, 500,
  1907. internAtom("Couldn't allocate object"));
  1908. return 1;
  1909. }
  1910. if(urlIsLocal(new_object->key, new_object->key_size))
  1911. new_object->flags |= OBJECT_LOCAL;
  1912. } else {
  1913. new_object = object;
  1914. }
  1915. suspectDynamic =
  1916. (!etag && last_modified < 0) ||
  1917. (cache_control.flags &
  1918. (CACHE_NO_HIDDEN | CACHE_NO | CACHE_NO_STORE |
  1919. (cacheIsShared ? CACHE_PRIVATE : 0))) ||
  1920. (cache_control.max_age >= 0 && cache_control.max_age <= 2) ||
  1921. (cacheIsShared &&
  1922. cache_control.s_maxage >= 0 && cache_control.s_maxage <= 5) ||
  1923. (old_object->last_modified >= 0 && old_object->expires >= 0 &&
  1924. (old_object->expires - old_object->last_modified <= 1)) ||
  1925. (supersede && (old_object->date - date <= 5));
  1926. if(suspectDynamic)
  1927. new_object->flags |= OBJECT_DYNAMIC;
  1928. else if(!supersede)
  1929. new_object->flags &= ~OBJECT_DYNAMIC;
  1930. else if(old_object->flags & OBJECT_DYNAMIC)
  1931. new_object->flags |= OBJECT_DYNAMIC;
  1932. new_object->age = age;
  1933. new_object->cache_control |= cache_control.flags;
  1934. new_object->max_age = cache_control.max_age;
  1935. new_object->s_maxage = cache_control.s_maxage;
  1936. new_object->flags &= ~OBJECT_FAILED;
  1937. if(date >= 0)
  1938. new_object->date = date;
  1939. if(last_modified >= 0)
  1940. new_object->last_modified = last_modified;
  1941. if(expires >= 0)
  1942. new_object->expires = expires;
  1943. if(new_object->etag == NULL)
  1944. new_object->etag = etag;
  1945. else
  1946. free(etag);
  1947. switch(code) {
  1948. case 200:
  1949. case 300: case 301: case 302: case 303: case 307:
  1950. case 403: case 404: case 405: case 401:
  1951. if(new_object->message) releaseAtom(new_object->message);
  1952. new_object->code = code;
  1953. new_object->message = message;
  1954. break;
  1955. case 206: case 304: case 412:
  1956. if(new_object->code != 200 || !new_object->message) {
  1957. if(new_object->message) releaseAtom(new_object->message);
  1958. new_object->code = 200;
  1959. new_object->message = internAtom("OK");
  1960. }
  1961. releaseAtom(message);
  1962. break;
  1963. default:
  1964. if(new_object->message) releaseAtom(new_object->message);
  1965. new_object->code = code;
  1966. new_object->message = retainAtom(message);
  1967. break;
  1968. }
  1969. httpTweakCachability(new_object);
  1970. if(!via)
  1971. new_via = internAtomF("%s %s",
  1972. version == HTTP_11 ? "1.1" : "1.0",
  1973. proxyName->string);
  1974. else
  1975. new_via = internAtomF("%s, %s %s", via->string,
  1976. version == HTTP_11 ? "1.1" : "1.0",
  1977. proxyName->string);
  1978. if(new_via == NULL) {
  1979. do_log(L_ERROR, "Couldn't allocate Via.\n");
  1980. } else {
  1981. if(new_object->via) releaseAtom(new_object->via);
  1982. new_object->via = new_via;
  1983. }
  1984. if(new_object->flags & OBJECT_INITIAL) {
  1985. objectPartial(new_object, full_len, headers);
  1986. } else {
  1987. if(new_object->length < 0)
  1988. new_object->length = full_len;
  1989. /* XXX -- RFC 2616 13.5.3 */
  1990. releaseAtom(headers);
  1991. }
  1992. if(supersede) {
  1993. assert(new_object != old_object);
  1994. supersedeObject(old_object);
  1995. }
  1996. if(new_object != old_object) {
  1997. if(new_object->flags & OBJECT_INPROGRESS) {
  1998. /* Make sure we don't fetch this object two times at the
  1999. same time. Just drop the connection. */
  2000. releaseObject(new_object);
  2001. httpServerFinish(connection, 1, 0);
  2002. return 1;
  2003. }
  2004. old_object->flags &= ~OBJECT_VALIDATING;
  2005. new_object->flags |= OBJECT_INPROGRESS;
  2006. /* Signal the client side to switch to the new object -- see
  2007. httpClientGetHandler. If it doesn't, we'll give up on this
  2008. request below. */
  2009. new_object->flags |= OBJECT_MUTATING;
  2010. request->can_mutate = new_object;
  2011. notifyObject(old_object);
  2012. request->can_mutate = NULL;
  2013. new_object->flags &= ~OBJECT_MUTATING;
  2014. old_object->flags &= ~OBJECT_INPROGRESS;
  2015. if(request->object == old_object) {
  2016. if(request->request)
  2017. request->request->request = NULL;
  2018. request->request = NULL;
  2019. request->object = new_object;
  2020. } else {
  2021. assert(request->object == new_object);
  2022. }
  2023. releaseNotifyObject(old_object);
  2024. old_object = NULL;
  2025. object = new_object;
  2026. } else {
  2027. objectMetadataChanged(new_object, 0);
  2028. }
  2029. if(object->flags & OBJECT_VALIDATING) {
  2030. object->flags &= ~OBJECT_VALIDATING;
  2031. notifyObject(object);
  2032. }
  2033. if(!expect_body) {
  2034. httpServerFinish(connection, 0, rc);
  2035. return 1;
  2036. }
  2037. if(request->request == NULL) {
  2038. httpServerFinish(connection, 1, 0);
  2039. return 1;
  2040. }
  2041. if(code == 412) {
  2042. /* 412 replies contain a useless body. For now, we
  2043. drop the connection. */
  2044. httpServerFinish(connection, 1, 0);
  2045. return 1;
  2046. }
  2047. if(request->flags & REQUEST_PERSISTENT) {
  2048. if(request->method != METHOD_HEAD &&
  2049. connection->te == TE_IDENTITY && len < 0) {
  2050. do_log(L_ERROR, "Persistent reply with no Content-Length\n");
  2051. /* That's potentially dangerous, as we could start reading
  2052. arbitrary data into the object. Unfortunately, some
  2053. servers do that. */
  2054. request->flags &= ~REQUEST_PERSISTENT;
  2055. }
  2056. }
  2057. /* we're getting a body */
  2058. if(content_range.from > 0)
  2059. connection->offset = content_range.from;
  2060. else
  2061. connection->offset = 0;
  2062. if(content_range.to >= 0)
  2063. request->to = content_range.to;
  2064. do_log(D_SERVER_OFFSET, "0x%lx(0x%lx): offset = %d\n",
  2065. (unsigned long)connection, (unsigned long)object,
  2066. connection->offset);
  2067. if(connection->len > rc) {
  2068. rc = connectionAddData(connection, rc);
  2069. if(rc) {
  2070. if(rc < 0) {
  2071. if(rc == -2) {
  2072. do_log(L_ERROR, "Couldn't parse chunk size.\n");
  2073. httpServerAbort(connection, 1, 502,
  2074. internAtom("Couldn't parse chunk size"));
  2075. } else {
  2076. do_log(L_ERROR, "Couldn't add data to connection.\n");
  2077. httpServerAbort(connection, 1, 500,
  2078. internAtom("Couldn't add data "
  2079. "to connection"));
  2080. }
  2081. return 1;
  2082. } else {
  2083. if(code != 206) {
  2084. if(object->length < 0) {
  2085. object->length = object->size;
  2086. objectMetadataChanged(object, 0);
  2087. } else if(object->length != object->size) {
  2088. httpServerAbort(connection, 1, 500,
  2089. internAtom("Inconsistent "
  2090. "object size"));
  2091. object->length = -1;
  2092. return 1;
  2093. }
  2094. }
  2095. httpServerFinish(connection, 0, 0);
  2096. return 1;
  2097. }
  2098. }
  2099. } else {
  2100. connection->len = 0;
  2101. }
  2102. if(eof) {
  2103. if(connection->te == TE_CHUNKED ||
  2104. (object->length >= 0 &&
  2105. connection->offset < object->length)) {
  2106. do_log(L_ERROR, "Server closed connection.\n");
  2107. httpServerAbort(connection, 1, 502,
  2108. internAtom("Server closed connection"));
  2109. return 1;
  2110. } else {
  2111. if(code != 206 && eof > 0 && object->length < 0) {
  2112. object->length = object->size;
  2113. objectMetadataChanged(object, 0);
  2114. }
  2115. httpServerFinish(connection, 1, 0);
  2116. return 1;
  2117. }
  2118. } else {
  2119. return httpServerReadData(connection, 1);
  2120. }
  2121. return 0;
  2122. fail:
  2123. releaseAtom(url);
  2124. releaseAtom(message);
  2125. if(headers)
  2126. releaseAtom(headers);
  2127. if(etag)
  2128. free(etag);
  2129. if(via)
  2130. releaseAtom(via);
  2131. return 1;
  2132. }
  2133. int
  2134. httpServerIndirectHandlerCommon(HTTPConnectionPtr connection, int eof)
  2135. {
  2136. HTTPRequestPtr request = connection->request;
  2137. assert(eof >= 0);
  2138. assert(request->object->flags & OBJECT_INPROGRESS);
  2139. if(connection->len > 0) {
  2140. int rc;
  2141. rc = connectionAddData(connection, 0);
  2142. if(rc) {
  2143. if(rc < 0) {
  2144. if(rc == -2) {
  2145. do_log(L_ERROR, "Couldn't parse chunk size.\n");
  2146. httpServerAbort(connection, 1, 502,
  2147. internAtom("Couldn't parse chunk size"));
  2148. } else {
  2149. do_log(L_ERROR, "Couldn't add data to connection.\n");
  2150. httpServerAbort(connection, 1, 500,
  2151. internAtom("Couldn't add data "
  2152. "to connection"));
  2153. }
  2154. return 1;
  2155. } else {
  2156. if(request->to < 0) {
  2157. if(request->object->length < 0) {
  2158. request->object->length = request->object->size;
  2159. objectMetadataChanged(request->object, 0);
  2160. } else if(request->object->length !=
  2161. request->object->size) {
  2162. request->object->length = -1;
  2163. httpServerAbort(connection, 1, 502,
  2164. internAtom("Inconsistent "
  2165. "object size"));
  2166. return 1;
  2167. }
  2168. }
  2169. httpServerFinish(connection, 0, 0);
  2170. }
  2171. return 1;
  2172. }
  2173. }
  2174. if(eof && connection->len == 0) {
  2175. if(connection->te == TE_CHUNKED ||
  2176. (request->to >= 0 && connection->offset < request->to)) {
  2177. do_log(L_ERROR, "Server dropped connection.\n");
  2178. httpServerAbort(connection, 1, 502,
  2179. internAtom("Server dropped connection"));
  2180. return 1;
  2181. } else {
  2182. if(request->object->length < 0 && eof > 0 &&
  2183. (request->to < 0 || request->to > request->object->size)) {
  2184. request->object->length = request->object->size;
  2185. objectMetadataChanged(request->object, 0);
  2186. }
  2187. httpServerFinish(connection, 1, 0);
  2188. return 1;
  2189. }
  2190. } else {
  2191. return httpServerReadData(connection, 0);
  2192. }
  2193. }
  2194. int
  2195. httpServerIndirectHandler(int status,
  2196. FdEventHandlerPtr event,
  2197. StreamRequestPtr srequest)
  2198. {
  2199. HTTPConnectionPtr connection = srequest->data;
  2200. assert(connection->request->object->flags & OBJECT_INPROGRESS);
  2201. httpSetTimeout(connection, -1);
  2202. if(status < 0) {
  2203. if(status != -ECLIENTRESET)
  2204. do_log_error(L_ERROR, -status, "Read from server failed");
  2205. httpServerAbort(connection, status != -ECLIENTRESET, 502,
  2206. internAtomError(-status, "Read from server failed"));
  2207. return 1;
  2208. }
  2209. connection->len = srequest->offset;
  2210. return httpServerIndirectHandlerCommon(connection, status);
  2211. }
  2212. int
  2213. httpServerReadData(HTTPConnectionPtr connection, int immediate)
  2214. {
  2215. HTTPRequestPtr request = connection->request;
  2216. ObjectPtr object = request->object;
  2217. int to = -1;
  2218. assert(object->flags & OBJECT_INPROGRESS);
  2219. if(request->request == NULL) {
  2220. httpServerFinish(connection, 1, 0);
  2221. return 1;
  2222. }
  2223. if(request->to >= 0)
  2224. to = request->to;
  2225. else
  2226. to = object->length;
  2227. if(to >= 0 && to == connection->offset) {
  2228. httpServerFinish(connection, 0, 0);
  2229. return 1;
  2230. }
  2231. if(connection->len == 0 &&
  2232. ((connection->te == TE_IDENTITY && to > connection->offset) ||
  2233. (connection->te == TE_CHUNKED && connection->chunk_remaining > 0))) {
  2234. /* Read directly into the object */
  2235. int i = connection->offset / CHUNK_SIZE;
  2236. int j = connection->offset % CHUNK_SIZE;
  2237. int end, len, more;
  2238. /* See httpServerDirectHandlerCommon if you change this */
  2239. if(connection->te == TE_CHUNKED) {
  2240. len = connection->chunk_remaining;
  2241. /* The logic here is that we want more to just fit the
  2242. chunk header if we're doing a large read, but do a
  2243. large read if we would otherwise do a small one. The
  2244. magic constant 2000 comes from the assumption that the
  2245. server uses chunks that have a size that are a power of
  2246. two (possibly including the chunk header), and that we
  2247. want a full ethernet packet to fit into our read. */
  2248. more = (len >= 2000 ? 20 : MIN(2048 - len, CHUNK_SIZE));
  2249. } else {
  2250. len = to - connection->offset;
  2251. /* We read more data only when there is a reasonable
  2252. chance of there being another reply coming. */
  2253. more = (connection->pipelined > 1) ? CHUNK_SIZE : 0;
  2254. }
  2255. end = len + connection->offset;
  2256. httpConnectionDestroyBuf(connection);
  2257. /* The order of allocation is important in case we run out of
  2258. memory. */
  2259. lockChunk(object, i);
  2260. if(object->chunks[i].data == NULL)
  2261. object->chunks[i].data = get_chunk();
  2262. if(object->chunks[i].data && object->chunks[i].size >= j) {
  2263. if(len + j > CHUNK_SIZE) {
  2264. lockChunk(object, i + 1);
  2265. if(object->chunks[i + 1].data == NULL)
  2266. object->chunks[i + 1].data = get_chunk();
  2267. /* Unless we're grabbing all len of data, we do not
  2268. want to do an indirect read immediately afterwards. */
  2269. if(more && len + j <= 2 * CHUNK_SIZE) {
  2270. if(!connection->buf)
  2271. connection->buf = get_chunk(); /* checked below */
  2272. }
  2273. if(object->chunks[i + 1].data) {
  2274. do_stream_3(IO_READ | IO_NOTNOW, connection->fd, j,
  2275. object->chunks[i].data, CHUNK_SIZE,
  2276. object->chunks[i + 1].data,
  2277. MIN(CHUNK_SIZE,
  2278. end - (i + 1) * CHUNK_SIZE),
  2279. connection->buf, connection->buf ? more : 0,
  2280. httpServerDirectHandler2, connection);
  2281. return 1;
  2282. }
  2283. unlockChunk(object, i + 1);
  2284. }
  2285. if(more && len + j <= CHUNK_SIZE) {
  2286. if(!connection->buf)
  2287. connection->buf = get_chunk();
  2288. }
  2289. do_stream_2(IO_READ | IO_NOTNOW, connection->fd, j,
  2290. object->chunks[i].data,
  2291. MIN(CHUNK_SIZE, end - i * CHUNK_SIZE),
  2292. connection->buf, connection->buf ? more : 0,
  2293. httpServerDirectHandler, connection);
  2294. return 1;
  2295. } else {
  2296. unlockChunk(object, i);
  2297. }
  2298. }
  2299. if(connection->len == 0)
  2300. httpConnectionDestroyBuf(connection);
  2301. httpSetTimeout(connection, serverTimeout);
  2302. do_stream_buf(IO_READ | IO_NOTNOW |
  2303. ((immediate && connection->len) ? IO_IMMEDIATE : 0),
  2304. connection->fd, connection->len,
  2305. &connection->buf,
  2306. (connection->te == TE_CHUNKED ?
  2307. MIN(2048, CHUNK_SIZE) : CHUNK_SIZE),
  2308. httpServerIndirectHandler, connection);
  2309. return 1;
  2310. }
  2311. int
  2312. httpServerDirectHandlerCommon(int kind, int status,
  2313. FdEventHandlerPtr event,
  2314. StreamRequestPtr srequest)
  2315. {
  2316. HTTPConnectionPtr connection = srequest->data;
  2317. HTTPRequestPtr request = connection->request;
  2318. ObjectPtr object = request->object;
  2319. int i = connection->offset / CHUNK_SIZE;
  2320. int to, end, end1;
  2321. assert(request->object->flags & OBJECT_INPROGRESS);
  2322. httpSetTimeout(connection, -1);
  2323. if(status < 0) {
  2324. unlockChunk(object, i);
  2325. if(kind == 2) unlockChunk(object, i + 1);
  2326. if(status != -ECLIENTRESET)
  2327. do_log_error(L_ERROR, -status, "Read from server failed");
  2328. httpServerAbort(connection, status != -ECLIENTRESET, 502,
  2329. internAtomError(-status, "Read from server failed"));
  2330. return 1;
  2331. }
  2332. /* We have incestuous knowledge of the decisions made in
  2333. httpServerReadData */
  2334. if(request->to >= 0)
  2335. to = request->to;
  2336. else
  2337. to = object->length;
  2338. if(connection->te == TE_CHUNKED)
  2339. end = connection->offset + connection->chunk_remaining;
  2340. else
  2341. end = to;
  2342. /* The amount of data actually read into the object */
  2343. end1 = MIN(end, i * CHUNK_SIZE + MIN(kind * CHUNK_SIZE, srequest->offset));
  2344. assert(end >= 0);
  2345. assert(end1 >= i * CHUNK_SIZE);
  2346. assert(end1 - 2 * CHUNK_SIZE <= i * CHUNK_SIZE);
  2347. object->chunks[i].size =
  2348. MAX(object->chunks[i].size, MIN(end1 - i * CHUNK_SIZE, CHUNK_SIZE));
  2349. if(kind == 2 && end1 > (i + 1) * CHUNK_SIZE) {
  2350. object->chunks[i + 1].size =
  2351. MAX(object->chunks[i + 1].size, end1 - (i + 1) * CHUNK_SIZE);
  2352. }
  2353. if(connection->te == TE_CHUNKED) {
  2354. connection->chunk_remaining -= (end1 - connection->offset);
  2355. assert(connection->chunk_remaining >= 0);
  2356. }
  2357. connection->offset = end1;
  2358. object->size = MAX(object->size, end1);
  2359. unlockChunk(object, i);
  2360. if(kind == 2) unlockChunk(object, i + 1);
  2361. if(i * CHUNK_SIZE + srequest->offset > end1) {
  2362. connection->len = i * CHUNK_SIZE + srequest->offset - end1;
  2363. return httpServerIndirectHandlerCommon(connection, status);
  2364. } else {
  2365. notifyObject(object);
  2366. if(status) {
  2367. if(connection->te == TE_CHUNKED ||
  2368. (end >= 0 && connection->offset < end)) {
  2369. do_log(L_ERROR, "Server dropped connection.\n");
  2370. httpServerAbort(connection, 1, 502,
  2371. internAtom("Server dropped connection"));
  2372. } else
  2373. httpServerFinish(connection, 1, 0);
  2374. return 1;
  2375. } else {
  2376. return httpServerReadData(connection, 0);
  2377. }
  2378. }
  2379. }
  2380. int
  2381. httpServerDirectHandler(int status,
  2382. FdEventHandlerPtr event,
  2383. StreamRequestPtr srequest)
  2384. {
  2385. return httpServerDirectHandlerCommon(1, status, event, srequest);
  2386. }
  2387. int
  2388. httpServerDirectHandler2(int status,
  2389. FdEventHandlerPtr event,
  2390. StreamRequestPtr srequest)
  2391. {
  2392. return httpServerDirectHandlerCommon(2, status, event, srequest);
  2393. }
  2394. /* Add the data accumulated in connection->buf into the object in
  2395. connection->request. Returns 0 in the normal case, 1 if the TE is
  2396. self-terminating and we're done, -1 if there was a problem with
  2397. objectAddData, -2 if there was a problem with the data. */
  2398. int
  2399. connectionAddData(HTTPConnectionPtr connection, int skip)
  2400. {
  2401. HTTPRequestPtr request = connection->request;
  2402. ObjectPtr object = request->object;
  2403. int rc;
  2404. if(connection->te == TE_IDENTITY) {
  2405. int len;
  2406. len = connection->len - skip;
  2407. if(object->length >= 0) {
  2408. len = MIN(object->length - connection->offset, len);
  2409. }
  2410. if(request->to >= 0)
  2411. len = MIN(request->to - connection->offset, len);
  2412. if(len > 0) {
  2413. rc = objectAddData(object, connection->buf + skip,
  2414. connection->offset, len);
  2415. if(rc < 0)
  2416. return -1;
  2417. connection->offset += len;
  2418. connection->len -= (len + skip);
  2419. do_log(D_SERVER_OFFSET, "0x%lx(0x%lx): offset = %d\n",
  2420. (unsigned long)connection, (unsigned long)object,
  2421. connection->offset);
  2422. }
  2423. if(connection->len > 0 && skip + len > 0) {
  2424. memmove(connection->buf,
  2425. connection->buf + skip + len, connection->len);
  2426. }
  2427. if((object->length >= 0 && object->length <= connection->offset) ||
  2428. (request->to >= 0 && request->to <= connection->offset)) {
  2429. notifyObject(object);
  2430. return 1;
  2431. } else {
  2432. if(len > 0)
  2433. notifyObject(object);
  2434. return 0;
  2435. }
  2436. } else if(connection->te == TE_CHUNKED) {
  2437. int i = skip, j, size;
  2438. /* connection->chunk_remaining is 0 at the end of a chunk, -1
  2439. after the CR/LF pair ending a chunk, and -2 after we've
  2440. seen a chunk of length 0. */
  2441. if(connection->chunk_remaining > -2) {
  2442. while(1) {
  2443. if(connection->chunk_remaining <= 0) {
  2444. if(connection->chunk_remaining == 0) {
  2445. if(connection->len < i + 2)
  2446. break;
  2447. if(connection->buf[i] != '\r' ||
  2448. connection->buf[i + 1] != '\n')
  2449. return -1;
  2450. i += 2;
  2451. connection->chunk_remaining = -1;
  2452. }
  2453. if(connection->len < i + 2)
  2454. break;
  2455. j = parseChunkSize(connection->buf, i,
  2456. connection->len, &size);
  2457. if(j < 0)
  2458. return -2;
  2459. if(j == 0)
  2460. break;
  2461. else
  2462. i = j;
  2463. if(size == 0) {
  2464. connection->chunk_remaining = -2;
  2465. break;
  2466. } else {
  2467. connection->chunk_remaining = size;
  2468. }
  2469. } else {
  2470. /* connection->chunk_remaining > 0 */
  2471. size = MIN(connection->chunk_remaining,
  2472. connection->len - i);
  2473. if(size <= 0)
  2474. break;
  2475. rc = objectAddData(object, connection->buf + i,
  2476. connection->offset, size);
  2477. connection->offset += size;
  2478. if(rc < 0)
  2479. return -1;
  2480. i += size;
  2481. connection->chunk_remaining -= size;
  2482. do_log(D_SERVER_OFFSET, "0x%lx(0x%lx): offset = %d\n",
  2483. (unsigned long)connection,
  2484. (unsigned long)object,
  2485. connection->offset);
  2486. }
  2487. }
  2488. }
  2489. connection->len -= i;
  2490. if(connection->len > 0)
  2491. memmove(connection->buf, connection->buf + i, connection->len);
  2492. if(i > 0 || connection->chunk_remaining == -2)
  2493. notifyObject(object);
  2494. if(connection->chunk_remaining == -2)
  2495. return 1;
  2496. else
  2497. return 0;
  2498. } else {
  2499. abort();
  2500. }
  2501. }
  2502. void
  2503. listServers(FILE *out)
  2504. {
  2505. HTTPServerPtr server;
  2506. int i, n, m, entry;
  2507. fprintf(out, "<!DOCTYPE HTML PUBLIC "
  2508. "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
  2509. "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
  2510. "<html><head>\n"
  2511. "\r\n<title>Known servers</title>\n"
  2512. "</head><body>\n"
  2513. "<h1>Known servers</h1>\n");
  2514. alternatingHttpStyle(out, "servers");
  2515. fprintf(out, "<table id=servers>\n");
  2516. fprintf(out, "<thead><tr><th>Server</th>"
  2517. "<th>Version</th>"
  2518. "<th>Persistent</th>"
  2519. "<th>Pipeline</th>"
  2520. "<th>Connections</th>"
  2521. "<th></th>"
  2522. "<th>rtt</th>"
  2523. "<th>rate</th>"
  2524. "</tr></thead>\n");
  2525. fprintf(out, "<tbody>\n");
  2526. server = servers;
  2527. entry = 0;
  2528. while(server) {
  2529. fprintf(out, "<tr class=\"%s\">", entry % 2 == 0 ? "even" : "odd");
  2530. if(server->port == 80)
  2531. fprintf(out, "<td>%s</td>", server->name);
  2532. else
  2533. fprintf(out, "<td>%s:%d</td>", server->name, server->port);
  2534. if(server->version == HTTP_11)
  2535. fprintf(out, "<td>1.1</td>");
  2536. else if(server->version == HTTP_10)
  2537. fprintf(out, "<td>1.0</td>");
  2538. else
  2539. fprintf(out, "<td>unknown</td>");
  2540. if(server->persistent < 0)
  2541. fprintf(out, "<td>no</td>");
  2542. else if(server->persistent > 0)
  2543. fprintf(out, "<td>yes</td>");
  2544. else
  2545. fprintf(out, "<td>unknown</td>");
  2546. if(server->version != HTTP_11 || server->persistent <= 0)
  2547. fprintf(out, "<td></td>");
  2548. else if(server->pipeline < 0)
  2549. fprintf(out, "<td>no</td>");
  2550. else if(server->pipeline >= 0 && server->pipeline <= 1)
  2551. fprintf(out, "<td>unknown</td>");
  2552. else if(server->pipeline == 2 || server->pipeline == 3)
  2553. fprintf(out, "<td>probing</td>");
  2554. else
  2555. fprintf(out, "<td>yes</td>");
  2556. n = 0; m = 0;
  2557. for(i = 0; i < server->maxslots; i++)
  2558. if(server->connection[i] && !server->connection[i]->connecting) {
  2559. if(i < server->numslots)
  2560. n++;
  2561. else
  2562. m++;
  2563. }
  2564. fprintf(out, "<td>%d/%d", n, server->numslots);
  2565. if(m)
  2566. fprintf(out, " + %d</td>", m);
  2567. else
  2568. fprintf(out, "</td>");
  2569. if(server->lies > 0)
  2570. fprintf(out, "<td>(%d lies)</td>", (server->lies + 9) / 10);
  2571. else
  2572. fprintf(out, "<td></td>");
  2573. if(server->rtt > 0)
  2574. fprintf(out, "<td>%.3f</td>", (double)server->rtt / 1000000.0);
  2575. else
  2576. fprintf(out, "<td></td>");
  2577. if(server->rate > 0)
  2578. fprintf(out, "<td>%d</td>", server->rate);
  2579. else
  2580. fprintf(out, "<td></td>");
  2581. fprintf(out, "</tr>\n");
  2582. server = server->next;
  2583. entry++;
  2584. }
  2585. fprintf(out, "</tbody>\n");
  2586. fprintf(out, "</table>\n");
  2587. fprintf(out, "<p><a href=\"/polipo/\">back</a></p>");
  2588. fprintf(out, "</body></html>\n");
  2589. }