123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389 |
- /*
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: George Wang <gwang@litespeedtech.com> |
- +----------------------------------------------------------------------+
- */
- /*
- Copyright (c) 2002-2018, Lite Speed Technologies Inc.
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of the Lite Speed Technologies Inc nor the
- names of its contributors may be used to endorse or promote
- products derived from this software without specific prior
- written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <ctype.h>
- #include <dlfcn.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <sys/stat.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/resource.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <sys/uio.h>
- #include <sys/wait.h>
- #include <grp.h>
- #include <pwd.h>
- #include <time.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <sys/un.h>
- #include "lsapilib.h"
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- #include <sys/prctl.h>
- #endif
- #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
- || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- #include <sys/sysctl.h>
- #endif
- #include <inttypes.h>
- #ifndef uint32
- #define uint32 uint32_t
- #endif
- #include <Zend/zend_portability.h>
- struct lsapi_MD5Context {
- uint32 buf[4];
- uint32 bits[2];
- unsigned char in[64];
- };
- void lsapi_MD5Init(struct lsapi_MD5Context *context);
- void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
- unsigned len);
- void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
- /*
- * This is needed to make RSAREF happy on some MS-DOS compilers.
- */
- typedef struct lsapi_MD5Context lsapi_MD5_CTX;
- #define LSAPI_ST_REQ_HEADER 1
- #define LSAPI_ST_REQ_BODY 2
- #define LSAPI_ST_RESP_HEADER 4
- #define LSAPI_ST_RESP_BODY 8
- #define LSAPI_ST_BACKGROUND 16
- #define LSAPI_RESP_BUF_SIZE 8192
- #define LSAPI_INIT_RESP_HEADER_LEN 4096
- enum
- {
- LSAPI_STATE_IDLE,
- LSAPI_STATE_CONNECTED,
- LSAPI_STATE_ACCEPTING,
- };
- typedef struct lsapi_child_status
- {
- int m_pid;
- long m_tmStart;
- volatile short m_iKillSent;
- volatile char m_inProcess;
- volatile char m_state;
- volatile int m_iReqCounter;
- volatile long m_tmWaitBegin;
- volatile long m_tmReqBegin;
- volatile long m_tmLastCheckPoint;
- }
- lsapi_child_status;
- static lsapi_child_status * s_worker_status = NULL;
- static int g_inited = 0;
- static int g_running = 1;
- static int s_ppid;
- static int s_restored_ppid = 0;
- static int s_pid = 0;
- static int s_slow_req_msecs = 0;
- static int s_keep_listener = 1;
- static int s_dump_debug_info = 0;
- static int s_pid_dump_debug_info = 0;
- static int s_req_processed = 0;
- static int s_skip_write = 0;
- static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
- void (*child)(void)) = NULL;
- static int *s_busy_workers = NULL;
- static int *s_accepting_workers = NULL;
- static int *s_global_counter = &s_req_processed;
- static int s_max_busy_workers = -1;
- static char *s_stderr_log_path = NULL;
- static int s_stderr_is_pipe = 0;
- static int s_ignore_pid = -1;
- static size_t s_total_pages = 1;
- static size_t s_min_avail_pages = 256 * 1024;
- static size_t *s_avail_pages = &s_total_pages;
- LSAPI_Request g_req =
- { .m_fdListen = -1, .m_fd = -1 };
- static char s_secret[24];
- static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
- void Flush_RespBuf_r( LSAPI_Request * pReq );
- static int lsapi_reopen_stderr(const char *p);
- static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
- {
- "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
- "HTTP_ACCEPT_ENCODING",
- "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
- "HTTP_CONNECTION", "CONTENT_TYPE",
- "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
- "HTTP_HOST", "HTTP_PRAGMA",
- "HTTP_REFERER", "HTTP_USER_AGENT",
- "HTTP_CACHE_CONTROL",
- "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
- "HTTP_IF_NONE_MATCH",
- "HTTP_IF_RANGE",
- "HTTP_IF_UNMODIFIED_SINCE",
- "HTTP_KEEP_ALIVE",
- "HTTP_RANGE",
- "HTTP_X_FORWARDED_FOR",
- "HTTP_VIA",
- "HTTP_TRANSFER_ENCODING"
- };
- static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
- { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
- 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
- static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
- {
- "Accept", "Accept-Charset",
- "Accept-Encoding",
- "Accept-Language", "Authorization",
- "Connection", "Content-Type",
- "Content-Length", "Cookie", "Cookie2",
- "Host", "Pragma",
- "Referer", "User-Agent",
- "Cache-Control",
- "If-Modified-Since", "If-Match",
- "If-None-Match",
- "If-Range",
- "If-Unmodified-Since",
- "Keep-Alive",
- "Range",
- "X-Forwarded-For",
- "Via",
- "Transfer-Encoding"
- };
- static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
- { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
- 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
- };
- static const char *s_log_level_names[8] =
- {
- "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
- };
- void LSAPI_Log(int flag, const char * fmt, ...)
- {
- char buf[1024];
- char *p = buf;
- if ((flag & LSAPI_LOG_TIMESTAMP_BITS)
- && !(s_stderr_is_pipe))
- {
- struct timeval tv;
- struct tm tm;
- gettimeofday(&tv, NULL);
- localtime_r(&tv.tv_sec, &tm);
- if (flag & LSAPI_LOG_TIMESTAMP_FULL)
- {
- p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
- }
- else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
- {
- p += snprintf(p, 1024, "%02d:%02d:%02d ",
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- }
- }
- int level = flag & LSAPI_LOG_LEVEL_BITS;
- if (level && level <= LSAPI_LOG_FLAG_FATAL)
- {
- p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
- }
- if (flag & LSAPI_LOG_PID)
- {
- p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid);
- }
- if (p > buf)
- fprintf(stderr, "%.*s", (int)(p - buf), buf);
- va_list ap;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- }
- #ifdef LSAPI_DEBUG
- #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
- #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
- #else
- #define lsapi_dbg(...)
- #endif
- #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__)
- void lsapi_perror(const char * pMessage, int err_no)
- {
- lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no));
- }
- static int lsapi_parent_dead()
- {
- // Return non-zero if the parent is dead. 0 if still alive.
- if (!s_ppid) {
- // not checking, so not dead
- return(0);
- }
- if (s_restored_ppid) {
- if (kill(s_restored_ppid,0) == -1) {
- if (errno == EPERM) {
- return(0); // no permission, but it's still there.
- }
- return(1); // Dead
- }
- return(0); // it worked, so it's not dead
- }
- return(s_ppid != getppid());
- }
- static void lsapi_sigpipe( int sig )
- {
- }
- static void lsapi_siguser1( int sig )
- {
- g_running = 0;
- }
- #ifndef sighandler_t
- typedef void (*sighandler_t)(int);
- #endif
- static void lsapi_signal(int signo, sighandler_t handler)
- {
- struct sigaction sa;
- sigaction(signo, NULL, &sa);
- if (sa.sa_handler == SIG_DFL)
- {
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = handler;
- sigaction(signo, &sa, NULL);
- }
- }
- static int s_enable_core_dump = 0;
- static void lsapi_enable_core_dump(void)
- {
- #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
- || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- int mib[2];
- size_t len;
- #if !defined(__OpenBSD__)
- len = 2;
- if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
- {
- len = sizeof(s_enable_core_dump);
- if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
- perror( "sysctl: Failed to set 'kern.sugid_coredump', "
- "core dump may not be available!");
- }
- #else
- int set = 3;
- len = sizeof(set);
- mib[0] = CTL_KERN;
- mib[1] = KERN_NOSUIDCOREDUMP;
- if (sysctl(mib, 2, NULL, 0, &set, len) == 0) {
- s_enable_core_dump = 1;
- }
- #endif
- #endif
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
- perror( "prctl: Failed to set dumpable, "
- "core dump may not be available!");
- #endif
- }
- static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
- char type, int len )
- {
- pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */
- pHeader->m_versionB1 = LSAPI_VERSION_B1;
- pHeader->m_type = type;
- pHeader->m_flag = LSAPI_ENDIAN;
- pHeader->m_packetLen.m_iLen = len;
- }
- static int lsapi_set_nblock( int fd, int nonblock )
- {
- int val = fcntl( fd, F_GETFL, 0 );
- if ( nonblock )
- {
- if (!( val & O_NONBLOCK ))
- {
- return fcntl( fd, F_SETFL, val | O_NONBLOCK );
- }
- }
- else
- {
- if ( val & O_NONBLOCK )
- {
- return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
- }
- }
- return 0;
- }
- static int lsapi_close( int fd )
- {
- int ret;
- while( 1 )
- {
- ret = close( fd );
- if (( ret == -1 )&&( errno == EINTR )&&(g_running))
- continue;
- return ret;
- }
- }
- static void lsapi_close_connection(LSAPI_Request *pReq)
- {
- if (pReq->m_fd == -1)
- return;
- lsapi_close(pReq->m_fd);
- pReq->m_fd = -1;
- if (s_busy_workers)
- __sync_fetch_and_sub(s_busy_workers, 1);
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
- }
- static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
- {
- ssize_t ret;
- while( 1 )
- {
- ret = read( fd, (char *)pBuf, len );
- if (( ret == -1 )&&( errno == EINTR )&&(g_running))
- continue;
- return ret;
- }
- }
- /*
- static int lsapi_write( int fd, const void * pBuf, int len )
- {
- int ret;
- const char * pCur;
- const char * pEnd;
- if ( len == 0 )
- return 0;
- pCur = (const char *)pBuf;
- pEnd = pCur + len;
- while( g_running && (pCur < pEnd) )
- {
- ret = write( fd, pCur, pEnd - pCur );
- if ( ret >= 0)
- pCur += ret;
- else if (( ret == -1 )&&( errno != EINTR ))
- return ret;
- }
- return pCur - (const char *)pBuf;
- }
- */
- static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
- {
- int ret;
- int left = totalLen;
- int n = count;
- if (s_skip_write)
- return totalLen;
- while(( left > 0 )&&g_running )
- {
- ret = writev( fd, *pVec, n );
- if ( ret > 0 )
- {
- left -= ret;
- if (( left <= 0)||( !g_running ))
- return totalLen - left;
- while( ret > 0 )
- {
- if ( (*pVec)->iov_len <= (unsigned int )ret )
- {
- ret -= (*pVec)->iov_len;
- ++(*pVec);
- }
- else
- {
- (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
- (*pVec)->iov_len -= ret;
- break;
- }
- }
- }
- else if ( ret == -1 )
- {
- if ( errno == EAGAIN )
- {
- if ( totalLen - left > 0 )
- return totalLen - left;
- else
- return -1;
- }
- else if ( errno != EINTR )
- return ret;
- }
- }
- return totalLen - left;
- }
- /*
- static int getTotalLen( struct iovec * pVec, int count )
- {
- struct iovec * pEnd = pVec + count;
- int total = 0;
- while( pVec < pEnd )
- {
- total += pVec->iov_len;
- ++pVec;
- }
- return total;
- }
- */
- static inline int allocateBuf( LSAPI_Request * pReq, int size )
- {
- char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
- if ( pBuf )
- {
- pReq->m_pReqBuf = pBuf;
- pReq->m_reqBufSize = size;
- pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
- return 0;
- }
- return -1;
- }
- static int allocateIovec( LSAPI_Request * pReq, int n )
- {
- struct iovec * p = (struct iovec *)realloc(
- pReq->m_pIovec, sizeof(struct iovec) * n );
- if ( !p )
- return -1;
- pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
- pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
- pReq->m_pIovec = p;
- pReq->m_pIovecEnd = p + n;
- return 0;
- }
- static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
- {
- char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
- if ( !p )
- return -1;
- pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
- pReq->m_pRespHeaderBuf = p;
- pReq->m_pRespHeaderBufEnd = p + size;
- return 0;
- }
- static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
- {
- if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
- ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
- ( pktType != pHeader->m_type ))
- return -1;
- if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
- {
- register char b;
- b = pHeader->m_packetLen.m_bytes[0];
- pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
- pHeader->m_packetLen.m_bytes[3] = b;
- b = pHeader->m_packetLen.m_bytes[1];
- pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
- pHeader->m_packetLen.m_bytes[2] = b;
- }
- return pHeader->m_packetLen.m_iLen;
- }
- static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
- int *curSize, int newSize )
- {
- struct LSAPI_key_value_pair * pBuf;
- if ( *curSize >= newSize )
- return 0;
- if ( newSize > 8192 )
- return -1;
- pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
- sizeof(struct LSAPI_key_value_pair) );
- if ( pBuf )
- {
- *pEnvList = pBuf;
- *curSize = newSize;
- return 0;
- }
- else
- return -1;
- }
- static inline int isPipe( int fd )
- {
- char achPeer[128];
- socklen_t len = 128;
- if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
- ( errno == ENOTCONN ))
- return 0;
- else
- return 1;
- }
- static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
- char **pBegin, char * pEnd )
- {
- struct LSAPI_key_value_pair * pEnvEnd;
- int keyLen = 0, valLen = 0;
- if ( count > 8192 )
- return -1;
- pEnvEnd = pEnvList + count;
- while( pEnvList != pEnvEnd )
- {
- if ( pEnd - *pBegin < 4 )
- return -1;
- keyLen = *((unsigned char *)((*pBegin)++));
- keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
- valLen = *((unsigned char *)((*pBegin)++));
- valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
- if ( *pBegin + keyLen + valLen > pEnd )
- return -1;
- if (( !keyLen )||( !valLen ))
- return -1;
- pEnvList->pKey = *pBegin;
- *pBegin += keyLen;
- pEnvList->pValue = *pBegin;
- *pBegin += valLen;
- pEnvList->keyLen = keyLen - 1;
- pEnvList->valLen = valLen - 1;
- ++pEnvList;
- }
- if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
- return -1;
- *pBegin += 4;
- return 0;
- }
- static inline void swapIntEndian( int * pInteger )
- {
- char * p = (char *)pInteger;
- register char b;
- b = p[0];
- p[0] = p[3];
- p[3] = b;
- b = p[1];
- p[1] = p[2];
- p[2] = b;
- }
- static inline void fixEndian( LSAPI_Request * pReq )
- {
- struct lsapi_req_header *p= pReq->m_pHeader;
- swapIntEndian( &p->m_httpHeaderLen );
- swapIntEndian( &p->m_reqBodyLen );
- swapIntEndian( &p->m_scriptFileOff );
- swapIntEndian( &p->m_scriptNameOff );
- swapIntEndian( &p->m_queryStringOff );
- swapIntEndian( &p->m_requestMethodOff );
- swapIntEndian( &p->m_cntUnknownHeaders );
- swapIntEndian( &p->m_cntEnv );
- swapIntEndian( &p->m_cntSpecialEnv );
- }
- static void fixHeaderIndexEndian( LSAPI_Request * pReq )
- {
- int i;
- for( i = 0; i < H_TRANSFER_ENCODING; ++i )
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- register char b;
- char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
- b = p[0];
- p[0] = p[1];
- p[1] = b;
- swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
- }
- }
- if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
- {
- struct lsapi_header_offset * pCur, *pEnd;
- pCur = pReq->m_pUnknownHeader;
- pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd )
- {
- swapIntEndian( &pCur->nameOff );
- swapIntEndian( &pCur->nameLen );
- swapIntEndian( &pCur->valueOff );
- swapIntEndian( &pCur->valueLen );
- ++pCur;
- }
- }
- }
- static int validateHeaders( LSAPI_Request * pReq )
- {
- int totalLen = pReq->m_pHeader->m_httpHeaderLen;
- int i;
- for(i = 0; i < H_TRANSFER_ENCODING; ++i)
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
- || pReq->m_pHeaderIndex->m_headerLen[i]
- + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
- return -1;
- }
- }
- if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
- {
- struct lsapi_header_offset * pCur, *pEnd;
- pCur = pReq->m_pUnknownHeader;
- pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd )
- {
- if (pCur->nameOff > totalLen
- || pCur->nameOff + pCur->nameLen > totalLen
- || pCur->valueOff > totalLen
- || pCur->valueOff + pCur->valueLen > totalLen)
- return -1;
- ++pCur;
- }
- }
- return 0;
- }
- static uid_t s_uid = 0;
- static uid_t s_defaultUid; //web server need set this
- static gid_t s_defaultGid;
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- #define LSAPI_LVE_DISABLED 0
- #define LSAPI_LVE_ENABLED 1
- #define LSAPI_CAGEFS_ENABLED 2
- #define LSAPI_CAGEFS_NO_SUEXEC 3
- struct liblve;
- static int s_enable_lve = LSAPI_LVE_DISABLED;
- static struct liblve * s_lve = NULL;
- static void *s_liblve;
- static int (*fp_lve_is_available)(void) = NULL;
- static int (*fp_lve_instance_init)(struct liblve *) = NULL;
- static int (*fp_lve_destroy)(struct liblve *) = NULL;
- static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
- static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
- static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
- static int lsapi_load_lve_lib(void)
- {
- s_liblve = DL_LOAD("liblve.so.0");
- if (s_liblve)
- {
- fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
- if (dlerror() == NULL)
- {
- if ( !(*fp_lve_is_available)() )
- {
- int uid = getuid();
- if ( uid )
- {
- if (setreuid( s_uid, uid )) {};
- if ( !(*fp_lve_is_available)() )
- s_enable_lve = 0;
- if (setreuid( uid, s_uid )) {};
- }
- }
- }
- }
- else
- {
- s_enable_lve = LSAPI_LVE_DISABLED;
- }
- return (s_liblve)? 0 : -1;
- }
- static int init_lve_ex(void)
- {
- int rc;
- if ( !s_liblve )
- return -1;
- fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
- fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
- fp_lve_enter = dlsym(s_liblve, "lve_enter");
- fp_lve_leave = dlsym(s_liblve, "lve_leave");
- if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
- fp_lve_jail = dlsym(s_liblve, "jail" );
- if ( s_lve == NULL )
- {
- rc = (*fp_lve_instance_init)(NULL);
- s_lve = malloc(rc);
- }
- rc = (*fp_lve_instance_init)(s_lve);
- if (rc != 0)
- {
- perror( "LSAPI: Unable to initialize LVE" );
- free( s_lve );
- s_lve = NULL;
- return -1;
- }
- return 0;
- }
- #endif
- static int readSecret( const char * pSecretFile )
- {
- struct stat st;
- int fd = open( pSecretFile, O_RDONLY , 0600 );
- if ( fd == -1 )
- {
- lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
- return -1;
- }
- if ( fstat( fd, &st ) == -1 )
- {
- lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
- close( fd );
- return -1;
- }
- /*
- if ( st.st_uid != s_uid )
- {
- lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
- close( fd );
- return -1;
- }
- */
- if ( st.st_mode & 0077 )
- {
- lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
- close( fd );
- return -1;
- }
- if ( read( fd, s_secret, 16 ) < 16 )
- {
- lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
- close( fd );
- return -1;
- }
- close( fd );
- return 0;
- }
- int LSAPI_is_suEXEC_Daemon(void)
- {
- if (( !s_uid )&&( s_secret[0] ))
- return 1;
- else
- return 0;
- }
- static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
- {
- char achError[4096];
- int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n",
- getuid(), getpid(),
- pErr1, (pErr2)?pErr2:"", strerror(errno));
- if (n > (int)sizeof(achError))
- n = sizeof(achError);
- if ( pReq )
- LSAPI_Write_Stderr_r( pReq, achError, n );
- else
- if (write( STDERR_FILENO, achError, n )) {};
- return 0;
- }
- static int lsapi_lve_error( LSAPI_Request * pReq )
- {
- static const char * headers[] =
- {
- "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
- "Pragma: no-cache",
- "Retry-After: 60",
- "Content-Type: text/html",
- NULL
- };
- static const char achBody[] =
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
- "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
- "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
- "The website is temporarily unable to service your request as it exceeded resource limit.\n"
- "Please try again later.\n"
- "<HR>\n"
- "</BODY></HTML>\n";
- LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
- return 0;
- }
- static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
- {
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- if ( s_lve && uid ) //root user should not do that
- {
- uint32_t cookie;
- int ret = -1;
- ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
- if ( ret < 0 )
- {
- //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret );
- LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
- lsapi_lve_error( pReq );
- return -1;
- }
- }
- #endif
- return 0;
- }
- static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
- {
- int ret = 0;
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- char error_msg[1024] = "";
- ret = (*fp_lve_jail)( pw, error_msg );
- if ( ret < 0 )
- {
- lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n",
- uid, ret, error_msg );
- LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
- return -1;
- }
- #endif
- return ret;
- }
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- static int lsapi_initLVE(void)
- {
- const char * pEnv;
- if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
- {
- s_enable_lve = atol( pEnv );
- pEnv = NULL;
- }
- else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
- {
- s_enable_lve = atol( pEnv );
- pEnv = NULL;
- }
- if ( s_enable_lve && !s_uid )
- {
- lsapi_load_lve_lib();
- if ( s_enable_lve )
- {
- return init_lve_ex();
- }
- }
- return 0;
- }
- #endif
- static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
- {
- int rv;
- struct passwd * pw;
- pw = getpwuid( uid );
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- if ( s_lve )
- {
- if( lsapi_enterLVE( pReq, uid ) == -1 )
- return -1;
- if ( pw && fp_lve_jail)
- {
- rv = lsapi_jailLVE( pReq, uid, pw );
- if ( rv == -1 )
- return -1;
- if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC
- {
- uid = s_defaultUid;
- gid = s_defaultGid;
- pw = getpwuid( uid );
- }
- }
- }
- #endif
- //if ( !uid || !gid ) //do not allow root
- //{
- // return -1;
- //}
- #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
- || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- if ( s_enable_core_dump )
- lsapi_enable_core_dump();
- #endif
- rv = setgid(gid);
- if (rv == -1)
- {
- LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
- return -1;
- }
- if ( pw && (pw->pw_gid == gid ))
- {
- rv = initgroups( pw->pw_name, gid );
- if (rv == -1)
- {
- LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
- return -1;
- }
- }
- else
- {
- rv = setgroups(1, &gid);
- if (rv == -1)
- {
- LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
- }
- }
- if ( pChroot )
- {
- rv = chroot( pChroot );
- if ( rv == -1 )
- {
- LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
- return -1;
- }
- }
- rv = setuid(uid);
- if (rv == -1)
- {
- LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
- return -1;
- }
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- if ( s_enable_core_dump )
- lsapi_enable_core_dump();
- #endif
- return 0;
- }
- static int lsapi_suexec_auth( LSAPI_Request *pReq,
- char * pAuth, int len, char * pUgid, int ugidLen )
- {
- lsapi_MD5_CTX md5ctx;
- unsigned char achMD5[16];
- if ( len < 32 )
- return -1;
- memmove( achMD5, pAuth + 16, 16 );
- memmove( pAuth + 16, s_secret, 16 );
- lsapi_MD5Init( &md5ctx );
- lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
- lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
- lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
- if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
- return 0;
- return 1;
- }
- static int lsapi_changeUGid( LSAPI_Request * pReq )
- {
- int uid = s_defaultUid;
- int gid = s_defaultGid;
- const char *pStderrLog;
- const char *pChroot = NULL;
- struct LSAPI_key_value_pair * pEnv;
- struct LSAPI_key_value_pair * pAuth;
- int i;
- if ( s_uid )
- return 0;
- //with special ID 0x00
- //authenticate the suEXEC request;
- //first one should be MD5( nonce + lscgid secret )
- //remember to clear the secret after verification
- //it should be set at the end of special env
- i = pReq->m_pHeader->m_cntSpecialEnv - 1;
- if ( i >= 0 )
- {
- pEnv = pReq->m_pSpecialEnvList + i;
- if (( *pEnv->pKey == '\000' )&&
- ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
- {
- --pReq->m_pHeader->m_cntSpecialEnv;
- pAuth = pEnv--;
- if (( *pEnv->pKey == '\000' )&&
- ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
- {
- --pReq->m_pHeader->m_cntSpecialEnv;
- uid = *(uint32_t *)pEnv->pValue;
- gid = *(((uint32_t *)pEnv->pValue) + 1 );
- //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
- }
- else
- {
- lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
- pEnv = NULL;
- }
- if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
- {
- //read UID, GID from specialEnv
- }
- else
- {
- //authentication error
- lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
- uid = 0;
- }
- }
- else
- {
- //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
- }
- }
- if ( !uid )
- {
- uid = s_defaultUid;
- gid = s_defaultGid;
- }
- //change uid
- if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
- {
- return -1;
- }
- s_uid = uid;
- if ( pReq->m_fdListen != -1 )
- {
- close( pReq->m_fdListen );
- pReq->m_fdListen = -1;
- }
- pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
- if (pStderrLog)
- lsapi_reopen_stderr(pStderrLog);
- return 0;
- }
- static int parseContentLenFromHeader(LSAPI_Request * pReq)
- {
- const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
- if ( pContentLen )
- pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
- return 0;
- }
- static int parseRequest( LSAPI_Request * pReq, int totalLen )
- {
- int shouldFixEndian;
- char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
- char * pEnd = pReq->m_pReqBuf + totalLen;
- shouldFixEndian = ( LSAPI_ENDIAN != (
- pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
- if ( shouldFixEndian )
- {
- fixEndian( pReq );
- }
- if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
- allocateEnvList( &pReq->m_pSpecialEnvList,
- &pReq->m_specialEnvListSize,
- pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
- return -1;
- if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
- allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
- pReq->m_pHeader->m_cntEnv ) == -1 )
- return -1;
- if ( parseEnv( pReq->m_pSpecialEnvList,
- pReq->m_pHeader->m_cntSpecialEnv,
- &pBegin, pEnd ) == -1 )
- return -1;
- if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
- &pBegin, pEnd ) == -1 )
- return -1;
- if (pReq->m_pHeader->m_scriptFileOff < 0
- || pReq->m_pHeader->m_scriptFileOff >= totalLen
- || pReq->m_pHeader->m_scriptNameOff < 0
- || pReq->m_pHeader->m_scriptNameOff >= totalLen
- || pReq->m_pHeader->m_queryStringOff < 0
- || pReq->m_pHeader->m_queryStringOff >= totalLen
- || pReq->m_pHeader->m_requestMethodOff < 0
- || pReq->m_pHeader->m_requestMethodOff >= totalLen)
- {
- lsapi_log("Bad request header - ERROR#1\n");
- return -1;
- }
- pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
- pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
- pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
- pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
- pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
- pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
- pBegin += sizeof( struct lsapi_http_header_index );
- pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
- pBegin += sizeof( struct lsapi_header_offset) *
- pReq->m_pHeader->m_cntUnknownHeaders;
- pReq->m_pHttpHeader = pBegin;
- pBegin += pReq->m_pHeader->m_httpHeaderLen;
- if ( pBegin != pEnd )
- {
- lsapi_log("Request header does match total size, total: %d, "
- "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
- return -1;
- }
- if ( shouldFixEndian )
- {
- fixHeaderIndexEndian( pReq );
- }
- if (validateHeaders(pReq) == -1)
- {
- lsapi_log("Bad request header - ERROR#2\n");
- return -1;
- }
- pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
- if ( pReq->m_reqBodyLen == -2 )
- {
- parseContentLenFromHeader(pReq);
- }
- return 0;
- }
- //OPTIMIZATION
- static char s_accept_notify = 0;
- static char s_schedule_notify = 0;
- static char s_notify_scheduled = 0;
- static char s_notified_pid = 0;
- static struct lsapi_packet_header s_ack = {'L', 'S',
- LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
- static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
- LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
- static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
- {
- if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
- return -1;
- return 0;
- }
- static inline int send_req_received_notification( int fd )
- {
- return send_notification_pkt(fd, &s_ack);
- }
- static inline int send_conn_close_notification( int fd )
- {
- return send_notification_pkt(fd, &s_conn_close_pkt);
- }
- //static void lsapi_sigalarm( int sig )
- //{
- // if ( s_notify_scheduled )
- // {
- // s_notify_scheduled = 0;
- // if ( g_req.m_fd != -1 )
- // write_req_received_notification( g_req.m_fd );
- // }
- //}
- static inline int lsapi_schedule_notify(void)
- {
- if ( !s_notify_scheduled )
- {
- alarm( 2 );
- s_notify_scheduled = 1;
- }
- return 0;
- }
- static inline int notify_req_received( int fd )
- {
- if ( s_schedule_notify )
- return lsapi_schedule_notify();
- return send_req_received_notification( fd );
- }
- static inline int lsapi_notify_pid( int fd )
- {
- char achBuf[16];
- lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
- 8 + LSAPI_PACKET_HEADER_LEN );
- memmove( &achBuf[8], "\0PID", 4 );
- *((int *)&achBuf[12]) = getpid();
- if ( write( fd, achBuf, 16 ) < 16 )
- return -1;
- return 0;
- }
- static char s_conn_key_packet[16];
- static inline int init_conn_key( int fd )
- {
- struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
- struct timeval tv;
- int i;
- gettimeofday( &tv, NULL );
- srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
- for( i = 8; i < 16; ++i )
- {
- s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
- }
- lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
- 8 + LSAPI_PACKET_HEADER_LEN );
- if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
- < LSAPI_PACKET_HEADER_LEN+8 )
- return -1;
- return 0;
- }
- static int readReq( LSAPI_Request * pReq )
- {
- int len;
- int packetLen;
- if ( !pReq )
- return -1;
- if ( pReq->m_reqBufSize < 8192 )
- {
- if ( allocateBuf( pReq, 8192 ) == -1 )
- return -1;
- }
- while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
- {
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
- if ( len <= 0 )
- return -1;
- pReq->m_bufRead += len;
- }
- pReq->m_reqState = LSAPI_ST_REQ_HEADER;
- packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
- if ( packetLen < 0 )
- {
- lsapi_log("packetLen < 0\n");
- return -1;
- }
- if ( packetLen > LSAPI_MAX_HEADER_LEN )
- {
- lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
- return -1;
- }
- if ( packetLen + 1024 > pReq->m_reqBufSize )
- {
- if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
- return -1;
- }
- while( packetLen > pReq->m_bufRead )
- {
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
- if ( len <= 0 )
- return -1;
- pReq->m_bufRead += len;
- }
- if ( parseRequest( pReq, packetLen ) < 0 )
- {
- lsapi_log("ParseRequest error\n");
- return -1;
- }
- pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
- if ( !s_uid )
- {
- if ( lsapi_changeUGid( pReq ) )
- return -1;
- memset(s_secret, 0, sizeof(s_secret));
- }
- pReq->m_bufProcessed = packetLen;
- //OPTIMIZATION
- if ( !s_accept_notify && !s_notified_pid )
- return notify_req_received( pReq->m_fd );
- else
- {
- s_notified_pid = 0;
- return 0;
- }
- }
- int LSAPI_Init(void)
- {
- if ( !g_inited )
- {
- s_uid = geteuid();
- s_secret[0] = 0;
- lsapi_signal(SIGPIPE, lsapi_sigpipe);
- lsapi_signal(SIGUSR1, lsapi_siguser1);
- #if defined(SIGXFSZ) && defined(SIG_IGN)
- signal(SIGXFSZ, SIG_IGN);
- #endif
- /* let STDOUT function as STDERR,
- just in case writing to STDOUT directly */
- dup2( 2, 1 );
- if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
- return -1;
- g_inited = 1;
- s_ppid = getppid();
- void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
- if (pthread_lib)
- pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
- }
- return 0;
- }
- void LSAPI_Stop(void)
- {
- g_running = 0;
- }
- int LSAPI_IsRunning(void)
- {
- return g_running;
- }
- void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
- {
- s_proc_group_timer_cb = cb;
- }
- int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
- {
- int newfd;
- if ( !pReq )
- return -1;
- memset( pReq, 0, sizeof( LSAPI_Request ) );
- if ( allocateIovec( pReq, 16 ) == -1 )
- return -1;
- pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
- if ( !pReq->m_pRespBuf )
- return -1;
- pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
- pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
- if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
- return -1;
- if ( fd == STDIN_FILENO )
- {
- fd = dup( fd );
- newfd = open( "/dev/null", O_RDWR );
- dup2( newfd, STDIN_FILENO );
- }
- if ( isPipe( fd ) )
- {
- pReq->m_fdListen = -1;
- pReq->m_fd = fd;
- }
- else
- {
- pReq->m_fdListen = fd;
- pReq->m_fd = -1;
- lsapi_set_nblock( fd, 1 );
- }
- return 0;
- }
- int LSAPI_Is_Listen( void )
- {
- return LSAPI_Is_Listen_r( &g_req );
- }
- int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
- {
- return pReq->m_fdListen != -1;
- }
- int LSAPI_Accept_r( LSAPI_Request * pReq )
- {
- char achPeer[128];
- socklen_t len;
- int nodelay = 1;
- if ( !pReq )
- return -1;
- if ( LSAPI_Finish_r( pReq ) == -1 )
- return -1;
- lsapi_set_nblock( pReq->m_fdListen , 0 );
- while( g_running )
- {
- if ( pReq->m_fd == -1 )
- {
- if ( pReq->m_fdListen != -1)
- {
- len = sizeof( achPeer );
- pReq->m_fd = accept( pReq->m_fdListen,
- (struct sockaddr *)&achPeer, &len );
- if ( pReq->m_fd == -1 )
- {
- if (( errno == EINTR )||( errno == EAGAIN))
- continue;
- else
- return -1;
- }
- else
- {
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_CONNECTED);
- if (s_busy_workers)
- __sync_fetch_and_add(s_busy_workers, 1);
- lsapi_set_nblock( pReq->m_fd , 0 );
- if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
- {
- setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&nodelay, sizeof(nodelay));
- }
- //init_conn_key( pReq->m_fd );
- //OPTIMIZATION
- if ( s_accept_notify )
- if ( notify_req_received( pReq->m_fd ) == -1 )
- return -1;
- }
- }
- else
- return -1;
- }
- if ( !readReq( pReq ) )
- break;
- //abort();
- lsapi_close_connection(pReq);
- LSAPI_Reset_r( pReq );
- }
- return 0;
- }
- static struct lsapi_packet_header finish_close[2] =
- {
- {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
- {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
- };
- int LSAPI_Finish_r( LSAPI_Request * pReq )
- {
- /* finish req body */
- if ( !pReq )
- return -1;
- if (pReq->m_reqState)
- {
- if ( pReq->m_fd != -1 )
- {
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- LSAPI_FinalizeRespHeaders_r( pReq );
- }
- if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
- {
- Flush_RespBuf_r( pReq );
- }
- pReq->m_pIovecCur->iov_base = (void *)finish_close;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
- pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
- ++pReq->m_pIovecCur;
- LSAPI_Flush_r( pReq );
- }
- LSAPI_Reset_r( pReq );
- }
- return 0;
- }
- int LSAPI_End_Response_r(LSAPI_Request * pReq)
- {
- if (!pReq)
- return -1;
- if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
- return 0;
- if (pReq->m_reqState)
- {
- if ( pReq->m_fd != -1 )
- {
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
- return 0;
- LSAPI_FinalizeRespHeaders_r( pReq );
- }
- if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
- {
- Flush_RespBuf_r( pReq );
- }
- pReq->m_pIovecCur->iov_base = (void *)finish_close;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1;
- pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
- ++pReq->m_pIovecCur;
- LSAPI_Flush_r( pReq );
- lsapi_close_connection(pReq);
- }
- pReq->m_reqState |= LSAPI_ST_BACKGROUND;
- }
- return 0;
- }
- void LSAPI_Reset_r( LSAPI_Request * pReq )
- {
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
- pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
- memset( &pReq->m_pHeaderIndex, 0,
- (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
- }
- int LSAPI_Release_r( LSAPI_Request * pReq )
- {
- if ( pReq->m_pReqBuf )
- free( pReq->m_pReqBuf );
- if ( pReq->m_pSpecialEnvList )
- free( pReq->m_pSpecialEnvList );
- if ( pReq->m_pEnvList )
- free( pReq->m_pEnvList );
- if ( pReq->m_pRespHeaderBuf )
- free( pReq->m_pRespHeaderBuf );
- return 0;
- }
- char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
- {
- int off;
- if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
- return NULL;
- off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
- if ( !off )
- return NULL;
- if ( *(pReq->m_pHttpHeader + off
- + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
- {
- *( pReq->m_pHttpHeader + off
- + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
- }
- return pReq->m_pHttpHeader + off;
- }
- static int readBodyToReqBuf( LSAPI_Request * pReq )
- {
- off_t bodyLeft;
- ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
- if ( len > 0 )
- return len;
- pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
- bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
- len = pReq->m_reqBufSize - pReq->m_bufRead;
- if ( len < 0 )
- return -1;
- if ( len > bodyLeft )
- len = bodyLeft;
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
- if ( len > 0 )
- pReq->m_bufRead += len;
- return len;
- }
- int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
- {
- if (!pReq || (pReq->m_fd ==-1) )
- return EOF;
- if ( pReq->m_bufProcessed >= pReq->m_bufRead )
- {
- if ( readBodyToReqBuf( pReq ) <= 0 )
- return EOF;
- }
- ++pReq->m_reqBodyRead;
- return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
- }
- int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
- {
- ssize_t len;
- ssize_t left;
- char * pBufEnd = pBuf + bufLen - 1;
- char * pBufCur = pBuf;
- char * pCur;
- char * p;
- if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
- return -1;
- *getLF = 0;
- while( (left = pBufEnd - pBufCur ) > 0 )
- {
- len = pReq->m_bufRead - pReq->m_bufProcessed;
- if ( len <= 0 )
- {
- if ( (len = readBodyToReqBuf( pReq )) <= 0 )
- {
- *getLF = 1;
- break;
- }
- }
- if ( len > left )
- len = left;
- pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
- p = memchr( pCur, '\n', len );
- if ( p )
- len = p - pCur + 1;
- memmove( pBufCur, pCur, len );
- pBufCur += len;
- pReq->m_bufProcessed += len;
- pReq->m_reqBodyRead += len;
- if ( p )
- {
- *getLF = 1;
- break;
- }
- }
- *pBufCur = 0;
- return pBufCur - pBuf;
- }
- ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
- {
- ssize_t len;
- off_t total;
- /* char *pOldBuf = pBuf; */
- if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
- return -1;
- total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
- if ( total <= 0 )
- return 0;
- if ( total < (ssize_t)bufLen )
- bufLen = total;
- total = 0;
- len = pReq->m_bufRead - pReq->m_bufProcessed;
- if ( len > 0 )
- {
- if ( len > (ssize_t)bufLen )
- len = bufLen;
- memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
- pReq->m_bufProcessed += len;
- total += len;
- pBuf += len;
- bufLen -= len;
- }
- while( bufLen > 0 )
- {
- len = lsapi_read( pReq->m_fd, pBuf, bufLen );
- if ( len > 0 )
- {
- total += len;
- pBuf += len;
- bufLen -= len;
- }
- else if ( len <= 0 )
- {
- if ( !total)
- return -1;
- break;
- }
- }
- pReq->m_reqBodyRead += total;
- return total;
- }
- ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
- {
- struct lsapi_packet_header * pHeader;
- const char * pEnd;
- const char * p;
- ssize_t bufLen;
- ssize_t toWrite;
- ssize_t packetLen;
- int skip = 0;
- if (!pReq || !pBuf)
- return -1;
- if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
- return len;
- if (pReq->m_fd == -1)
- return -1;
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- LSAPI_FinalizeRespHeaders_r( pReq );
- /*
- if ( *pBuf == '\r' )
- {
- ++skip;
- }
- if ( *pBuf == '\n' )
- {
- ++skip;
- }
- */
- }
- pReq->m_reqState |= LSAPI_ST_RESP_BODY;
- if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
- {
- memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
- pReq->m_pRespBufPos += len - skip;
- return len;
- }
- pHeader = pReq->m_respPktHeader;
- p = pBuf + skip;
- pEnd = pBuf + len;
- bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
- while( ( toWrite = pEnd - p ) > 0 )
- {
- packetLen = toWrite + bufLen;
- if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
- {
- packetLen = LSAPI_MAX_DATA_PACKET_LEN;
- toWrite = packetLen - bufLen;
- }
- lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
- packetLen + LSAPI_PACKET_HEADER_LEN );
- pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
- pReq->m_pIovecCur->iov_base = (void *)pHeader;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
- ++pReq->m_pIovecCur;
- ++pHeader;
- if ( bufLen > 0 )
- {
- pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
- pReq->m_pIovecCur->iov_len = bufLen;
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
- ++pReq->m_pIovecCur;
- bufLen = 0;
- }
- pReq->m_pIovecCur->iov_base = (void *)p;
- pReq->m_pIovecCur->iov_len = toWrite;
- ++pReq->m_pIovecCur;
- p += toWrite;
- if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
- {
- if ( LSAPI_Flush_r( pReq ) == -1 )
- return -1;
- pHeader = pReq->m_respPktHeader;
- }
- }
- if ( pHeader != pReq->m_respPktHeader )
- if ( LSAPI_Flush_r( pReq ) == -1 )
- return -1;
- return p - pBuf;
- }
- #if defined(__FreeBSD__ )
- ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
- {
- ssize_t ret;
- off_t written;
- ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
- if ( written > 0 )
- {
- ret = written;
- *off += ret;
- }
- return ret;
- }
- #endif
- #if defined(__OpenBSD__) || defined(__NetBSD__)
- ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
- {
- ssize_t ret;
- off_t written = 0;
- const size_t bufsiz = 16384;
- unsigned char in[bufsiz] = {0};
- if (lseek(fdIn, *off, SEEK_SET) == -1) {
- return -1;
- }
- while (size > 0) {
- size_t tor = size > sizeof(in) ? sizeof(in) : size;
- ssize_t c = read(fdIn, in, tor);
- if (c <= 0) {
- goto end;
- }
- ssize_t w = write(fdOut, in, c);
- if (w != c) {
- goto end;
- }
- written += w;
- size -= c;
- }
- end:
- *off += written;
- return 0;
- }
- #endif
- #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
- {
- ssize_t ret;
- off_t len = size;
- ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
- if (( ret == 0 )&&( len > 0 ))
- {
- ret = len;
- *off += len;
- }
- return ret;
- }
- #endif
- #if defined(sun) || defined(__sun)
- #include <sys/sendfile.h>
- ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
- {
- int n = 0 ;
- sendfilevec_t vec[1];
- vec[n].sfv_fd = fdIn;
- vec[n].sfv_flag = 0;
- vec[n].sfv_off = *off;
- vec[n].sfv_len = size;
- ++n;
- size_t written;
- ssize_t ret = sendfilev( fdOut, vec, n, &written );
- if (( !ret )||( errno == EAGAIN ))
- ret = written;
- if ( ret > 0 )
- *off += ret;
- return ret;
- }
- #endif
- #if defined(linux) || defined(__linux) || defined(__linux__) || \
- defined(__gnu_linux__)
- #include <sys/sendfile.h>
- #define gsendfile sendfile
- #endif
- #if defined(HPUX)
- ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
- {
- return sendfile( fdOut, fdIn, off, size, NULL, 0 );
- }
- #endif
- ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
- {
- struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
- if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
- return -1;
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- LSAPI_FinalizeRespHeaders_r( pReq );
- }
- pReq->m_reqState |= LSAPI_ST_RESP_BODY;
- LSAPI_Flush_r(pReq);
- lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
- size + LSAPI_PACKET_HEADER_LEN );
- if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
- return -1;
- return gsendfile( pReq->m_fd, fdIn, off, size );
- }
- void Flush_RespBuf_r( LSAPI_Request * pReq )
- {
- struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
- int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
- pReq->m_reqState |= LSAPI_ST_RESP_BODY;
- lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
- bufLen + LSAPI_PACKET_HEADER_LEN );
- pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
- pReq->m_pIovecCur->iov_base = (void *)pHeader;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
- ++pReq->m_pIovecCur;
- ++pHeader;
- if ( bufLen > 0 )
- {
- pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
- pReq->m_pIovecCur->iov_len = bufLen;
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
- ++pReq->m_pIovecCur;
- bufLen = 0;
- }
- }
- int LSAPI_Flush_r( LSAPI_Request * pReq )
- {
- int ret = 0;
- int n;
- if ( !pReq )
- return -1;
- n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
- if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
- return 0;
- if ( pReq->m_fd == -1 )
- {
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
- pReq->m_totalLen = 0;
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
- return -1;
- }
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- LSAPI_FinalizeRespHeaders_r( pReq );
- }
- if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
- {
- Flush_RespBuf_r( pReq );
- }
- n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
- if ( n > 0 )
- {
- ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
- n, pReq->m_totalLen );
- if ( ret < pReq->m_totalLen )
- {
- lsapi_close_connection(pReq);
- ret = -1;
- }
- pReq->m_totalLen = 0;
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
- }
- return ret;
- }
- ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
- {
- struct lsapi_packet_header header;
- const char * pEnd;
- const char * p;
- ssize_t packetLen;
- ssize_t totalLen;
- int ret;
- struct iovec iov[2];
- struct iovec *pIov;
- if ( !pReq )
- return -1;
- if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
- return write( 2, pBuf, len );
- if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
- {
- LSAPI_Flush_r( pReq );
- }
- p = pBuf;
- pEnd = pBuf + len;
- while( ( packetLen = pEnd - p ) > 0 )
- {
- if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
- {
- packetLen = LSAPI_MAX_DATA_PACKET_LEN;
- }
- lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
- packetLen + LSAPI_PACKET_HEADER_LEN );
- totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
- iov[0].iov_base = (void *)&header;
- iov[0].iov_len = LSAPI_PACKET_HEADER_LEN;
- iov[1].iov_base = (void *)p;
- iov[1].iov_len = packetLen;
- p += packetLen;
- pIov = iov;
- ret = lsapi_writev( pReq->m_fd, &pIov,
- 2, totalLen );
- if ( ret < totalLen )
- {
- lsapi_close_connection(pReq);
- ret = -1;
- }
- }
- return p - pBuf;
- }
- static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
- {
- int i;
- char * pValue;
- for( i = 0; i < H_TRANSFER_ENCODING; ++i )
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
- {
- pValue = pReq->m_pHttpHeader
- + pReq->m_pHeaderIndex->m_headerOff[i];
- if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
- {
- *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
- }
- return pValue;
- }
- }
- }
- if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
- {
- const char *p;
- char *pKey;
- char *pKeyEnd;
- int keyLen;
- struct lsapi_header_offset * pCur, *pEnd;
- pCur = pReq->m_pUnknownHeader;
- pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd )
- {
- pKey = pReq->m_pHttpHeader + pCur->nameOff;
- keyLen = pCur->nameLen;
- pKeyEnd = pKey + keyLen;
- p = &name[5];
- while(( pKey < pKeyEnd )&&( *p ))
- {
- char ch = toupper( *pKey );
- if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
- break;
- ++p; ++pKey;
- }
- if (( pKey == pKeyEnd )&& (!*p ))
- {
- pValue = pReq->m_pHttpHeader + pCur->valueOff;
- if ( *(pValue + pCur->valueLen) != '\0')
- {
- *(pValue + pCur->valueLen) = '\0';
- }
- return pValue;
- }
- ++pCur;
- }
- }
- return NULL;
- }
- char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
- {
- struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
- struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
- if ( !pReq || !name )
- return NULL;
- if ( strncmp( name, "HTTP_", 5 ) == 0 )
- {
- return GetHeaderVar( pReq, name );
- }
- while( pBegin < pEnd )
- {
- if ( strcmp( name, pBegin->pKey ) == 0 )
- return pBegin->pValue;
- ++pBegin;
- }
- return NULL;
- }
- struct _headerInfo
- {
- const char * _name;
- int _nameLen;
- const char * _value;
- int _valueLen;
- };
- int compareValueLocation(const void * v1, const void *v2 )
- {
- return ((const struct _headerInfo *)v1)->_value -
- ((const struct _headerInfo *)v2)->_value;
- }
- int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
- LSAPI_CB_EnvHandler fn, void * arg )
- {
- int i;
- int len = 0;
- char * pValue;
- int ret;
- int count = 0;
- struct _headerInfo headers[512];
- if ( !pReq || !fn )
- return -1;
- if ( !pReq->m_pHeaderIndex )
- return 0;
- for( i = 0; i < H_TRANSFER_ENCODING; ++i )
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- len = pReq->m_pHeaderIndex->m_headerLen[i];
- pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
- *(pValue + len ) = 0;
- headers[count]._name = HTTP_HEADERS[i];
- headers[count]._nameLen = HTTP_HEADER_LEN[i];
- headers[count]._value = pValue;
- headers[count]._valueLen = len;
- ++count;
- //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
- // pValue, len, arg );
- //if ( ret <= 0 )
- // return ret;
- }
- }
- if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
- {
- char *pKey;
- int keyLen;
- struct lsapi_header_offset * pCur, *pEnd;
- pCur = pReq->m_pUnknownHeader;
- pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd )
- {
- pKey = pReq->m_pHttpHeader + pCur->nameOff;
- keyLen = pCur->nameLen;
- *(pKey + keyLen ) = 0;
- pValue = pReq->m_pHttpHeader + pCur->valueOff;
- *(pValue + pCur->valueLen ) = 0;
- headers[count]._name = pKey;
- headers[count]._nameLen = keyLen;
- headers[count]._value = pValue;
- headers[count]._valueLen = pCur->valueLen;
- ++count;
- if ( count == 512 )
- break;
- //ret = (*fn)( pKey, keyLen,
- // pValue, pCur->valueLen, arg );
- //if ( ret <= 0 )
- // return ret;
- ++pCur;
- }
- }
- qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
- for( i = 0; i < count; ++i )
- {
- ret = (*fn)( headers[i]._name, headers[i]._nameLen,
- headers[i]._value, headers[i]._valueLen, arg );
- if ( ret <= 0 )
- return ret;
- }
- return count;
- }
- int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
- LSAPI_CB_EnvHandler fn, void * arg )
- {
- int i;
- int len = 0;
- char * pValue;
- int ret;
- int count = 0;
- if ( !pReq || !fn )
- return -1;
- for( i = 0; i < H_TRANSFER_ENCODING; ++i )
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- len = pReq->m_pHeaderIndex->m_headerLen[i];
- pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
- *(pValue + len ) = 0;
- ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
- pValue, len, arg );
- ++count;
- if ( ret <= 0 )
- return ret;
- }
- }
- if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
- {
- char achHeaderName[256];
- char *p;
- char *pKey;
- char *pKeyEnd ;
- int keyLen;
- struct lsapi_header_offset * pCur, *pEnd;
- pCur = pReq->m_pUnknownHeader;
- pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
- while( pCur < pEnd )
- {
- pKey = pReq->m_pHttpHeader + pCur->nameOff;
- keyLen = pCur->nameLen;
- if ( keyLen > 250 )
- keyLen = 250;
- pKeyEnd = pKey + keyLen;
- memcpy( achHeaderName, "HTTP_", 5 );
- p = &achHeaderName[5];
- while( pKey < pKeyEnd )
- {
- char ch = *pKey++;
- if ( ch == '-' )
- *p++ = '_';
- else
- *p++ = toupper( ch );
- }
- *p = 0;
- keyLen += 5;
- pValue = pReq->m_pHttpHeader + pCur->valueOff;
- *(pValue + pCur->valueLen ) = 0;
- ret = (*fn)( achHeaderName, keyLen,
- pValue, pCur->valueLen, arg );
- if ( ret <= 0 )
- return ret;
- ++pCur;
- }
- }
- return count + pReq->m_pHeader->m_cntUnknownHeaders;
- }
- static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
- int n, LSAPI_CB_EnvHandler fn, void * arg )
- {
- struct LSAPI_key_value_pair * pEnd = pEnv + n;
- int ret;
- if ( !pEnv || !fn )
- return -1;
- while( pEnv < pEnd )
- {
- ret = (*fn)( pEnv->pKey, pEnv->keyLen,
- pEnv->pValue, pEnv->valLen, arg );
- if ( ret <= 0 )
- return ret;
- ++pEnv;
- }
- return n;
- }
- int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
- LSAPI_CB_EnvHandler fn, void * arg )
- {
- if ( !pReq || !fn )
- return -1;
- if ( pReq->m_pHeader->m_cntEnv > 0 )
- {
- return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
- fn, arg );
- }
- return 0;
- }
- int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
- LSAPI_CB_EnvHandler fn, void * arg )
- {
- if ( !pReq || !fn )
- return -1;
- if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
- {
- return EnvForeach( pReq->m_pSpecialEnvList,
- pReq->m_pHeader->m_cntSpecialEnv,
- fn, arg );
- }
- return 0;
- }
- int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
- {
- if ( !pReq || !pReq->m_pIovec )
- return -1;
- if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
- return 0;
- pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
- if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
- {
- pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
- pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
- pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
- ++pReq->m_pIovecCur;
- }
- pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
- + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
- pReq->m_totalLen += pReq->m_pIovec->iov_len;
- lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
- LSAPI_RESP_HEADER, pReq->m_totalLen );
- pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
- pReq->m_pIovecToWrite = pReq->m_pIovec;
- return 0;
- }
- int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
- const char * pHeaderValue )
- {
- int nameLen, valLen, len;
- if ( !pReq || !pHeaderName || !pHeaderValue )
- return -1;
- if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
- return -1;
- if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
- return -1;
- nameLen = strlen( pHeaderName );
- valLen = strlen( pHeaderValue );
- if ( nameLen == 0 )
- return -1;
- while( nameLen > 0 )
- {
- char ch = *(pHeaderName + nameLen - 1 );
- if (( ch == '\n' )||( ch == '\r' ))
- --nameLen;
- else
- break;
- }
- if ( nameLen <= 0 )
- return 0;
- while( valLen > 0 )
- {
- char ch = *(pHeaderValue + valLen - 1 );
- if (( ch == '\n' )||( ch == '\r' ))
- --valLen;
- else
- break;
- }
- len = nameLen + valLen + 1;
- if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
- return -1;
- if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
- {
- int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
- newlen -= newlen % 4096;
- if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
- return -1;
- }
- memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
- pReq->m_pRespHeaderBufPos += nameLen;
- *pReq->m_pRespHeaderBufPos++ = ':';
- memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
- pReq->m_pRespHeaderBufPos += valLen;
- *pReq->m_pRespHeaderBufPos++ = 0;
- ++len; /* add one byte padding for \0 */
- pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
- ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
- return 0;
- }
- int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
- {
- if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
- return -1;
- if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
- return -1;
- if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
- return -1;
- while( len > 0 )
- {
- char ch = *(pBuf + len - 1 );
- if (( ch == '\n' )||( ch == '\r' ))
- --len;
- else
- break;
- }
- if ( len <= 0 )
- return 0;
- if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
- {
- int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
- newlen -= newlen % 4096;
- if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
- return -1;
- }
- memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
- pReq->m_pRespHeaderBufPos += len;
- *pReq->m_pRespHeaderBufPos++ = 0;
- ++len; /* add one byte padding for \0 */
- pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
- ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
- return 0;
- }
- int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
- {
- int ret;
- int fd;
- int flag = 1;
- int addr_len;
- switch( pServerAddr->sa_family )
- {
- case AF_INET:
- addr_len = 16;
- break;
- case AF_INET6:
- addr_len = sizeof( struct sockaddr_in6 );
- break;
- case AF_UNIX:
- addr_len = sizeof( struct sockaddr_un );
- unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
- break;
- default:
- return -1;
- }
- fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
- if ( fd == -1 )
- return -1;
- fcntl( fd, F_SETFD, FD_CLOEXEC );
- if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)( &flag ), sizeof(flag)) == 0)
- {
- ret = bind( fd, pServerAddr, addr_len );
- if ( !ret )
- {
- ret = listen( fd, backlog );
- if ( !ret )
- return fd;
- }
- }
- ret = errno;
- close(fd);
- errno = ret;
- return -1;
- }
- int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
- {
- char achAddr[256];
- char * p = achAddr;
- char * pEnd;
- struct addrinfo *res, hints;
- int doAddrInfo = 0;
- int port;
- if ( !pBind )
- return -1;
- while( isspace( *pBind ) )
- ++pBind;
- strncpy(achAddr, pBind, 255);
- achAddr[255] = 0;
- switch( *p )
- {
- case '/':
- pAddr->sa_family = AF_UNIX;
- strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
- sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
- return 0;
- case '[':
- pAddr->sa_family = AF_INET6;
- ++p;
- pEnd = strchr( p, ']' );
- if ( !pEnd )
- return -1;
- *pEnd++ = 0;
- if ( *p == '*' )
- {
- strcpy( achAddr, "::" );
- p = achAddr;
- }
- doAddrInfo = 1;
- break;
- default:
- pAddr->sa_family = AF_INET;
- pEnd = strchr( p, ':' );
- if ( !pEnd )
- return -1;
- *pEnd++ = 0;
- doAddrInfo = 0;
- if ( *p == '*' )
- {
- ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
- }
- else if (!strcasecmp( p, "localhost" ) )
- ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
- else
- {
- #ifdef HAVE_INET_PTON
- if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr))
- #else
- ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
- if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
- #endif
- {
- doAddrInfo = 1;
- }
- }
- break;
- }
- if ( *pEnd == ':' )
- ++pEnd;
- port = atoi( pEnd );
- if (( port <= 0 )||( port > 65535 ))
- return -1;
- if ( doAddrInfo )
- {
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = pAddr->sa_family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- if ( getaddrinfo(p, NULL, &hints, &res) )
- {
- return -1;
- }
- memcpy(pAddr, res->ai_addr, res->ai_addrlen);
- freeaddrinfo(res);
- }
- if ( pAddr->sa_family == AF_INET )
- ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
- else
- ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
- return 0;
- }
- int LSAPI_CreateListenSock( const char * pBind, int backlog )
- {
- char serverAddr[128];
- int ret;
- int fd = -1;
- ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
- if ( !ret )
- {
- fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
- }
- return fd;
- }
- static fn_select_t g_fnSelect = select;
- typedef struct _lsapi_prefork_server
- {
- int m_fd;
- int m_iMaxChildren;
- int m_iExtraChildren;
- int m_iCurChildren;
- int m_iMaxIdleChildren;
- int m_iServerMaxIdle;
- int m_iChildrenMaxIdleTime;
- int m_iMaxReqProcessTime;
- int m_iAvoidFork;
- lsapi_child_status * m_pChildrenStatus;
- lsapi_child_status * m_pChildrenStatusCur;
- lsapi_child_status * m_pChildrenStatusEnd;
- }lsapi_prefork_server;
- static lsapi_prefork_server * g_prefork_server = NULL;
- int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
- {
- if ( g_prefork_server )
- return 0;
- if ( max_children <= 1 )
- return -1;
- if ( max_children >= 10000)
- max_children = 10000;
- if (s_max_busy_workers == 0)
- s_max_busy_workers = max_children / 2 + 1;
- g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
- if ( !g_prefork_server )
- return -1;
- memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
- if ( fp != NULL )
- g_fnSelect = fp;
- s_ppid = getppid();
- s_pid = getpid();
- setpgid( s_pid, s_pid );
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- s_total_pages = sysconf(_SC_PHYS_PAGES);
- #endif
- g_prefork_server->m_iAvoidFork = avoidFork;
- g_prefork_server->m_iMaxChildren = max_children;
- g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
- g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
- if ( g_prefork_server->m_iMaxIdleChildren == 0 )
- g_prefork_server->m_iMaxIdleChildren = 1;
- g_prefork_server->m_iChildrenMaxIdleTime = 300;
- g_prefork_server->m_iMaxReqProcessTime = 3600;
- setsid();
- return 0;
- }
- void LSAPI_Set_Server_fd( int fd )
- {
- if( g_prefork_server )
- g_prefork_server->m_fd = fd;
- }
- static int lsapi_accept( int fdListen )
- {
- int fd;
- int nodelay = 1;
- socklen_t len;
- char achPeer[128];
- len = sizeof( achPeer );
- fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
- if ( fd != -1 )
- {
- if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
- {
- setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&nodelay, sizeof(nodelay));
- }
- //OPTIMIZATION
- //if ( s_accept_notify )
- // notify_req_received( fd );
- }
- return fd;
- }
- static unsigned int s_max_reqs = UINT_MAX;
- static int s_max_idle_secs = 300;
- static int s_stop;
- static void lsapi_cleanup(int signal)
- {
- s_stop = signal;
- }
- static lsapi_child_status * find_child_status( int pid )
- {
- lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
- lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
- while( pStatus < pEnd )
- {
- if ( pStatus->m_pid == pid )
- {
- if (pid == 0)
- {
- memset(pStatus, 0, sizeof( *pStatus ) );
- pStatus->m_pid = -1;
- }
- if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
- g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
- return pStatus;
- }
- ++pStatus;
- }
- return NULL;
- }
- void LSAPI_reset_server_state( void )
- {
- /*
- Reset child status
- */
- g_prefork_server->m_iCurChildren = 0;
- lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
- lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
- while( pStatus < pEnd )
- {
- pStatus->m_pid = 0;
- ++pStatus;
- }
- if (s_busy_workers)
- __sync_lock_release(s_busy_workers);
- if (s_accepting_workers)
- __sync_lock_release(s_accepting_workers);
- }
- static void lsapi_sigchild( int signal )
- {
- int status, pid;
- lsapi_child_status * child_status;
- if (g_prefork_server == NULL)
- return;
- while( 1 )
- {
- pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
- if ( pid <= 0 )
- {
- break;
- }
- if ( WIFSIGNALED( status ))
- {
- int sig_num = WTERMSIG( status );
- #ifdef WCOREDUMP
- const char * dump = WCOREDUMP( status ) ? "yes" : "no";
- #else
- const char * dump = "unknown";
- #endif
- lsapi_log("Child process with pid: %d was killed by signal: "
- "%d, core dumped: %s\n", pid, sig_num, dump );
- }
- if ( pid == s_pid_dump_debug_info )
- {
- pid = 0;
- continue;
- }
- if ( pid == s_ignore_pid )
- {
- pid = 0;
- s_ignore_pid = -1;
- continue;
- }
- child_status = find_child_status( pid );
- if ( child_status )
- {
- if (__sync_bool_compare_and_swap(&child_status->m_state,
- LSAPI_STATE_CONNECTED,
- LSAPI_STATE_IDLE))
- {
- if (s_busy_workers)
- __sync_fetch_and_sub(s_busy_workers, 1);
- }
- else if (__sync_bool_compare_and_swap(&child_status->m_state,
- LSAPI_STATE_ACCEPTING,
- LSAPI_STATE_IDLE))
- {
- if (s_accepting_workers)
- __sync_fetch_and_sub(s_accepting_workers, 1);
- }
- child_status->m_pid = 0;
- --g_prefork_server->m_iCurChildren;
- }
- }
- while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
- &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
- --g_prefork_server->m_pChildrenStatusCur;
- }
- static int lsapi_init_children_status(void)
- {
- char * pBuf;
- int size = 4096;
- int max_children;
- if (g_prefork_server->m_pChildrenStatus)
- return 0;
- max_children = g_prefork_server->m_iMaxChildren
- + g_prefork_server->m_iExtraChildren;
- size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
- size = (size + 4095) / 4096 * 4096;
- pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_SHARED, -1, 0 );
- if ( pBuf == MAP_FAILED )
- {
- perror( "Anonymous mmap() failed" );
- return -1;
- }
- memset( pBuf, 0, size );
- g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
- g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
- g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
- s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
- s_accepting_workers = s_busy_workers + 1;
- s_global_counter = s_accepting_workers + 1;
- s_avail_pages = (size_t *)(s_global_counter + 1);
- setsid();
- return 0;
- }
- static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
- {
- char achCmd[1024];
- if ( s_pid_dump_debug_info )
- {
- if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
- return;
- }
- lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
- "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
- "time: %ld\n", getuid(), getppid(), pStatus->m_pid,
- pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
- tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
- s_pid_dump_debug_info = fork();
- if (s_pid_dump_debug_info == 0)
- {
- snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
- "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
- pStatus->m_pid, pStatus->m_pid );
- if ( system( achCmd ) == -1 )
- perror( "system()" );
- exit( 0 );
- }
- }
- static void lsapi_check_child_status( long tmCur )
- {
- int idle = 0;
- int tobekilled;
- int dying = 0;
- int count = 0;
- lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
- lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
- while( pStatus < pEnd )
- {
- tobekilled = 0;
- if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
- {
- ++count;
- if ( !pStatus->m_inProcess )
- {
- if (g_prefork_server->m_iCurChildren - dying
- > g_prefork_server->m_iMaxChildren
- || idle > g_prefork_server->m_iMaxIdleChildren)
- {
- ++pStatus->m_iKillSent;
- //tobekilled = SIGUSR1;
- }
- else
- {
- if (s_max_idle_secs> 0
- && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
- {
- ++pStatus->m_iKillSent;
- //tobekilled = SIGUSR1;
- }
- }
- if (!pStatus->m_iKillSent)
- ++idle;
- }
- else
- {
- if (tmCur - pStatus->m_tmReqBegin >
- g_prefork_server->m_iMaxReqProcessTime)
- {
- if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
- dump_debug_info( pStatus, tmCur );
- if ( pStatus->m_iKillSent > 5 )
- {
- tobekilled = SIGKILL;
- lsapi_log("Force killing runaway process PID: %d"
- " with SIGKILL\n", pStatus->m_pid );
- }
- else
- {
- tobekilled = SIGTERM;
- lsapi_log("Killing runaway process PID: %d with "
- "SIGTERM\n", pStatus->m_pid );
- }
- }
- }
- if ( tobekilled )
- {
- if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
- ( errno == ESRCH ))
- {
- pStatus->m_pid = 0;
- --count;
- }
- else
- {
- ++pStatus->m_iKillSent;
- ++dying;
- }
- }
- }
- ++pStatus;
- }
- if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
- {
- lsapi_log("Children tracking is wrong: Cur Children: %d,"
- " count: %d, idle: %d, dying: %d\n",
- g_prefork_server->m_iCurChildren, count, idle, dying );
- }
- }
- //static int lsapi_all_children_must_die(void)
- //{
- // int maxWait;
- // int sec =0;
- // g_prefork_server->m_iMaxReqProcessTime = 10;
- // g_prefork_server->m_iMaxIdleChildren = -1;
- // maxWait = 15;
- //
- // while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
- // {
- // lsapi_check_child_status(time(NULL));
- // sleep( 1 );
- // sec++;
- // }
- // if ( g_prefork_server->m_iCurChildren != 0 )
- // kill( -getpgrp(), SIGKILL );
- // return 0;
- //}
- void set_skip_write()
- { s_skip_write = 1; }
- int is_enough_free_mem()
- {
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- //minimum 1GB or 10% available free memory
- return (*s_avail_pages > s_min_avail_pages
- || (*s_avail_pages * 10) / s_total_pages > 0);
- #endif
- return 1;
- }
- static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
- LSAPI_Request * pReq )
- {
- struct sigaction act, old_term, old_quit, old_int,
- old_usr1, old_child;
- lsapi_child_status * child_status;
- int wait_secs = 0;
- int ret = 0;
- int pid;
- time_t lastTime = 0;
- time_t curTime = 0;
- fd_set readfds;
- struct timeval timeout;
- sigset_t mask;
- sigset_t orig_mask;
- lsapi_init_children_status();
- act.sa_flags = 0;
- act.sa_handler = lsapi_sigchild;
- sigemptyset(&(act.sa_mask));
- if( sigaction( SIGCHLD, &act, &old_child ) )
- {
- perror( "Can't set signal handler for SIGCHILD" );
- return -1;
- }
- /* Set up handler to kill children upon exit */
- act.sa_flags = 0;
- act.sa_handler = lsapi_cleanup;
- sigemptyset(&(act.sa_mask));
- if( sigaction( SIGTERM, &act, &old_term ) ||
- sigaction( SIGINT, &act, &old_int ) ||
- sigaction( SIGUSR1, &act, &old_usr1 ) ||
- sigaction( SIGQUIT, &act, &old_quit ))
- {
- perror( "Can't set signals" );
- return -1;
- }
- while( !s_stop )
- {
- if (s_proc_group_timer_cb != NULL) {
- s_proc_group_timer_cb(&s_ignore_pid);
- }
- curTime = time( NULL );
- if (curTime != lastTime )
- {
- lastTime = curTime;
- if (lsapi_parent_dead())
- break;
- lsapi_check_child_status(curTime );
- if (pServer->m_iServerMaxIdle)
- {
- if ( pServer->m_iCurChildren <= 0 )
- {
- ++wait_secs;
- if ( wait_secs > pServer->m_iServerMaxIdle )
- return -1;
- }
- else
- wait_secs = 0;
- }
- }
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
- // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
- // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
- #endif
- FD_ZERO( &readfds );
- FD_SET( pServer->m_fd, &readfds );
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
- if (ret == 1 )
- {
- int accepting = 0;
- if (s_accepting_workers)
- accepting = __sync_add_and_fetch(s_accepting_workers, 0);
- if (pServer->m_iCurChildren > 0
- && accepting > 0)
- {
- usleep(400);
- while(accepting-- > 0)
- sched_yield();
- continue;
- }
- }
- else if ( ret == -1 )
- {
- if ( errno == EINTR )
- continue;
- /* perror( "select()" ); */
- break;
- }
- else
- {
- continue;
- }
- if (pServer->m_iCurChildren >=
- pServer->m_iMaxChildren + pServer->m_iExtraChildren)
- {
- lsapi_log("Reached max children process limit: %d, extra: %d,"
- " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
- pServer->m_iMaxChildren, pServer->m_iExtraChildren,
- pServer->m_iCurChildren,
- s_busy_workers ? *s_busy_workers : -1 );
- usleep( 100000 );
- continue;
- }
- pReq->m_fd = lsapi_accept( pServer->m_fd );
- if ( pReq->m_fd != -1 )
- {
- wait_secs = 0;
- child_status = find_child_status( 0 );
- sigemptyset( &mask );
- sigaddset( &mask, SIGCHLD );
- if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
- {
- perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
- }
- pid = fork();
- if ( !pid )
- {
- setsid();
- if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
- perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
- g_prefork_server = NULL;
- s_ppid = getppid();
- s_pid = getpid();
- s_req_processed = 0;
- s_proc_group_timer_cb = NULL;
- s_worker_status = child_status;
- if (pthread_atfork_func)
- (*pthread_atfork_func)(NULL, NULL, set_skip_write);
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_CONNECTED);
- if (s_busy_workers)
- __sync_add_and_fetch(s_busy_workers, 1);
- lsapi_set_nblock( pReq->m_fd, 0 );
- //keep it open if busy_count is used.
- if (!s_keep_listener && s_busy_workers
- && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
- s_keep_listener = 1;
- if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
- && pReq->m_fdListen != -1 )
- {
- close( pReq->m_fdListen );
- pReq->m_fdListen = -1;
- }
- /* don't catch our signals */
- sigaction( SIGCHLD, &old_child, 0 );
- sigaction( SIGTERM, &old_term, 0 );
- sigaction( SIGQUIT, &old_quit, 0 );
- sigaction( SIGINT, &old_int, 0 );
- sigaction( SIGUSR1, &old_usr1, 0 );
- //init_conn_key( pReq->m_fd );
- lsapi_notify_pid( pReq->m_fd );
- s_notified_pid = 1;
- //if ( s_accept_notify )
- // return notify_req_received( pReq->m_fd );
- return 0;
- }
- else if ( pid == -1 )
- {
- lsapi_perror("fork() failed, please increase process limit", errno);
- if (child_status)
- child_status->m_pid = 0;
- }
- else
- {
- ++pServer->m_iCurChildren;
- if ( child_status )
- {
- child_status->m_pid = pid;
- child_status->m_tmWaitBegin = curTime;
- child_status->m_tmStart = curTime;
- }
- }
- close( pReq->m_fd );
- pReq->m_fd = -1;
- if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
- perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
- }
- else
- {
- if (( errno == EINTR )||( errno == EAGAIN))
- continue;
- lsapi_perror("accept() failed", errno);
- return -1;
- }
- }
- sigaction( SIGUSR1, &old_usr1, 0 );
- //kill( -getpgrp(), SIGUSR1 );
- //lsapi_all_children_must_die(); /* Sorry, children ;-) */
- return -1;
- }
- static struct sigaction old_term, old_quit, old_int,
- old_usr1, old_child;
- int LSAPI_Postfork_Child(LSAPI_Request * pReq)
- {
- int max_children = g_prefork_server->m_iMaxChildren;
- s_pid = getpid();
- __sync_lock_test_and_set(&pReq->child_status->m_pid, s_pid);
- s_worker_status = pReq->child_status;
- setsid();
- g_prefork_server = NULL;
- s_ppid = getppid();
- s_req_processed = 0;
- s_proc_group_timer_cb = NULL;
- if (pthread_atfork_func)
- (*pthread_atfork_func)(NULL, NULL, set_skip_write);
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_CONNECTED);
- if (s_busy_workers)
- __sync_add_and_fetch(s_busy_workers, 1);
- lsapi_set_nblock( pReq->m_fd, 0 );
- //keep it open if busy_count is used.
- if (!s_keep_listener && s_busy_workers
- && *s_busy_workers > (max_children >> 1))
- s_keep_listener = 1;
- if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
- && pReq->m_fdListen != -1 )
- {
- close(pReq->m_fdListen);
- pReq->m_fdListen = -1;
- }
- //init_conn_key( pReq->m_fd );
- lsapi_notify_pid(pReq->m_fd);
- s_notified_pid = 1;
- //if ( s_accept_notify )
- // return notify_req_received( pReq->m_fd );
- return 0;
- }
- int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
- {
- ++g_prefork_server->m_iCurChildren;
- if (pReq->child_status)
- {
- time_t curTime = time( NULL );
- pReq->child_status->m_tmWaitBegin = curTime;
- pReq->child_status->m_tmStart = curTime;
- }
- close(pReq->m_fd);
- pReq->m_fd = -1;
- return 0;
- }
- int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
- {
- time_t lastTime = 0;
- time_t curTime = 0;
- fd_set readfds;
- struct timeval timeout;
- int wait_secs = 0;
- int ret = 0;
- lsapi_prefork_server * pServer = g_prefork_server;
- struct sigaction act;
- lsapi_init_children_status();
- act.sa_flags = 0;
- act.sa_handler = lsapi_sigchild;
- sigemptyset(&(act.sa_mask));
- if (sigaction(SIGCHLD, &act, &old_child))
- {
- perror( "Can't set signal handler for SIGCHILD" );
- return -1;
- }
- /* Set up handler to kill children upon exit */
- act.sa_flags = 0;
- act.sa_handler = lsapi_cleanup;
- sigemptyset(&(act.sa_mask));
- if (sigaction(SIGTERM, &act, &old_term) ||
- sigaction(SIGINT, &act, &old_int ) ||
- sigaction(SIGUSR1, &act, &old_usr1) ||
- sigaction(SIGQUIT, &act, &old_quit))
- {
- perror( "Can't set signals" );
- return -1;
- }
- s_stop = 0;
- pReq->m_reqState = 0;
- while(!s_stop)
- {
- if (s_proc_group_timer_cb != NULL) {
- s_proc_group_timer_cb(&s_ignore_pid);
- }
- curTime = time(NULL);
- if (curTime != lastTime)
- {
- lastTime = curTime;
- if (lsapi_parent_dead())
- break;
- lsapi_check_child_status(curTime);
- if (pServer->m_iServerMaxIdle)
- {
- if (pServer->m_iCurChildren <= 0)
- {
- ++wait_secs;
- if ( wait_secs > pServer->m_iServerMaxIdle )
- return -1;
- }
- else
- wait_secs = 0;
- }
- }
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
- // lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
- // s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
- #endif
- FD_ZERO(&readfds);
- FD_SET(pServer->m_fd, &readfds);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
- if (ret == 1 )
- {
- int accepting = 0;
- if (s_accepting_workers)
- accepting = __sync_add_and_fetch(s_accepting_workers, 0);
- if (pServer->m_iCurChildren > 0
- && accepting > 0)
- {
- usleep( 400);
- while(accepting-- > 0)
- sched_yield();
- continue;
- }
- }
- else if (ret == -1)
- {
- if (errno == EINTR)
- continue;
- /* perror( "select()" ); */
- break;
- }
- else
- {
- continue;
- }
- if (pServer->m_iCurChildren >=
- pServer->m_iMaxChildren + pServer->m_iExtraChildren)
- {
- lsapi_log("Reached max children process limit: %d, extra: %d,"
- " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
- pServer->m_iMaxChildren, pServer->m_iExtraChildren,
- pServer->m_iCurChildren,
- s_busy_workers ? *s_busy_workers : -1);
- usleep(100000);
- continue;
- }
- pReq->m_fd = lsapi_accept(pServer->m_fd);
- if (pReq->m_fd != -1)
- {
- wait_secs = 0;
- pReq->child_status = find_child_status(0);
- ret = 0;
- break;
- }
- else
- {
- if ((errno == EINTR) || (errno == EAGAIN))
- continue;
- lsapi_perror("accept() failed", errno);
- ret = -1;
- break;
- }
- }
- sigaction(SIGCHLD, &old_child, 0);
- sigaction(SIGTERM, &old_term, 0);
- sigaction(SIGQUIT, &old_quit, 0);
- sigaction(SIGINT, &old_int, 0);
- sigaction(SIGUSR1, &old_usr1, 0);
- return ret;
- }
- int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
- {
- int fd;
- int ret;
- int wait_secs;
- fd_set readfds;
- struct timeval timeout;
- if (s_skip_write)
- return -1;
- LSAPI_Finish_r( pReq );
- if ( g_prefork_server )
- {
- if ( g_prefork_server->m_fd != -1 )
- if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
- return -1;
- }
- else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
- {
- ret = __sync_fetch_and_add(s_busy_workers, 0);
- if (ret >= s_max_busy_workers)
- {
- send_conn_close_notification(pReq->m_fd);
- lsapi_close_connection(pReq);
- }
- }
- if ( (unsigned int)s_req_processed > s_max_reqs )
- return -1;
- if ( s_worker_status )
- {
- s_worker_status->m_tmWaitBegin = time( NULL );
- }
- while( g_running )
- {
- if ( pReq->m_fd != -1 )
- {
- fd = pReq->m_fd;
- }
- else if ( pReq->m_fdListen != -1 )
- fd = pReq->m_fdListen;
- else
- {
- break;
- }
- wait_secs = 0;
- while( 1 )
- {
- if ( !g_running )
- return -1;
- if (s_req_processed && s_worker_status
- && s_worker_status->m_iKillSent)
- return -1;
- FD_ZERO( &readfds );
- FD_SET( fd, &readfds );
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- if (fd == pReq->m_fdListen)
- {
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_ACCEPTING);
- if (s_accepting_workers)
- __sync_fetch_and_add(s_accepting_workers, 1);
- }
- ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
- if (fd == pReq->m_fdListen)
- {
- if (s_accepting_workers)
- __sync_fetch_and_sub(s_accepting_workers, 1);
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_IDLE);
- }
- if ( ret == 0 )
- {
- if ( s_worker_status )
- {
- s_worker_status->m_inProcess = 0;
- if (fd == pReq->m_fdListen)
- {
- if (s_keep_listener == 0 || !is_enough_free_mem())
- return -1;
- if (s_keep_listener == 1)
- {
- int wait_time = 10;
- if (s_busy_workers)
- wait_time += *s_busy_workers * 10;
- if (s_accepting_workers)
- wait_time >>= (*s_accepting_workers);
- if (wait_secs >= wait_time)
- return -1;
- }
- }
- }
- ++wait_secs;
- if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
- return -1;
- if ( lsapi_parent_dead() )
- return -1;
- }
- else if ( ret == -1 )
- {
- if ( errno == EINTR )
- continue;
- else
- return -1;
- }
- else if ( ret >= 1 )
- {
- if (s_req_processed && s_worker_status
- && s_worker_status->m_iKillSent)
- return -1;
- if ( fd == pReq->m_fdListen )
- {
- pReq->m_fd = lsapi_accept( pReq->m_fdListen );
- if ( pReq->m_fd != -1 )
- {
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_CONNECTED);
- if (s_busy_workers)
- __sync_fetch_and_add(s_busy_workers, 1);
- fd = pReq->m_fd;
- lsapi_set_nblock( fd, 0 );
- //init_conn_key( pReq->m_fd );
- if (!s_keep_listener)
- {
- close( pReq->m_fdListen );
- pReq->m_fdListen = -1;
- }
- if ( s_accept_notify )
- if ( notify_req_received( pReq->m_fd ) == -1 )
- return -1;
- }
- else
- {
- if (( errno == EINTR )||( errno == EAGAIN))
- continue;
- lsapi_perror( "lsapi_accept() error", errno );
- return -1;
- }
- }
- else
- break;
- }
- }
- if ( !readReq( pReq ) )
- {
- if ( s_worker_status )
- {
- s_worker_status->m_iKillSent = 0;
- s_worker_status->m_inProcess = 1;
- ++s_worker_status->m_iReqCounter;
- s_worker_status->m_tmReqBegin =
- s_worker_status->m_tmLastCheckPoint = time(NULL);
- }
- ++s_req_processed;
- return 0;
- }
- lsapi_close_connection(pReq);
- LSAPI_Reset_r( pReq );
- }
- return -1;
- }
- void LSAPI_Set_Max_Reqs( int reqs )
- { s_max_reqs = reqs - 1; }
- void LSAPI_Set_Max_Idle( int secs )
- { s_max_idle_secs = secs; }
- void LSAPI_Set_Max_Children( int maxChildren )
- {
- if ( g_prefork_server )
- g_prefork_server->m_iMaxChildren = maxChildren;
- }
- void LSAPI_Set_Extra_Children( int extraChildren )
- {
- if (( g_prefork_server )&&( extraChildren >= 0 ))
- g_prefork_server->m_iExtraChildren = extraChildren;
- }
- void LSAPI_Set_Max_Process_Time( int secs )
- {
- if (( g_prefork_server )&&( secs > 0 ))
- g_prefork_server->m_iMaxReqProcessTime = secs;
- }
- void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
- {
- if (( g_prefork_server )&&( maxIdleChld > 0 ))
- g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
- }
- void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
- {
- if ( g_prefork_server )
- g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
- }
- void LSAPI_Set_Slow_Req_Msecs( int msecs )
- {
- s_slow_req_msecs = msecs;
- }
- int LSAPI_Get_Slow_Req_Msecs(void)
- {
- return s_slow_req_msecs;
- }
- void LSAPI_No_Check_ppid(void)
- {
- s_ppid = 0;
- }
- int LSAPI_Get_ppid()
- {
- return(s_ppid);
- }
- #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- #include <crt_externs.h>
- #else
- extern char ** environ;
- #endif
- static void unset_lsapi_envs(void)
- {
- char **env;
- #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- env = *_NSGetEnviron();
- #else
- env = environ;
- #endif
- while( env != NULL && *env != NULL )
- {
- if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
- || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
- {
- char ** del = env;
- do
- *del = del[1];
- while( *del++ );
- }
- else
- ++env;
- }
- }
- static int lsapi_initSuEXEC(void)
- {
- int i;
- struct passwd * pw;
- s_defaultUid = 0;
- s_defaultGid = 0;
- if ( s_uid == 0 )
- {
- const char * p = getenv( "LSAPI_DEFAULT_UID" );
- if ( p )
- {
- i = atoi( p );
- if ( i > 0 )
- s_defaultUid = i;
- }
- p = getenv( "LSAPI_DEFAULT_GID" );
- if ( p )
- {
- i = atoi( p );
- if ( i > 0 )
- s_defaultGid = i;
- }
- p = getenv( "LSAPI_SECRET" );
- if (( !p )||( readSecret(p) == -1 ))
- return -1;
- if ( g_prefork_server )
- {
- if ( g_prefork_server->m_iMaxChildren < 100 )
- g_prefork_server->m_iMaxChildren = 100;
- if ( g_prefork_server->m_iExtraChildren < 1000 )
- g_prefork_server->m_iExtraChildren = 1000;
- }
- }
- if ( !s_defaultUid || !s_defaultGid )
- {
- pw = getpwnam( "nobody" );
- if ( pw )
- {
- if ( !s_defaultUid )
- s_defaultUid = pw->pw_uid;
- if ( !s_defaultGid )
- s_defaultGid = pw->pw_gid;
- }
- else
- {
- if ( !s_defaultUid )
- s_defaultUid = 10000;
- if ( !s_defaultGid )
- s_defaultGid = 10000;
- }
- }
- return 0;
- }
- static int lsapi_check_path(const char *p, char *final, int max_len)
- {
- char resolved_path[PATH_MAX+1];
- int len = 0;
- char *end;
- if (*p != '/')
- {
- if (getcwd(final, max_len) == NULL)
- return -1;
- len = strlen(final);
- *(final + len) = '/';
- ++len;
- }
- end = memccpy(&final[len], p, '\0', PATH_MAX - len);
- if (!end)
- {
- errno = EINVAL;
- return -1;
- }
- p = final;
- if (realpath(p, resolved_path) == NULL
- && errno != ENOENT && errno != EACCES)
- return -1;
- if (strncmp(resolved_path, "/etc/", 5) == 0)
- {
- errno = EPERM;
- return -1;
- }
- return 0;
- }
- static int lsapi_reopen_stderr2(const char *full_path)
- {
- int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
- if (newfd == -1)
- {
- LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
- return -1;
- }
- if (newfd != 2)
- {
- dup2(newfd, 2);
- close(newfd);
- dup2(2, 1);
- }
- if (s_stderr_log_path && full_path != s_stderr_log_path)
- {
- free(s_stderr_log_path);
- s_stderr_log_path = NULL;
- }
- s_stderr_log_path = strdup(full_path);
- return 0;
- }
- static int lsapi_reopen_stderr(const char *p)
- {
- char full_path[PATH_MAX];
- if (s_uid == 0)
- return -1;
- if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
- {
- LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
- return -1;
- }
- return lsapi_reopen_stderr2(full_path);
- }
- int LSAPI_Init_Env_Parameters( fn_select_t fp )
- {
- const char *p;
- char ch;
- int n;
- int avoidFork = 0;
- p = getenv("LSAPI_STDERR_LOG");
- if (p)
- {
- lsapi_reopen_stderr(p);
- }
- if (!s_stderr_log_path)
- s_stderr_is_pipe = isPipe(STDERR_FILENO);
- p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
- if ( !p )
- p = getenv( "LSAPI_MAX_REQS" );
- if ( p )
- {
- n = atoi( p );
- if ( n > 0 )
- LSAPI_Set_Max_Reqs( n );
- }
- p = getenv( "LSAPI_KEEP_LISTEN" );
- if ( p )
- {
- n = atoi( p );
- s_keep_listener = n;
- }
- p = getenv( "LSAPI_AVOID_FORK" );
- if ( p )
- {
- avoidFork = atoi( p );
- if (avoidFork)
- {
- s_keep_listener = 2;
- ch = *(p + strlen(p) - 1);
- if ( ch == 'G' || ch == 'g' )
- avoidFork *= 1024 * 1024 * 1024;
- else if ( ch == 'M' || ch == 'm' )
- avoidFork *= 1024 * 1024;
- if (avoidFork >= 1024 * 10240)
- s_min_avail_pages = avoidFork / 4096;
- }
- }
- p = getenv( "LSAPI_ACCEPT_NOTIFY" );
- if ( p )
- {
- s_accept_notify = atoi( p );
- }
- p = getenv( "LSAPI_SLOW_REQ_MSECS" );
- if ( p )
- {
- n = atoi( p );
- LSAPI_Set_Slow_Req_Msecs( n );
- }
- #if defined( RLIMIT_CORE )
- p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
- if ( !p )
- {
- struct rlimit limit = { 0, 0 };
- setrlimit( RLIMIT_CORE, &limit );
- }
- else
- s_enable_core_dump = 1;
- #endif
- p = getenv( "LSAPI_MAX_IDLE" );
- if ( p )
- {
- n = atoi( p );
- LSAPI_Set_Max_Idle( n );
- }
- if ( LSAPI_Is_Listen() )
- {
- n = 0;
- p = getenv( "PHP_LSAPI_CHILDREN" );
- if ( !p )
- p = getenv( "LSAPI_CHILDREN" );
- if ( p )
- n = atoi( p );
- if ( n > 1 )
- {
- LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
- LSAPI_Set_Server_fd( g_req.m_fdListen );
- }
- p = getenv( "LSAPI_EXTRA_CHILDREN" );
- if ( p )
- LSAPI_Set_Extra_Children( atoi( p ) );
- p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
- if ( p )
- LSAPI_Set_Max_Idle_Children( atoi( p ) );
- p = getenv( "LSAPI_PGRP_MAX_IDLE" );
- if ( p )
- {
- LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
- }
- p = getenv( "LSAPI_MAX_PROCESS_TIME" );
- if ( p )
- LSAPI_Set_Max_Process_Time( atoi( p ) );
- if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
- {
- LSAPI_No_Check_ppid();
- }
- p = getenv("LSAPI_MAX_BUSY_WORKER");
- if (p)
- {
- n = atoi(p);
- s_max_busy_workers = n;
- if (n >= 0)
- LSAPI_No_Check_ppid();
- }
- p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
- if ( p )
- s_dump_debug_info = atoi( p );
- if ( lsapi_initSuEXEC() == -1 )
- return -1;
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- lsapi_initLVE();
- #endif
- }
- unset_lsapi_envs();
- return 0;
- }
- int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
- const char * pBody, int bodyLen )
- {
- LSAPI_SetRespStatus_r( pReq, code );
- if ( pRespHeaders )
- {
- while( *pRespHeaders )
- {
- LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
- ++pRespHeaders;
- }
- }
- if ( pBody &&( bodyLen > 0 ))
- {
- LSAPI_Write_r( pReq, pBody, bodyLen );
- }
- LSAPI_Finish_r( pReq );
- return 0;
- }
- static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
- /*
- * Note: this code is harmless on little-endian machines.
- */
- static void byteReverse(unsigned char *buf, unsigned longs)
- {
- uint32 t;
- do {
- t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32 *) buf = t;
- buf += 4;
- } while (--longs);
- }
- /*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
- void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
- {
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
- }
- /*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
- void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
- {
- register uint32 t;
- /* Update bitcount */
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
- /* Handle any leading odd-sized chunks */
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
- t = 64 - t;
- if (len < t) {
- memmove(p, buf, len);
- return;
- }
- memmove(p, buf, t);
- byteReverse(ctx->in, 16);
- lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
- buf += t;
- len -= t;
- }
- /* Process data in 64-byte chunks */
- while (len >= 64) {
- memmove(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
- buf += 64;
- len -= 64;
- }
- /* Handle any remaining bytes of data. */
- memmove(ctx->in, buf, len);
- }
- /*
- * Final wrap-up - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
- void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
- {
- unsigned int count;
- unsigned char *p;
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
- /* Append length in bits and transform */
- ((uint32 *) ctx->in)[14] = ctx->bits[0];
- ((uint32 *) ctx->in)[15] = ctx->bits[1];
- lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memmove(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
- }
- /* The four core functions - F1 is optimized somewhat */
- /* #define F1(x, y, z) (x & y | ~x & z) */
- #define F1(x, y, z) (z ^ (x & (y ^ z)))
- #define F2(x, y, z) F1(z, x, y)
- #define F3(x, y, z) (x ^ y ^ z)
- #define F4(x, y, z) (y ^ (x | ~z))
- /* This is the central step in the MD5 algorithm. */
- #define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
- /*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
- static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
- {
- register uint32 a, b, c, d;
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
- }
- int LSAPI_Set_Restored_Parent_Pid(int pid)
- {
- int old_ppid = s_ppid;
- s_restored_ppid = pid;
- return old_ppid;
- }
- int LSAPI_Inc_Req_Processed(int cnt)
- {
- return __sync_add_and_fetch(s_global_counter, cnt);
- }
|