inet.cpp 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429
  1. /*
  2. * PROGRAM: JRD Remote Interface/Server
  3. * MODULE: inet.cpp
  4. * DESCRIPTION: TCP/UCP/IP Communications module.
  5. *
  6. * The contents of this file are subject to the Interbase Public
  7. * License Version 1.0 (the "License"); you may not use this file
  8. * except in compliance with the License. You may obtain a copy
  9. * of the License at http://www.Inprise.com/IPL.html
  10. *
  11. * Software distributed under the License is distributed on an
  12. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  13. * or implied. See the License for the specific language governing
  14. * rights and limitations under the License.
  15. *
  16. * The Original Code was created by Inprise Corporation
  17. * and its predecessors. Portions created by Inprise Corporation are
  18. * Copyright (C) Inprise Corporation.
  19. *
  20. * All Rights Reserved.
  21. * Contributor(s): ______________________________________.
  22. *
  23. * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "EPSON" port
  24. * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "XENIX" port
  25. * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "IMP" port
  26. * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "NCR3000" port
  27. *
  28. * 2002-02-23 Sean Leyne - Code Cleanup, removed old M88K and NCR3000 port
  29. *
  30. * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "UNIXWARE" port
  31. * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "Ultrix/MIPS" port
  32. *
  33. * 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
  34. *
  35. * 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
  36. *
  37. * 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
  38. * 2002.10.30 Sean Leyne - Code Cleanup, removed obsolete "SUN3_3" port
  39. * 2005.04.01 Konstantin Kuznetsov - allow setting NoNagle option in Classic
  40. *
  41. */
  42. #include "firebird.h"
  43. #include <stdio.h>
  44. #ifdef HAVE_SYS_TYPES_H
  45. #include <sys/types.h>
  46. #endif
  47. #include <errno.h>
  48. #include <string.h>
  49. #include <stdlib.h>
  50. #include "../common/file_params.h"
  51. #include <stdarg.h>
  52. #include "../common/classes/timestamp.h"
  53. #include "../common/classes/init.h"
  54. #include "../common/ThreadStart.h"
  55. #include "../common/os/os_utils.h"
  56. #ifdef HAVE_PWD_H
  57. #include <pwd.h>
  58. #endif
  59. #ifdef HAVE_SYS_PARAM_H
  60. #include <sys/param.h>
  61. #endif
  62. #ifdef HAVE_GRP_H
  63. #include <grp.h>
  64. #endif
  65. #ifdef HAVE_SYS_SOCKET_H
  66. #include <sys/socket.h> // for socket()
  67. #endif
  68. #ifdef HAVE_UNISTD_H
  69. #include <unistd.h>
  70. #endif
  71. #ifdef WIN_NT
  72. #define FD_SETSIZE 2048
  73. #endif
  74. #ifndef WIN_NT
  75. #include <netinet/tcp.h>
  76. #include <netinet/in.h>
  77. #include <netdb.h>
  78. #include <arpa/inet.h>
  79. #include <sys/wait.h>
  80. #if defined(HAVE_POLL_H)
  81. #include <poll.h>
  82. #elif defined(HAVE_SYS_SELECT_H)
  83. #include <sys/select.h>
  84. #endif
  85. #endif // !WIN_NT
  86. const int INET_RETRY_CALL = 5;
  87. #include "../remote/remote.h"
  88. #include "../remote/SockAddr.h"
  89. #include "ibase.h"
  90. #include "../remote/inet_proto.h"
  91. #include "../remote/proto_proto.h"
  92. #include "../remote/remot_proto.h"
  93. #include "../yvalve/gds_proto.h"
  94. #include "../common/isc_proto.h"
  95. #include "../common/isc_f_proto.h"
  96. #include "../common/os/isc_i_proto.h"
  97. #include "../common/config/config.h"
  98. #include "../common/utils_proto.h"
  99. #include "../common/classes/ClumpletWriter.h"
  100. // Please review. Maybe not needed. See H_ERRNO in common.h.
  101. #if defined HPUX
  102. extern int h_errno;
  103. #endif
  104. using namespace Firebird;
  105. #ifdef WIN_NT
  106. #include <fcntl.h>
  107. #include <process.h>
  108. #include <signal.h>
  109. #include "../utilities/install/install_nt.h"
  110. #include <mstcpip.h>
  111. #ifndef SIO_LOOPBACK_FAST_PATH
  112. #define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)
  113. #endif
  114. #define INET_RETRY_ERRNO WSAEINPROGRESS
  115. #define INET_ADDR_IN_USE WSAEADDRINUSE
  116. #define sleep(seconds) Sleep ((seconds) * 1000)
  117. const int NOTASOCKET = WSAENOTSOCK;
  118. #else // WIN_NT
  119. #ifndef INET_ADDR_IN_USE
  120. #define INET_ADDR_IN_USE EADDRINUSE
  121. #endif
  122. #ifndef INET_RETRY_ERRNO
  123. #define INET_RETRY_ERRNO TRY_AGAIN
  124. #endif
  125. const int NOTASOCKET = EBADF;
  126. #endif // WIN_NT
  127. static void SOCLOSE(SOCKET& socket)
  128. {
  129. SOCKET s = socket;
  130. if (s != INVALID_SOCKET)
  131. {
  132. socket = INVALID_SOCKET;
  133. #ifdef WIN_NT
  134. closesocket(s);
  135. #else
  136. close(s);
  137. #endif
  138. }
  139. }
  140. #ifndef ENOBUFS
  141. #define ENOBUFS 0
  142. #endif
  143. #ifndef FB_SEND_FLAGS
  144. #define FB_SEND_FLAGS 0
  145. #endif
  146. #ifndef FB_SETOPT_FLAGS
  147. #define FB_SETOPT_FLAGS 0
  148. #endif
  149. //
  150. //#define DEBUG 1
  151. //
  152. #ifdef DEBUG
  153. #ifdef HAVE_SYS_TIMEB_H
  154. # include <sys/timeb.h>
  155. #endif
  156. const int TRACE_packets = 1 << 0; // bit 0
  157. const int TRACE_operations = 1 << 1; // bit 1
  158. const int TRACE_summary = 1 << 2; // bit 2
  159. static int INET_trace = TRACE_summary | TRACE_packets | TRACE_operations;
  160. static time_t INET_start_time = 0;
  161. SLONG INET_force_error = -1; // simulate a network error
  162. static ULONG INET_count_send = 0;
  163. static ULONG INET_count_recv = 0;
  164. static ULONG INET_bytes_send = 0;
  165. static ULONG INET_bytes_recv = 0;
  166. static ULONG inet_debug_timer()
  167. {
  168. /**************************************
  169. *
  170. * i n e t _ d e b u g _ t i m e r
  171. *
  172. **************************************
  173. *
  174. * Functional description
  175. * Utility function used in DEBUG mode only to put a timestamp
  176. * since start of connection on each debug output message.
  177. *
  178. * This has been implemented and tested on SOLARIS, and may
  179. * need tweeking on any other platform where DEBUG is needed.
  180. *
  181. **************************************/
  182. #ifdef HAVE_GETTIMEOFDAY
  183. struct timeval tv;
  184. GETTIMEOFDAY(&tv);
  185. return (tv.tv_sec * 1000 + tv.tv_usec - INET_start_time);
  186. #else
  187. struct timeb now;
  188. ftime(&now);
  189. return (now.time * 1000 + now.millitm - INET_start_time);
  190. #endif // HAVE_GETTIMEOFDAY
  191. }
  192. #endif // DEBUG
  193. const ULONG MAX_DATA_LW = 1448; // Low Water mark
  194. const ULONG MAX_DATA_HW = 32768; // High Water mark
  195. const ULONG DEF_MAX_DATA = 8192;
  196. //const int MAXHOSTLEN = 64;
  197. const int SELECT_TIMEOUT = 60; // Dispatch thread select timeout (sec)
  198. class Select
  199. {
  200. #ifdef HAVE_POLL
  201. private:
  202. static const int SEL_INIT_EVENTS = POLLIN;
  203. static const int SEL_CHECK_MASK = POLLIN;
  204. pollfd* getPollFd(int n)
  205. {
  206. FB_SIZE_T pos;
  207. if (slct_poll.find(n, pos))
  208. return &slct_poll[pos];
  209. return nullptr;
  210. }
  211. #endif
  212. public:
  213. #ifdef HAVE_POLL
  214. Select()
  215. : slct_time(0), slct_count(0), slct_poll(*getDefaultMemoryPool()),
  216. slct_ready(*getDefaultMemoryPool())
  217. { }
  218. explicit Select(Firebird::MemoryPool& pool)
  219. : slct_time(0), slct_count(0), slct_poll(pool), slct_ready(pool)
  220. { }
  221. #else
  222. Select()
  223. : slct_time(0), slct_count(0), slct_width(0)
  224. {
  225. memset(&slct_fdset, 0, sizeof slct_fdset);
  226. }
  227. explicit Select(Firebird::MemoryPool& /*pool*/)
  228. : slct_time(0), slct_count(0), slct_width(0)
  229. {
  230. memset(&slct_fdset, 0, sizeof slct_fdset);
  231. }
  232. #endif
  233. enum HandleState {SEL_BAD, SEL_DISCONNECTED, SEL_NO_DATA, SEL_READY};
  234. // set first port to check for readyness
  235. void checkStart(RemPortPtr& port)
  236. {
  237. slct_main = port;
  238. slct_port = port;
  239. #ifdef WIRE_COMPRESS_SUPPORT
  240. slct_zport = nullptr;
  241. #endif
  242. }
  243. // get port to check for readyness
  244. // assume port_mutex is locked
  245. HandleState checkNext(RemPortPtr& port)
  246. {
  247. #ifdef WIRE_COMPRESS_SUPPORT
  248. if (slct_zport)
  249. {
  250. if (slct_zport->port_z_data &&
  251. (slct_zport->port_state != rem_port::DISCONNECTED))
  252. {
  253. port = slct_zport;
  254. slct_zport = nullptr; // Will be set again by select_multi() if needed
  255. return SEL_READY;
  256. }
  257. slct_zport = nullptr;
  258. }
  259. #endif
  260. if (slct_port && slct_port->port_state == rem_port::DISCONNECTED)
  261. {
  262. // restart from main port
  263. slct_port = nullptr;
  264. if (slct_main && slct_main->port_state == rem_port::DISCONNECTED)
  265. slct_main = nullptr;
  266. slct_port = slct_main;
  267. }
  268. port = slct_port;
  269. if (!slct_port)
  270. return SEL_NO_DATA;
  271. #ifdef WIRE_COMPRESS_SUPPORT
  272. if (slct_port->port_z_data)
  273. return SEL_READY;
  274. #endif
  275. slct_port = slct_port->port_next;
  276. return ok(port);
  277. }
  278. void setZDataPort(RemPortPtr& port)
  279. {
  280. #ifdef WIRE_COMPRESS_SUPPORT
  281. slct_zport = port;
  282. #endif
  283. }
  284. HandleState ok(const rem_port* port)
  285. {
  286. #ifdef WIRE_COMPRESS_SUPPORT
  287. if (port->port_z_data)
  288. return SEL_READY;
  289. #endif
  290. SOCKET n = port->port_handle;
  291. #if defined(WIN_NT)
  292. if (FD_ISSET(n, &slct_fdset))
  293. {
  294. unset(n);
  295. return SEL_READY;
  296. }
  297. return SEL_NO_DATA;
  298. #elif defined(HAVE_POLL)
  299. pollfd* pf = nullptr;
  300. FB_SIZE_T pos;
  301. if (slct_ready.find(n, pos))
  302. pf = slct_ready[pos];
  303. if (pf)
  304. {
  305. HandleState ret = pf->events & SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA;
  306. pf->events = 0; // unset
  307. return ret;
  308. }
  309. return n < 0 ? (port->port_flags & PORT_disconnect ? SEL_DISCONNECTED : SEL_BAD) : SEL_NO_DATA;
  310. #else
  311. if (n < 0 || n >= FD_SETSIZE)
  312. return port->port_flags & PORT_disconnect ? SEL_DISCONNECTED : SEL_BAD;
  313. if (n < slct_width && FD_ISSET(n, &slct_fdset))
  314. {
  315. unset(n);
  316. return SEL_READY;
  317. }
  318. return SEL_NO_DATA;
  319. #endif
  320. }
  321. void unset(SOCKET handle)
  322. {
  323. #if defined(HAVE_POLL)
  324. pollfd* pf = getPollFd(handle);
  325. if (pf)
  326. {
  327. pf->events = 0;
  328. }
  329. #else
  330. FD_CLR(handle, &slct_fdset);
  331. --slct_count;
  332. #endif
  333. }
  334. void set(SOCKET handle)
  335. {
  336. #ifdef HAVE_POLL
  337. FB_SIZE_T pos;
  338. if (slct_poll.find(handle, pos))
  339. {
  340. slct_poll[pos].events = SEL_INIT_EVENTS;
  341. }
  342. else
  343. {
  344. pollfd f;
  345. f.fd = handle;
  346. f.events = SEL_INIT_EVENTS;
  347. slct_poll.insert(pos, f);
  348. }
  349. #else
  350. FD_SET(handle, &slct_fdset);
  351. #ifdef WIN_NT
  352. ++slct_width;
  353. #else
  354. slct_width = MAX(slct_width, handle + 1);
  355. #endif // WIN_NT
  356. #endif // HAVE_POLL
  357. }
  358. void clear()
  359. {
  360. slct_count = 0;
  361. #if defined(HAVE_POLL)
  362. slct_poll.clear();
  363. #else
  364. slct_width = 0;
  365. FD_ZERO(&slct_fdset);
  366. #endif
  367. slct_main = nullptr;
  368. slct_port = nullptr;
  369. #ifdef WIRE_COMPRESS_SUPPORT
  370. slct_zport = nullptr;
  371. #endif
  372. }
  373. void select(timeval* timeout)
  374. {
  375. #ifdef HAVE_POLL
  376. slct_ready.clear();
  377. bool hasRequest = false;
  378. pollfd* const end = slct_poll.end();
  379. for (pollfd* pf = slct_poll.begin(); pf < end; ++pf)
  380. {
  381. pf->revents = pf->events;
  382. if (pf->events & SEL_CHECK_MASK)
  383. hasRequest = true;
  384. }
  385. if (!hasRequest)
  386. {
  387. errno = NOTASOCKET;
  388. slct_count = -1;
  389. return;
  390. }
  391. int milliseconds = timeout ? timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : -1;
  392. slct_count = ::poll(slct_poll.begin(), slct_poll.getCount(), milliseconds);
  393. if (slct_count >= 0) // in case of error return revents may contain something bad
  394. {
  395. for (pollfd* pf = slct_poll.begin(); pf < end; ++pf)
  396. {
  397. pf->events = pf->revents;
  398. if (pf->revents & SEL_CHECK_MASK)
  399. slct_ready.add(pf);
  400. }
  401. }
  402. #else
  403. #ifdef WIN_NT
  404. slct_count = ::select(FD_SETSIZE, &slct_fdset, NULL, NULL, timeout);
  405. #else
  406. slct_count = ::select(slct_width, &slct_fdset, NULL, NULL, timeout);
  407. #endif // WIN_NT
  408. #endif // HAVE_POLL
  409. }
  410. int getCount()
  411. {
  412. return slct_count;
  413. }
  414. time_t slct_time;
  415. private:
  416. int slct_count;
  417. #ifdef HAVE_POLL
  418. class PollToFD
  419. {
  420. public:
  421. static int generate(const pollfd* p) { return p->fd; };
  422. static int generate(const pollfd& p) { return p.fd; };
  423. };
  424. SortedArray<pollfd, InlineStorage<pollfd, 8>, int, PollToFD> slct_poll;
  425. SortedArray<pollfd*, InlineStorage<pollfd*, 8>, int, PollToFD> slct_ready;
  426. #else
  427. int slct_width;
  428. fd_set slct_fdset;
  429. #endif
  430. RemPortPtr slct_main; // first port to check for readyness
  431. RemPortPtr slct_port; // next port to check for readyness
  432. #ifdef WIRE_COMPRESS_SUPPORT
  433. RemPortPtr slct_zport; // port with some compressed data remaining in the buffer
  434. #endif
  435. };
  436. static bool accept_connection(rem_port*, const P_CNCT*);
  437. #ifdef HAVE_SETITIMER
  438. static void alarm_handler(int);
  439. #endif
  440. static rem_port* alloc_port(rem_port*, const USHORT = 0);
  441. static rem_port* aux_connect(rem_port*, PACKET*);
  442. static void abort_aux_connection(rem_port*);
  443. static rem_port* aux_request(rem_port*, PACKET*);
  444. #if !defined(WIN_NT)
  445. static THREAD_ENTRY_DECLARE waitThread(THREAD_ENTRY_PARAM);
  446. static GlobalPtr<Mutex> waitThreadMutex;
  447. static unsigned int procCount = 0;
  448. #endif // WIN_NT
  449. static void disconnect(rem_port*);
  450. static void force_close(rem_port*);
  451. static int cleanup_ports(const int, const int, void*);
  452. #ifdef NO_FORK
  453. static int fork();
  454. #endif
  455. typedef Array<SOCKET> SocketsArray;
  456. #ifdef WIN_NT
  457. static int wsaExitHandler(const int, const int, void*);
  458. static int fork(SOCKET, USHORT);
  459. static THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM);
  460. static GlobalPtr<Mutex> forkMutex;
  461. static HANDLE forkEvent = INVALID_HANDLE_VALUE;
  462. static bool forkThreadStarted = false;
  463. static SocketsArray* forkSockets;
  464. #endif
  465. static void get_peer_info(rem_port*);
  466. static void inet_gen_error(bool, rem_port*, const Arg::StatusVector& v);
  467. static void inet_error(bool, rem_port*, const TEXT*, ISC_STATUS, int);
  468. static bool inet_read(RemoteXdr*);
  469. static rem_port* inet_try_connect( PACKET*,
  470. Rdb*,
  471. const PathName&,
  472. const TEXT*,
  473. ClumpletReader&,
  474. RefPtr<const Config>*,
  475. const PathName*,
  476. int);
  477. static bool inet_write(RemoteXdr*);
  478. static rem_port* listener_socket(rem_port* port, USHORT flag, const addrinfo* pai);
  479. #ifdef DEBUG
  480. static void packet_print(const TEXT*, const UCHAR*, int, ULONG);
  481. #endif
  482. static bool packet_receive(rem_port*, UCHAR*, SSHORT, SSHORT*);
  483. static bool packet_receive2(rem_port*, UCHAR*, SSHORT, SSHORT*);
  484. static bool packet_send(rem_port*, const SCHAR*, SSHORT);
  485. static rem_port* receive(rem_port*, PACKET *);
  486. static rem_port* select_accept(rem_port*);
  487. static void select_port(rem_port*, Select*, RemPortPtr&);
  488. static bool select_multi(rem_port*, UCHAR* buffer, SSHORT bufsize, SSHORT* length, RemPortPtr&);
  489. static bool select_wait(rem_port*, Select*);
  490. static int send_full(rem_port*, PACKET *);
  491. static int send_partial(rem_port*, PACKET *);
  492. static RemoteXdr* xdrinet_create(rem_port*, UCHAR *, USHORT, enum xdr_op);
  493. static bool setNoNagleOption(rem_port*);
  494. static bool setKeepAlive(SOCKET);
  495. static FPTR_INT tryStopMainThread = 0;
  496. struct InetXdr : public RemoteXdr
  497. {
  498. virtual bool_t x_getbytes(SCHAR *, unsigned); // get some bytes from "
  499. virtual bool_t x_putbytes(const SCHAR*, unsigned); // put some bytes to "
  500. };
  501. #define MAXCLIENTS NOFILE - 10
  502. // Select uses bit masks of file descriptors in longs.
  503. #ifndef NBBY
  504. #define NBBY 8
  505. #endif
  506. #ifndef NFDBITS
  507. #if !defined(WIN_NT)
  508. #define NFDBITS (sizeof(SLONG) * NBBY)
  509. #define FD_SET(n, p) ((p)->fds_bits[(n) / NFDBITS] |= (1 << ((n) % NFDBITS)))
  510. #define FD_CLR(n, p) ((p)->fds_bits[(n) / NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  511. #define FD_ISSET(n, p) ((p)->fds_bits[(n) / NFDBITS] & (1 << ((n) % NFDBITS)))
  512. #define FD_ZERO(p) memset(p, 0, sizeof(*(p)))
  513. #endif
  514. #endif
  515. #ifdef WIN_NT
  516. #define INTERRUPT_ERROR(x) (SYSCALL_INTERRUPTED(x) || (x) == WSAEINTR)
  517. #else
  518. #define INTERRUPT_ERROR(x) (SYSCALL_INTERRUPTED(x))
  519. #endif
  520. ULONG INET_remote_buffer;
  521. static GlobalPtr<Mutex> init_mutex;
  522. static volatile bool INET_initialized = false;
  523. static volatile bool INET_shutting_down = false;
  524. static Firebird::GlobalPtr<Select> INET_select;
  525. static rem_port* inet_async_receive = NULL;
  526. static GlobalPtr<Mutex> port_mutex;
  527. static GlobalPtr<PortsCleanup> inet_ports;
  528. static GlobalPtr<SocketsArray> ports_to_close;
  529. rem_port* INET_analyze(ClntAuthBlock* cBlock,
  530. const PathName& file_name,
  531. const TEXT* node_name,
  532. bool uv_flag,
  533. ClumpletReader &dpb,
  534. RefPtr<const Config>* config,
  535. const PathName* ref_db_name,
  536. Firebird::ICryptKeyCallback* cryptCb,
  537. int af)
  538. {
  539. /**************************************
  540. *
  541. * I N E T _ a n a l y z e
  542. *
  543. **************************************
  544. *
  545. * Functional description
  546. * File_name is on node_name.
  547. * Establish an external connection to node_name.
  548. *
  549. * If a connection is established, return a port block, otherwise
  550. * return NULL.
  551. *
  552. * If the "uv_flag" is non-zero, user verification also takes place.
  553. *
  554. **************************************/
  555. // We need to establish a connection to a remote server. Allocate the necessary
  556. // blocks and get ready to go.
  557. Rdb* rdb = FB_NEW Rdb;
  558. PACKET* packet = &rdb->rdb_packet;
  559. // Pick up some user identification information
  560. ClumpletWriter user_id(ClumpletReader::UnTagged, 64000);
  561. if (cBlock)
  562. {
  563. cBlock->extractDataFromPluginTo(user_id);
  564. }
  565. string buffer;
  566. int eff_gid;
  567. int eff_uid;
  568. ISC_get_user(&buffer, &eff_uid, &eff_gid);
  569. #ifdef WIN_NT
  570. // XNET lowercases user names (as it's always case-insensitive in Windows),
  571. // so let's be consistent and use the same trick for INET as well
  572. buffer.lower();
  573. #endif
  574. ISC_systemToUtf8(buffer);
  575. user_id.insertString(CNCT_user, buffer);
  576. ISC_get_host(buffer);
  577. buffer.lower();
  578. ISC_systemToUtf8(buffer);
  579. user_id.insertString(CNCT_host, buffer);
  580. if ((eff_uid == -1) || uv_flag) {
  581. user_id.insertTag(CNCT_user_verification);
  582. }
  583. else
  584. {
  585. // Communicate group id info to server, as user maybe running under group
  586. // id other than default specified in /etc/passwd.
  587. eff_gid = htonl(eff_gid);
  588. user_id.insertBytes(CNCT_group, reinterpret_cast<UCHAR*>(&eff_gid), sizeof(eff_gid));
  589. }
  590. // Should compression be tried?
  591. bool compression = config && (*config)->getWireCompression();
  592. // Establish connection to server
  593. // If we want user verification, we can't speak anything less than version 7
  594. P_CNCT* cnct = &packet->p_cnct;
  595. cnct->p_cnct_user_id.cstr_length = (ULONG) user_id.getBufferLength();
  596. cnct->p_cnct_user_id.cstr_address = user_id.getBuffer();
  597. static const p_cnct::p_cnct_repeat protocols_to_try[] =
  598. {
  599. REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_lazy_send, 1),
  600. REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_lazy_send, 2),
  601. REMOTE_PROTOCOL(PROTOCOL_VERSION12, ptype_lazy_send, 3),
  602. REMOTE_PROTOCOL(PROTOCOL_VERSION13, ptype_lazy_send, 4),
  603. REMOTE_PROTOCOL(PROTOCOL_VERSION14, ptype_lazy_send, 5),
  604. REMOTE_PROTOCOL(PROTOCOL_VERSION15, ptype_lazy_send, 6),
  605. REMOTE_PROTOCOL(PROTOCOL_VERSION16, ptype_lazy_send, 7),
  606. REMOTE_PROTOCOL(PROTOCOL_VERSION17, ptype_lazy_send, 8),
  607. REMOTE_PROTOCOL(PROTOCOL_VERSION18, ptype_lazy_send, 9),
  608. REMOTE_PROTOCOL(PROTOCOL_VERSION19, ptype_lazy_send, 10)
  609. };
  610. fb_assert(FB_NELEM(protocols_to_try) <= FB_NELEM(cnct->p_cnct_versions));
  611. cnct->p_cnct_count = FB_NELEM(protocols_to_try);
  612. for (size_t i = 0; i < cnct->p_cnct_count; i++) {
  613. cnct->p_cnct_versions[i] = protocols_to_try[i];
  614. if (compression && cnct->p_cnct_versions[i].p_cnct_version >= PROTOCOL_VERSION13 &&
  615. rem_port::checkCompression())
  616. {
  617. cnct->p_cnct_versions[i].p_cnct_max_type |= pflag_compress;
  618. }
  619. }
  620. rem_port* port = inet_try_connect(packet, rdb, file_name, node_name, dpb, config, ref_db_name, af);
  621. P_ACPT* accept;
  622. for (;;)
  623. {
  624. accept = NULL;
  625. switch (packet->p_operation)
  626. {
  627. case op_accept_data:
  628. case op_cond_accept:
  629. accept = &packet->p_acpd;
  630. if (cBlock)
  631. {
  632. cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
  633. packet->p_acpd.p_acpt_data.cstr_address);
  634. cBlock->authComplete = packet->p_acpd.p_acpt_authenticated;
  635. port->addServerKeys(&packet->p_acpd.p_acpt_keys);
  636. cBlock->resetClnt(&packet->p_acpd.p_acpt_keys);
  637. }
  638. break;
  639. case op_accept:
  640. if (cBlock)
  641. {
  642. cBlock->resetClnt();
  643. }
  644. accept = &packet->p_acpt;
  645. break;
  646. case op_crypt_key_callback:
  647. try
  648. {
  649. UCharBuffer buf;
  650. P_CRYPT_CALLBACK* cc = &packet->p_cc;
  651. if (cryptCb)
  652. {
  653. if (cc->p_cc_reply <= 0)
  654. {
  655. cc->p_cc_reply = 1;
  656. }
  657. UCHAR* reply = buf.getBuffer(cc->p_cc_reply);
  658. unsigned l = cryptCb->callback(cc->p_cc_data.cstr_length,
  659. cc->p_cc_data.cstr_address, cc->p_cc_reply, reply);
  660. REMOTE_free_packet(port, packet, true);
  661. cc->p_cc_data.cstr_length = l;
  662. cc->p_cc_data.cstr_address = reply;
  663. }
  664. else
  665. {
  666. REMOTE_free_packet(port, packet, true);
  667. cc->p_cc_data.cstr_length = 0;
  668. }
  669. packet->p_operation = op_crypt_key_callback;
  670. cc->p_cc_reply = 0;
  671. port->send(packet);
  672. port->receive(packet);
  673. continue;
  674. }
  675. catch (const Exception&)
  676. {
  677. disconnect(port);
  678. delete rdb;
  679. throw;
  680. }
  681. case op_response:
  682. try
  683. {
  684. LocalStatus warning; // Ignore connect warnings for a while
  685. CheckStatusWrapper statusWrapper(&warning);
  686. REMOTE_check_response(&statusWrapper, rdb, packet, false);
  687. }
  688. catch (const Exception&)
  689. {
  690. disconnect(port);
  691. delete rdb;
  692. throw;
  693. }
  694. // fall through - response is not a required accept
  695. default:
  696. disconnect(port);
  697. delete rdb;
  698. Arg::Gds(isc_connect_reject).raise();
  699. break;
  700. }
  701. break; // Always leave for() loop here
  702. }
  703. fb_assert(accept);
  704. fb_assert(port);
  705. port->port_protocol = accept->p_acpt_version;
  706. // once we've decided on a protocol, concatenate the version
  707. // string to reflect it...
  708. string temp;
  709. temp.printf("%s/P%d", port->port_version->str_data, port->port_protocol & FB_PROTOCOL_MASK);
  710. delete port->port_version;
  711. port->port_version = REMOTE_make_string(temp.c_str());
  712. if (accept->p_acpt_architecture == ARCHITECTURE) {
  713. port->port_flags |= PORT_symmetric;
  714. }
  715. bool compress = accept->p_acpt_type & pflag_compress;
  716. accept->p_acpt_type &= ptype_MASK;
  717. if (accept->p_acpt_type != ptype_out_of_band) {
  718. port->port_flags |= PORT_no_oob;
  719. }
  720. if (accept->p_acpt_type == ptype_lazy_send) {
  721. port->port_flags |= PORT_lazy;
  722. }
  723. if (compress)
  724. {
  725. port->initCompression();
  726. port->port_flags |= PORT_compressed;
  727. }
  728. return port;
  729. }
  730. rem_port* INET_connect(const TEXT* name,
  731. PACKET* packet,
  732. USHORT flag,
  733. ClumpletReader* dpb,
  734. RefPtr<const Config>* config,
  735. int af)
  736. {
  737. /**************************************
  738. *
  739. * I N E T _ c o n n e c t
  740. *
  741. **************************************
  742. *
  743. * Functional description
  744. * Establish half of a communication link. If a connect packet is given,
  745. * the connection is on behalf of a remote interface. Otherwise the connect
  746. * is for a server process.
  747. *
  748. **************************************/
  749. #ifdef DEBUG
  750. {
  751. if (INET_trace & TRACE_operations)
  752. {
  753. fprintf(stdout, "INET_connect\n");
  754. fflush(stdout);
  755. }
  756. INET_start_time = inet_debug_timer();
  757. // CVC: I don't see the point in replacing this with fb_utils::readenv().
  758. const char* p = getenv("INET_force_error");
  759. if (p != NULL) {
  760. INET_force_error = atoi(p);
  761. }
  762. }
  763. #endif
  764. rem_port* port = alloc_port(NULL);
  765. if (config)
  766. {
  767. port->port_config = *config;
  768. }
  769. REMOTE_get_timeout_params(port, dpb);
  770. string host;
  771. string protocol;
  772. if ((!name || !name[0]) && !packet)
  773. {
  774. name = port->getPortConfig()->getRemoteBindAddress();
  775. }
  776. if (name)
  777. {
  778. host = name;
  779. const FB_SIZE_T pos = host.find("/");
  780. if (pos != string::npos)
  781. {
  782. protocol = host.substr(pos + 1);
  783. host = host.substr(0, pos);
  784. }
  785. if (host.hasData() && host[0] == '[' && host[host.length() - 1] == ']')
  786. {
  787. // host name or address is in brackets, remove them
  788. host.erase(host.length() - 1);
  789. host.erase(0, 1);
  790. }
  791. }
  792. if (host.hasData())
  793. {
  794. delete port->port_connection;
  795. port->port_connection = nullptr;
  796. port->port_connection = REMOTE_make_string(host.c_str());
  797. }
  798. else if (packet)
  799. {
  800. host = port->port_host->str_data;
  801. }
  802. if (protocol.isEmpty())
  803. {
  804. const unsigned short port2 = port->getPortConfig()->getRemoteServicePort();
  805. if (port2) {
  806. protocol.printf("%hu", port2);
  807. }
  808. else {
  809. protocol = port->getPortConfig()->getRemoteServiceName();
  810. }
  811. }
  812. // Prepare hints
  813. const bool ipv6 = os_utils::isIPv6supported();
  814. struct addrinfo gai_hints;
  815. memset(&gai_hints, 0, sizeof(gai_hints));
  816. if (packet)
  817. gai_hints.ai_family = af;
  818. else
  819. gai_hints.ai_family = ((host.hasData() || !ipv6) ? AF_UNSPEC : AF_INET6);
  820. gai_hints.ai_socktype = SOCK_STREAM;
  821. #if !defined(WIN_NT) && !defined(__clang__)
  822. gai_hints.ai_protocol = SOL_TCP;
  823. #else
  824. gai_hints.ai_protocol = IPPROTO_TCP;
  825. #endif
  826. gai_hints.ai_flags =
  827. #ifndef ANDROID
  828. ((af == AF_UNSPEC) ? AI_V4MAPPED : 0) |
  829. #endif
  830. AI_ADDRCONFIG | (packet ? 0 : AI_PASSIVE);
  831. struct AutoAddrInfo
  832. {
  833. ~AutoAddrInfo()
  834. {
  835. if (ptr)
  836. freeaddrinfo(ptr);
  837. }
  838. addrinfo* ptr = nullptr;
  839. } gai_result;
  840. const char* host_str = (host.hasData() ? host.c_str() : NULL);
  841. bool retry_gai;
  842. int n;
  843. do
  844. {
  845. retry_gai = false;
  846. n = getaddrinfo(host_str, protocol.c_str(), &gai_hints, &gai_result.ptr);
  847. if ((n == EAI_FAMILY || (!host_str && n == EAI_NONAME)) &&
  848. (gai_hints.ai_family == AF_INET6) && (af != AF_INET6))
  849. {
  850. // May be on a system without IPv6 support, try IPv4
  851. gai_hints.ai_family = AF_UNSPEC;
  852. retry_gai = true;
  853. }
  854. if ((n == EAI_SERVICE) && (protocol == FB_SERVICE_NAME))
  855. {
  856. // Try hard-wired translation of "gds_db" to "3050"
  857. protocol.printf("%hu", FB_SERVICE_PORT);
  858. retry_gai = (protocol != FB_SERVICE_NAME);
  859. }
  860. } while (retry_gai);
  861. if (n)
  862. {
  863. gds__log("INET/INET_connect: getaddrinfo(%s,%s) failed: %s",
  864. host.c_str(), protocol.c_str(), gai_strerror(n));
  865. inet_gen_error(true, port, Arg::Gds(isc_net_lookup_err) << Arg::Gds(isc_host_unknown));
  866. }
  867. for (const addrinfo* pai = gai_result.ptr; pai; pai = pai->ai_next)
  868. {
  869. // Allocate a port block and initialize a socket for communications
  870. port->port_handle = os_utils::socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol);
  871. if (port->port_handle == INVALID_SOCKET)
  872. {
  873. gds__log("socket: error creating socket (family %d, socktype %d, protocol %d",
  874. pai->ai_family, pai->ai_socktype, pai->ai_protocol);
  875. continue;
  876. }
  877. if (!packet) // server
  878. return listener_socket(port, flag, pai);
  879. // client
  880. if (!setKeepAlive(port->port_handle))
  881. gds__log("setsockopt: error setting SO_KEEPALIVE");
  882. if (!setNoNagleOption(port))
  883. gds__log("setsockopt: error setting TCP_NODELAY");
  884. else
  885. {
  886. n = connect(port->port_handle, pai->ai_addr, pai->ai_addrlen);
  887. if (n != -1)
  888. {
  889. port->port_peer_name = host;
  890. get_peer_info(port);
  891. if (send_full(port, packet))
  892. return port;
  893. }
  894. }
  895. SOCLOSE(port->port_handle);
  896. }
  897. // all attempts failed
  898. if (packet)
  899. inet_error(true, port, "connect", isc_net_connect_err, 0);
  900. else
  901. inet_error(true, port, "listen", isc_net_connect_listen_err, 0);
  902. return port;
  903. }
  904. static rem_port* listener_socket(rem_port* port, USHORT flag, const addrinfo* pai)
  905. {
  906. /**************************************
  907. *
  908. * l i s t e n e r _ s o c k e t
  909. *
  910. **************************************
  911. *
  912. * Functional description
  913. * Final part of server (listening) socket setup. Sets socket options,
  914. * binds the socket and calls listen().
  915. * For multi-client server (SuperServer or SuperClassic) return listener
  916. * port.
  917. * For classic server - accept incoming connections and fork worker
  918. * processes, return NULL at exit;
  919. * On error throw exception.
  920. *
  921. **************************************/
  922. int ipv6_v6only = port->getPortConfig()->getIPv6V6Only() ? 1 : 0;
  923. int n = setsockopt(port->port_handle, IPPROTO_IPV6, IPV6_V6ONLY,
  924. (SCHAR*) &ipv6_v6only, sizeof(ipv6_v6only));
  925. if (n == -1)
  926. gds__log("setsockopt: error setting IPV6_V6ONLY to %d", ipv6_v6only);
  927. if (flag & SRVR_multi_client)
  928. {
  929. struct linger lingerInfo;
  930. lingerInfo.l_onoff = 0;
  931. lingerInfo.l_linger = 0;
  932. #ifndef WIN_NT
  933. // dimitr: on Windows, lack of SO_REUSEADDR works the same way as it was specified on POSIX,
  934. // i.e. it allows binding to a port in a TIME_WAIT/FIN_WAIT state. If this option
  935. // is turned on explicitly, then a port can be re-bound regardless of its state,
  936. // e.g. while it's listening. This is surely not what we want.
  937. int optval = TRUE;
  938. n = setsockopt(port->port_handle, SOL_SOCKET, SO_REUSEADDR,
  939. (SCHAR*) &optval, sizeof(optval));
  940. if (n == -1)
  941. {
  942. inet_error(true, port, "setsockopt REUSE", isc_net_connect_listen_err, INET_ERRNO);
  943. }
  944. #endif
  945. // Get any values for SO_LINGER so that they can be reset during
  946. // disconnect. SO_LINGER should be set by default on the socket
  947. socklen_t optlen = sizeof(port->port_linger);
  948. n = getsockopt(port->port_handle, SOL_SOCKET, SO_LINGER,
  949. (SCHAR *) & port->port_linger, &optlen);
  950. if (n != 0) // getsockopt failed
  951. port->port_linger.l_onoff = 0;
  952. n = setsockopt(port->port_handle, SOL_SOCKET, SO_LINGER,
  953. (SCHAR *) & lingerInfo, sizeof(lingerInfo));
  954. if (n == -1)
  955. {
  956. inet_error(true, port, "setsockopt LINGER", isc_net_connect_listen_err, INET_ERRNO);
  957. }
  958. }
  959. else
  960. {
  961. if (! setKeepAlive(port->port_handle))
  962. {
  963. inet_error(true, port, "setsockopt SO_KEEPALIVE", isc_net_connect_listen_err, INET_ERRNO);
  964. }
  965. }
  966. // RS: In linux sockets inherit this option from listener. Previously CLASSIC had no its own listen socket
  967. // Now it's necessary to respect the option via listen socket.
  968. if (! setNoNagleOption(port))
  969. {
  970. inet_error(true, port, "setsockopt TCP_NODELAY", isc_net_connect_listen_err, INET_ERRNO);
  971. }
  972. // On Linux platform, when the server dies the system holds a port
  973. // for some time (we don't set SO_REUSEADDR for standalone server).
  974. int retry = -1;
  975. do
  976. {
  977. if (++retry)
  978. sleep(10);
  979. n = bind(port->port_handle, pai->ai_addr, pai->ai_addrlen);
  980. } while (n == -1 && INET_ERRNO == INET_ADDR_IN_USE && retry < INET_RETRY_CALL);
  981. if (n == -1)
  982. {
  983. inet_error(true, port, "bind", isc_net_connect_listen_err, INET_ERRNO);
  984. }
  985. n = listen(port->port_handle, SOMAXCONN);
  986. if (n == -1)
  987. {
  988. inet_error(false, port, "listen", isc_net_connect_listen_err, INET_ERRNO);
  989. }
  990. inet_ports->registerPort(port);
  991. if (flag & SRVR_multi_client)
  992. {
  993. // Prevent the generation of dummy keepalive packets on the connect port.
  994. port->port_dummy_packet_interval = 0;
  995. port->port_dummy_timeout = 0;
  996. port->port_server_flags |= (SRVR_server | SRVR_multi_client);
  997. return port;
  998. }
  999. while (true)
  1000. {
  1001. SOCKET s = os_utils::accept(port->port_handle, NULL, NULL);
  1002. const int inetErrNo = INET_ERRNO;
  1003. if (s == INVALID_SOCKET)
  1004. {
  1005. if (INET_shutting_down)
  1006. return NULL;
  1007. inet_error(true, port, "accept", isc_net_connect_err, inetErrNo);
  1008. }
  1009. #ifdef WIN_NT
  1010. if (flag & SRVR_debug)
  1011. #else
  1012. if ((flag & SRVR_debug) || !fork())
  1013. #endif
  1014. {
  1015. SOCLOSE(port->port_handle);
  1016. port->port_handle = s;
  1017. port->port_server_flags |= SRVR_server;
  1018. port->port_flags |= PORT_server;
  1019. return port;
  1020. }
  1021. #ifdef WIN_NT
  1022. MutexLockGuard forkGuard(forkMutex, FB_FUNCTION);
  1023. if (!forkThreadStarted)
  1024. {
  1025. forkThreadStarted = true;
  1026. forkEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1027. forkSockets = FB_NEW SocketsArray(*getDefaultMemoryPool());
  1028. Thread::start(forkThread, (void*) flag, THREAD_medium);
  1029. }
  1030. forkSockets->add(s);
  1031. SetEvent(forkEvent);
  1032. #else
  1033. MutexLockGuard guard(waitThreadMutex, FB_FUNCTION);
  1034. if (! procCount++) {
  1035. Thread::start(waitThread, 0, THREAD_medium);
  1036. }
  1037. SOCLOSE(s);
  1038. #endif
  1039. }
  1040. #ifdef WIN_NT
  1041. MutexLockGuard forkGuard(forkMutex, FB_FUNCTION);
  1042. if (forkThreadStarted)
  1043. {
  1044. SetEvent(forkEvent);
  1045. CloseHandle(forkEvent);
  1046. delete forkSockets;
  1047. forkSockets = NULL;
  1048. }
  1049. #endif
  1050. return NULL;
  1051. }
  1052. rem_port* INET_reconnect(SOCKET handle)
  1053. {
  1054. /**************************************
  1055. *
  1056. * I N E T _ r e c o n n e c t
  1057. *
  1058. **************************************
  1059. *
  1060. * Functional description
  1061. * A communications link has been established by another
  1062. * process. We have inheritted the handle. Set up
  1063. * a port block.
  1064. *
  1065. **************************************/
  1066. rem_port* const port = alloc_port(NULL);
  1067. port->port_handle = handle;
  1068. port->port_flags |= PORT_server;
  1069. port->port_server_flags |= SRVR_server;
  1070. if (! setKeepAlive(port->port_handle)) {
  1071. gds__log("inet server err: setting KEEPALIVE socket option \n");
  1072. }
  1073. if (! setNoNagleOption(port)) {
  1074. gds__log("inet server err: setting NODELAY socket option \n");
  1075. }
  1076. return port;
  1077. }
  1078. rem_port* INET_server(SOCKET sock)
  1079. {
  1080. /**************************************
  1081. *
  1082. * I N E T _ s e r v e r
  1083. *
  1084. **************************************
  1085. *
  1086. * Functional description
  1087. * We have been spawned by a master server with a connection
  1088. * established. Set up port block with the appropriate socket.
  1089. *
  1090. **************************************/
  1091. rem_port* const port = alloc_port(NULL);
  1092. port->port_flags |= PORT_server;
  1093. port->port_server_flags |= SRVR_server;
  1094. port->port_handle = sock;
  1095. if (! setKeepAlive(port->port_handle)) {
  1096. gds__log("inet server err: setting KEEPALIVE socket option \n");
  1097. }
  1098. if (! setNoNagleOption(port)) {
  1099. gds__log("inet server err: setting NODELAY socket option \n");
  1100. }
  1101. return port;
  1102. }
  1103. static bool accept_connection(rem_port* port, const P_CNCT* cnct)
  1104. {
  1105. /**************************************
  1106. *
  1107. * a c c e p t _ c o n n e c t i o n
  1108. *
  1109. **************************************
  1110. *
  1111. * Functional description
  1112. * Accept an incoming request for connection. This is purely a lower
  1113. * level handshaking function, and does not constitute the server
  1114. * response for protocol selection.
  1115. *
  1116. **************************************/
  1117. // Default account to "guest" (in theory all packets contain a name)
  1118. string user_name("guest"), host_name;
  1119. // Pick up account and host name, if given
  1120. ClumpletReader id(ClumpletReader::UnTagged,
  1121. cnct->p_cnct_user_id.cstr_address,
  1122. cnct->p_cnct_user_id.cstr_length);
  1123. for (id.rewind(); !id.isEof(); id.moveNext())
  1124. {
  1125. switch (id.getClumpTag())
  1126. {
  1127. case CNCT_user:
  1128. id.getString(user_name);
  1129. break;
  1130. case CNCT_host:
  1131. id.getString(host_name);
  1132. break;
  1133. default:
  1134. break;
  1135. }
  1136. }
  1137. #ifndef WIN_NT
  1138. { // scope
  1139. // If the environment variable ISC_INET_SERVER_HOME is set,
  1140. // change the home directory to the specified directory.
  1141. // Note that this will overrule the normal setting of
  1142. // the current directory to the effective user's home directory.
  1143. // This feature was added primarily for testing via remote
  1144. // loopback - but does seem to be of good general use, so
  1145. // is activated for the release version.
  1146. // 1995-February-27 David Schnepper
  1147. PathName home;
  1148. if (fb_utils::readenv("ISC_INET_SERVER_HOME", home))
  1149. {
  1150. if (chdir(home.c_str()))
  1151. {
  1152. gds__log("inet_server: unable to cd to %s errno %d\n", home.c_str(), INET_ERRNO);
  1153. // We continue after the error
  1154. }
  1155. }
  1156. } // end scope
  1157. #endif // !WIN_NT
  1158. // store user identity
  1159. port->port_login = port->port_user_name = user_name;
  1160. port->port_peer_name = host_name;
  1161. get_peer_info(port);
  1162. return true;
  1163. }
  1164. static rem_port* alloc_port(rem_port* const parent, const USHORT flags)
  1165. {
  1166. /**************************************
  1167. *
  1168. * a l l o c _ p o r t
  1169. *
  1170. **************************************
  1171. *
  1172. * Functional description
  1173. * Allocate a port block, link it in to parent (if there is a parent),
  1174. * and initialize input and output XDR streams.
  1175. *
  1176. **************************************/
  1177. if (!INET_initialized)
  1178. {
  1179. MutexLockGuard guard(init_mutex, FB_FUNCTION);
  1180. if (!INET_initialized)
  1181. {
  1182. #ifdef WIN_NT
  1183. static WSADATA wsadata;
  1184. const WORD version = MAKEWORD(2, 0);
  1185. const int wsaError = WSAStartup(version, &wsadata);
  1186. if (wsaError)
  1187. {
  1188. inet_error(false, parent, "WSAStartup", isc_net_init_error, wsaError);
  1189. }
  1190. fb_shutdown_callback(0, wsaExitHandler, fb_shut_finish, 0);
  1191. #endif
  1192. INET_remote_buffer = Config::getTcpRemoteBufferSize();
  1193. if (INET_remote_buffer < MAX_DATA_LW || INET_remote_buffer > MAX_DATA_HW)
  1194. {
  1195. INET_remote_buffer = DEF_MAX_DATA;
  1196. }
  1197. #ifdef DEBUG
  1198. gds__log(" Info: Remote Buffer Size set to %ld", INET_remote_buffer);
  1199. #endif
  1200. fb_shutdown_callback(0, cleanup_ports, fb_shut_postproviders, 0);
  1201. INET_initialized = true;
  1202. // This should go AFTER 'INET_initialized = true' to avoid recursion
  1203. // That order of statements at the first glance appears to be possible cause of races:
  1204. // Someone may pass the if (!INET_initialized) with INET_initialized == true,
  1205. // but inet_async_receive still being NULL. Luckily it's not so awful actually.
  1206. // Async receive is used only by network server and there is no way for it
  1207. // to allocate secondary ports until completion of master port init.
  1208. inet_async_receive = alloc_port(0);
  1209. inet_async_receive->port_flags |= PORT_server;
  1210. }
  1211. }
  1212. rem_port* const port = FB_NEW rem_port(rem_port::INET, INET_remote_buffer * 2);
  1213. REMOTE_get_timeout_params(port, 0);
  1214. TEXT buffer[BUFFER_SMALL];
  1215. gethostname(buffer, sizeof(buffer));
  1216. port->port_host = REMOTE_make_string(buffer);
  1217. port->port_connection = REMOTE_make_string(buffer);
  1218. SNPRINTF(buffer, FB_NELEM(buffer), "tcp (%s)", port->port_host->str_data);
  1219. port->port_version = REMOTE_make_string(buffer);
  1220. port->port_accept = accept_connection;
  1221. port->port_disconnect = disconnect;
  1222. port->port_force_close = force_close;
  1223. port->port_receive_packet = receive;
  1224. port->port_select_multi = select_multi;
  1225. port->port_send_packet = send_full;
  1226. port->port_send_partial = send_partial;
  1227. port->port_connect = aux_connect;
  1228. port->port_abort_aux_connection = abort_aux_connection;
  1229. port->port_request = aux_request;
  1230. port->port_buff_size = (USHORT) INET_remote_buffer;
  1231. port->port_async_receive = inet_async_receive;
  1232. port->port_flags |= flags;
  1233. port->port_send = xdrinet_create(port,
  1234. &port->port_buffer[REM_SEND_OFFSET(INET_remote_buffer)],
  1235. (USHORT) INET_remote_buffer, XDR_ENCODE);
  1236. port->port_receive = xdrinet_create(port,
  1237. &port->port_buffer[REM_RECV_OFFSET(INET_remote_buffer)], 0, XDR_DECODE);
  1238. if (parent && !(parent->port_server_flags & SRVR_thread_per_port))
  1239. {
  1240. MutexLockGuard guard(port_mutex, FB_FUNCTION);
  1241. port->linkParent(parent);
  1242. }
  1243. return port;
  1244. }
  1245. static void abort_aux_connection(rem_port* port)
  1246. {
  1247. if (port->port_flags & PORT_connecting)
  1248. {
  1249. shutdown(port->port_channel, 2);
  1250. SOCLOSE(port->port_channel);
  1251. }
  1252. }
  1253. static rem_port* aux_connect(rem_port* port, PACKET* packet)
  1254. {
  1255. /**************************************
  1256. *
  1257. * a u x _ c o n n e c t
  1258. *
  1259. **************************************
  1260. *
  1261. * Functional description
  1262. * Try to establish an alternative connection. Somebody has already
  1263. * done a successfull connect request ("packet" contains the response).
  1264. *
  1265. **************************************/
  1266. // If this is a server, we're got an auxiliary connection. Accept it
  1267. if (port->port_server_flags)
  1268. {
  1269. struct timeval timeout;
  1270. timeout.tv_sec = port->port_connect_timeout;
  1271. timeout.tv_usec = 0;
  1272. Select slct;
  1273. slct.set(port->port_channel);
  1274. int inetErrNo = 0;
  1275. while (true)
  1276. {
  1277. slct.select(&timeout);
  1278. const int count = slct.getCount();
  1279. inetErrNo = INET_ERRNO;
  1280. if (count != -1 || !INTERRUPT_ERROR(inetErrNo))
  1281. {
  1282. if (count == 1)
  1283. break;
  1284. const ISC_STATUS error_code =
  1285. (count == 0) ? isc_net_event_connect_timeout : isc_net_event_connect_err;
  1286. int savedError = inetErrNo;
  1287. SOCLOSE(port->port_channel);
  1288. inet_error(false, port, "select", error_code, savedError);
  1289. }
  1290. }
  1291. if (port->port_channel == INVALID_SOCKET)
  1292. return NULL;
  1293. const SOCKET n = os_utils::accept(port->port_channel, NULL, NULL);
  1294. inetErrNo = INET_ERRNO;
  1295. if (n == INVALID_SOCKET)
  1296. {
  1297. int savedError = inetErrNo;
  1298. SOCLOSE(port->port_channel);
  1299. inet_error(false, port, "accept", isc_net_event_connect_err, savedError);
  1300. }
  1301. SOCLOSE(port->port_channel);
  1302. port->port_handle = n;
  1303. port->port_flags |= PORT_async;
  1304. get_peer_info(port);
  1305. return port;
  1306. }
  1307. rem_port* const new_port = alloc_port(port->port_parent,
  1308. (port->port_flags & PORT_no_oob) | PORT_async);
  1309. port->port_async = new_port;
  1310. new_port->port_dummy_packet_interval = port->port_dummy_packet_interval;
  1311. new_port->port_dummy_timeout = new_port->port_dummy_packet_interval;
  1312. P_RESP* response = &packet->p_resp;
  1313. // NJK - Determine address and port to use.
  1314. //
  1315. // The address returned by the server may be incorrect if it is behind a NAT box
  1316. // so we must use the address that was used to connect the main socket, not the
  1317. // address reported by the server.
  1318. //
  1319. // The port number reported by the server is used. For NAT support the port number
  1320. // should be configured to be a fixed port number in the server configuration.
  1321. SockAddr address;
  1322. int status = address.getpeername(port->port_handle);
  1323. if (status != 0)
  1324. {
  1325. int savedError = INET_ERRNO;
  1326. port->auxAcceptError(packet);
  1327. inet_error(false, port, "socket", isc_net_event_connect_err, savedError);
  1328. }
  1329. SockAddr resp_address(response->p_resp_data.cstr_address, response->p_resp_data.cstr_length);
  1330. address.setPort(resp_address.port());
  1331. // Set up new socket
  1332. SOCKET n = os_utils::socket(address.family(), SOCK_STREAM, 0);
  1333. if (n == INVALID_SOCKET)
  1334. {
  1335. int savedError = INET_ERRNO;
  1336. port->auxAcceptError(packet);
  1337. inet_error(false, port, "socket", isc_net_event_connect_err, savedError);
  1338. }
  1339. setKeepAlive(n);
  1340. status = address.connect(n);
  1341. if (status < 0)
  1342. {
  1343. int savedError = INET_ERRNO;
  1344. SOCLOSE(n);
  1345. port->auxAcceptError(packet);
  1346. inet_error(false, port, "connect", isc_net_event_connect_err, savedError);
  1347. }
  1348. new_port->port_handle = n;
  1349. new_port->port_peer_name = port->port_peer_name;
  1350. get_peer_info(new_port);
  1351. return new_port;
  1352. }
  1353. static rem_port* aux_request( rem_port* port, PACKET* packet)
  1354. {
  1355. /**************************************
  1356. *
  1357. * a u x _ r e q u e s t
  1358. *
  1359. **************************************
  1360. *
  1361. * Functional description
  1362. * A remote interface has requested the server prepare an auxiliary
  1363. * connection; the server calls aux_request to set up the connection.
  1364. *
  1365. **************************************/
  1366. // listen on (local) address of the original socket
  1367. SockAddr our_address;
  1368. if (our_address.getsockname(port->port_handle) < 0)
  1369. {
  1370. gds__log("INET/aux_request: failed to get local address of the original socket");
  1371. inet_error(false, port, "getsockname", isc_net_event_listen_err, INET_ERRNO);
  1372. }
  1373. unsigned short aux_port = port->getPortConfig()->getRemoteAuxPort();
  1374. our_address.setPort(aux_port); // may be 0
  1375. SOCKET n = os_utils::socket(our_address.family(), SOCK_STREAM, 0);
  1376. if (n == INVALID_SOCKET)
  1377. {
  1378. inet_error(false, port, "socket", isc_net_event_listen_err, INET_ERRNO);
  1379. }
  1380. int optval;
  1381. #ifndef WIN_NT
  1382. // dimitr: on Windows, lack of SO_REUSEADDR works the same way as it was specified on POSIX,
  1383. // i.e. it allows binding to a port in a TIME_WAIT/FIN_WAIT state. If this option
  1384. // is turned on explicitly, then a port can be re-bound regardless of its state,
  1385. // e.g. while it's listening. This is surely not what we want.
  1386. optval = TRUE;
  1387. if (setsockopt(n, SOL_SOCKET, SO_REUSEADDR, (SCHAR*) &optval, sizeof(optval)) < 0)
  1388. {
  1389. inet_error(false, port, "setsockopt REUSE", isc_net_event_listen_err, INET_ERRNO);
  1390. }
  1391. #endif
  1392. optval = port->getPortConfig()->getIPv6V6Only() ? 1 : 0;
  1393. // ignore failure, we already have it logged from the main listening port
  1394. setsockopt(n, IPPROTO_IPV6, IPV6_V6ONLY, (SCHAR*) &optval, sizeof(optval));
  1395. if (bind(n, our_address.ptr(), our_address.length()) < 0)
  1396. {
  1397. inet_error(false, port, "bind", isc_net_event_listen_err, INET_ERRNO);
  1398. }
  1399. if (our_address.getsockname(n) < 0)
  1400. {
  1401. inet_error(false, port, "getsockname", isc_net_event_listen_err, INET_ERRNO);
  1402. }
  1403. if (listen(n, 1) < 0)
  1404. {
  1405. inet_error(false, port, "listen", isc_net_event_listen_err, INET_ERRNO);
  1406. }
  1407. rem_port* const new_port = alloc_port(port->port_parent,
  1408. (port->port_flags & PORT_no_oob) | PORT_async | PORT_connecting);
  1409. port->port_async = new_port;
  1410. new_port->port_dummy_packet_interval = port->port_dummy_packet_interval;
  1411. new_port->port_dummy_timeout = new_port->port_dummy_packet_interval;
  1412. new_port->port_server_flags = port->port_server_flags;
  1413. new_port->port_channel = (int) n;
  1414. P_RESP* response = &packet->p_resp;
  1415. SockAddr port_address;
  1416. if (port_address.getsockname(port->port_handle) < 0)
  1417. inet_error(false, port, "getsockname", isc_net_event_listen_err, INET_ERRNO);
  1418. port_address.setPort(our_address.port());
  1419. // CORE-5902: MacOS has sockaddr struct layout different than one found in POSIX/Windows.
  1420. // This prevent usage of events when client or server is MacOS but the other end is not.
  1421. // Here we try to make this case work. However it's not bullet-proof for others platforms and architectures.
  1422. // A proper solution would be to just send the port number in a protocol friendly way.
  1423. bool macOsClient =
  1424. port->port_client_arch == arch_darwin_ppc ||
  1425. port->port_client_arch == arch_darwin_x64 ||
  1426. port->port_client_arch == arch_darwin_ppc64;
  1427. bool macOsServer =
  1428. ARCHITECTURE == arch_darwin_ppc ||
  1429. ARCHITECTURE == arch_darwin_x64 ||
  1430. ARCHITECTURE == arch_darwin_ppc64;
  1431. if (macOsServer && !macOsClient)
  1432. port_address.convertFromMacOsToPosixWindows();
  1433. else if (!macOsServer && macOsClient)
  1434. port_address.convertFromPosixWindowsToMacOs();
  1435. response->p_resp_data.cstr_length = (ULONG) port_address.length();
  1436. memcpy(response->p_resp_data.cstr_address, port_address.ptr(), port_address.length());
  1437. new_port->port_peer_name = port->port_peer_name;
  1438. return new_port;
  1439. }
  1440. #if !(defined WIN_NT)
  1441. static THREAD_ENTRY_DECLARE waitThread(THREAD_ENTRY_PARAM)
  1442. {
  1443. /**************************************
  1444. *
  1445. * w a i t T h r e a d
  1446. *
  1447. **************************************
  1448. *
  1449. * Functional description
  1450. * Waits for processes started by standalone classic server (avoid zombies)
  1451. *
  1452. **************************************/
  1453. while (procCount > 0)
  1454. {
  1455. int rc = wait(0);
  1456. MutexLockGuard guard(waitThreadMutex, FB_FUNCTION);
  1457. if (rc > 0) {
  1458. --procCount;
  1459. }
  1460. }
  1461. return 0;
  1462. }
  1463. #endif // !defined(WIN_NT)
  1464. static void disconnect(rem_port* port)
  1465. {
  1466. /**************************************
  1467. *
  1468. * d i s c o n n e c t
  1469. *
  1470. **************************************
  1471. *
  1472. * Functional description
  1473. * Break a remote connection.
  1474. *
  1475. **************************************/
  1476. // SO_LINGER was turned off on the initial bind when the server was started.
  1477. // This will force a reset to be sent to the client when the socket is closed.
  1478. // We only want this behavior in the case of the server terminating
  1479. // abnormally and not on an orderly shut down. Because of this, turn the
  1480. // SO_LINGER option back on for the socket. The result of setsockopt isn't
  1481. // too important at this stage since we are closing the socket anyway. This
  1482. // is an attempt to return the socket to a state where a graceful shutdown can
  1483. // occur.
  1484. if (port->port_linger.l_onoff)
  1485. {
  1486. setsockopt(port->port_handle, SOL_SOCKET, SO_LINGER,
  1487. (SCHAR*) &port->port_linger, sizeof(port->port_linger));
  1488. }
  1489. if (port->port_handle != INVALID_SOCKET)
  1490. {
  1491. shutdown(port->port_handle, 2);
  1492. }
  1493. MutexLockGuard guard(port_mutex, FB_FUNCTION);
  1494. if (port->port_state == rem_port::DISCONNECTED)
  1495. return;
  1496. port->port_state = rem_port::DISCONNECTED;
  1497. port->port_flags &= ~PORT_connecting;
  1498. if (port->port_async)
  1499. {
  1500. disconnect(port->port_async);
  1501. port->port_async = NULL;
  1502. }
  1503. port->port_context = NULL;
  1504. // hvlad: delay closing of the server sockets to prevent its reuse
  1505. // by another (newly accepted) port until next select() call. See
  1506. // also select_wait() function.
  1507. const bool delayClose = (port->port_server_flags && port->port_parent);
  1508. // If this is a sub-port, unlink it from its parent
  1509. port->unlinkParent();
  1510. inet_ports->unRegisterPort(port);
  1511. if (delayClose)
  1512. {
  1513. if (port->port_handle != INVALID_SOCKET)
  1514. ports_to_close->push(port->port_handle);
  1515. if (port->port_channel != INVALID_SOCKET)
  1516. ports_to_close->push(port->port_channel);
  1517. }
  1518. else
  1519. {
  1520. SOCLOSE(port->port_handle);
  1521. SOCLOSE(port->port_channel);
  1522. }
  1523. if (port->port_thread_guard && port->port_events_thread && !port->port_events_threadId.isCurrent())
  1524. port->port_thread_guard->setWait(port->port_events_thread);
  1525. else
  1526. port->releasePort();
  1527. #ifdef DEBUG
  1528. if (INET_trace & TRACE_summary)
  1529. {
  1530. fprintf(stdout, "INET_count_send = %u packets\n", INET_count_send);
  1531. fprintf(stdout, "INET_bytes_send = %u bytes\n", INET_bytes_send);
  1532. fprintf(stdout, "INET_count_recv = %u packets\n", INET_count_recv);
  1533. fprintf(stdout, "INET_bytes_recv = %u bytes\n", INET_bytes_recv);
  1534. fflush(stdout);
  1535. }
  1536. #endif
  1537. return;
  1538. }
  1539. static void force_close(rem_port* port)
  1540. {
  1541. /**************************************
  1542. *
  1543. * f o r c e _ c l o s e
  1544. *
  1545. **************************************
  1546. *
  1547. * Functional description
  1548. * Forcebly close remote connection.
  1549. *
  1550. **************************************/
  1551. if (port->port_async)
  1552. abort_aux_connection(port->port_async);
  1553. if (port->port_state != rem_port::PENDING)
  1554. return;
  1555. RefMutexGuard guard(*port->port_write_sync, FB_FUNCTION);
  1556. port->port_state = rem_port::BROKEN;
  1557. if (port->port_handle != INVALID_SOCKET)
  1558. {
  1559. shutdown(port->port_handle, 2);
  1560. SOCLOSE(port->port_handle);
  1561. }
  1562. }
  1563. static int cleanup_ports(const int, const int, void* /*arg*/)
  1564. {
  1565. /**************************************
  1566. *
  1567. * c l e a n u p _ p o r t s
  1568. *
  1569. **************************************
  1570. *
  1571. * Functional description
  1572. * Shutdown all active connections
  1573. * to allow correct shutdown.
  1574. *
  1575. **************************************/
  1576. INET_shutting_down = true;
  1577. inet_ports->closePorts();
  1578. while (ports_to_close->hasData())
  1579. {
  1580. SOCKET s = ports_to_close->pop();
  1581. SOCLOSE(s);
  1582. }
  1583. return 0;
  1584. }
  1585. #ifdef NO_FORK
  1586. static int fork()
  1587. {
  1588. /**************************************
  1589. *
  1590. * f o r k ( N O _ F O R K )
  1591. *
  1592. **************************************
  1593. *
  1594. * Functional description
  1595. * Hmmm.
  1596. *
  1597. **************************************/
  1598. return 1;
  1599. }
  1600. #endif
  1601. #ifdef WIN_NT
  1602. static int wsaExitHandler(const int, const int, void*)
  1603. {
  1604. /**************************************
  1605. *
  1606. * w s a E x i t H a n d l e r
  1607. *
  1608. **************************************
  1609. *
  1610. * Functional description
  1611. * Cleanup WSA.
  1612. *
  1613. **************************************/
  1614. SleepEx(0, FALSE); // let select in other thread(s) shutdown gracefully
  1615. WSACleanup();
  1616. return 0;
  1617. }
  1618. static int fork(SOCKET old_handle, USHORT flag)
  1619. {
  1620. /**************************************
  1621. *
  1622. * f o r k ( W I N _ N T )
  1623. *
  1624. **************************************
  1625. *
  1626. * Functional description
  1627. * Create a child process.
  1628. *
  1629. **************************************/
  1630. TEXT name[MAXPATHLEN];
  1631. GetModuleFileName(NULL, name, sizeof(name));
  1632. HANDLE new_handle;
  1633. if (!DuplicateHandle(GetCurrentProcess(), (HANDLE) old_handle,
  1634. GetCurrentProcess(), &new_handle,
  1635. 0, TRUE, DUPLICATE_SAME_ACCESS))
  1636. {
  1637. gds__log("INET/inet_error: fork/DuplicateHandle errno = %d", GetLastError());
  1638. return 0;
  1639. }
  1640. string cmdLine;
  1641. cmdLine.printf("%s -i -h %" HANDLEFORMAT"@%" ULONGFORMAT, name, new_handle, GetCurrentProcessId());
  1642. STARTUPINFO start_crud;
  1643. start_crud.cb = sizeof(STARTUPINFO);
  1644. start_crud.lpReserved = NULL;
  1645. start_crud.lpReserved2 = NULL;
  1646. start_crud.cbReserved2 = 0;
  1647. start_crud.lpDesktop = NULL;
  1648. start_crud.lpTitle = NULL;
  1649. start_crud.dwFlags = STARTF_FORCEOFFFEEDBACK;
  1650. PROCESS_INFORMATION pi;
  1651. if (CreateProcess(NULL, cmdLine.begin(), NULL, NULL, FALSE,
  1652. (flag & SRVR_high_priority ?
  1653. HIGH_PRIORITY_CLASS | DETACHED_PROCESS :
  1654. NORMAL_PRIORITY_CLASS | DETACHED_PROCESS),
  1655. NULL, NULL, &start_crud, &pi))
  1656. {
  1657. CloseHandle(pi.hThread);
  1658. CloseHandle(pi.hProcess);
  1659. // hvlad: child process will close our handle of just accepted socket
  1660. return 1;
  1661. }
  1662. gds__log("INET/inet_error: fork/CreateProcess errno = %d", GetLastError());
  1663. CloseHandle(new_handle);
  1664. return 0;
  1665. }
  1666. THREAD_ENTRY_DECLARE forkThread(THREAD_ENTRY_PARAM arg)
  1667. {
  1668. const USHORT flag = (USHORT)(U_IPTR) arg;
  1669. while (!INET_shutting_down)
  1670. {
  1671. if (WaitForSingleObject(forkEvent, INFINITE) != WAIT_OBJECT_0)
  1672. break;
  1673. while (!INET_shutting_down)
  1674. {
  1675. SOCKET s = 0;
  1676. { // scope
  1677. MutexLockGuard forkGuard(forkMutex, FB_FUNCTION);
  1678. if (!forkSockets || forkSockets->getCount() == 0)
  1679. break;
  1680. s = (*forkSockets)[0];
  1681. forkSockets->remove((FB_SIZE_T) 0);
  1682. }
  1683. fork(s, flag);
  1684. SOCLOSE(s);
  1685. }
  1686. }
  1687. return 0;
  1688. }
  1689. // Windows does not have an inet_aton function.
  1690. bool inet_aton(const char* name, in_addr* address)
  1691. {
  1692. address->s_addr = inet_addr(name);
  1693. return address->s_addr != INADDR_NONE;
  1694. }
  1695. #endif
  1696. static rem_port* receive( rem_port* main_port, PACKET * packet)
  1697. {
  1698. /**************************************
  1699. *
  1700. * r e c e i v e
  1701. *
  1702. **************************************
  1703. *
  1704. * Functional description
  1705. * Receive a message from a port or clients of a port. If the process
  1706. * is a server and a connection request comes in, generate a new port
  1707. * block for the client.
  1708. *
  1709. **************************************/
  1710. // loop as long as we are receiving dummy packets, just
  1711. // throwing them away--note that if we are a server we won't
  1712. // be receiving them, but it is better to check for them at
  1713. // this level rather than try to catch them in all places where
  1714. // this routine is called
  1715. do {
  1716. if (!xdr_protocol(main_port->port_receive, packet))
  1717. {
  1718. packet->p_operation = main_port->port_partial_data ? op_partial : op_exit;
  1719. if (packet->p_operation == op_exit)
  1720. main_port->port_state = rem_port::BROKEN;
  1721. main_port->port_partial_data = false;
  1722. break;
  1723. }
  1724. #ifdef DEBUG
  1725. {
  1726. static ULONG op_rec_count = 0;
  1727. op_rec_count++;
  1728. if (INET_trace & TRACE_operations)
  1729. {
  1730. fprintf(stdout, "%04u: OP Recd %5u opcode %d\n",
  1731. inet_debug_timer(),
  1732. op_rec_count, packet->p_operation);
  1733. fflush(stdout);
  1734. }
  1735. }
  1736. #endif
  1737. } while (packet->p_operation == op_dummy);
  1738. return main_port;
  1739. }
  1740. static bool select_multi(rem_port* main_port, UCHAR* buffer, SSHORT bufsize, SSHORT* length,
  1741. RemPortPtr& port)
  1742. {
  1743. /**************************************
  1744. *
  1745. * s e l e c t _ m u l t i
  1746. *
  1747. **************************************
  1748. *
  1749. * Functional description
  1750. * Receive an IP packet from a port or clients of a port.
  1751. * Used only by the multiclient server on main server's port.
  1752. * If a connection request comes in, generate a new port
  1753. * block for the client.
  1754. *
  1755. **************************************/
  1756. // This code is used to test error handling in main server loop
  1757. #ifdef NEVERDEF
  1758. static int dummyCnt = 0;
  1759. if (++dummyCnt % 64 == 0)
  1760. (Arg::Gds(isc_random) << "Simulated select_multi error").raise();
  1761. #endif
  1762. for (;;)
  1763. {
  1764. select_port(main_port, &INET_select, port);
  1765. if (port == main_port && (port->port_server_flags & SRVR_multi_client))
  1766. {
  1767. if (INET_shutting_down)
  1768. {
  1769. if (main_port->port_state == rem_port::PENDING)
  1770. {
  1771. main_port->port_state = rem_port::BROKEN;
  1772. shutdown(main_port->port_handle, 2);
  1773. SOCLOSE(main_port->port_handle);
  1774. }
  1775. }
  1776. else if ((port = select_accept(main_port)))
  1777. {
  1778. if (!REMOTE_inflate(port, packet_receive, buffer, bufsize, length))
  1779. {
  1780. *length = 0;
  1781. }
  1782. #ifdef WIRE_COMPRESS_SUPPORT
  1783. if (port->port_z_data)
  1784. INET_select->setZDataPort(port);
  1785. #endif
  1786. return (*length) ? true : false;
  1787. }
  1788. continue;
  1789. }
  1790. if (port)
  1791. {
  1792. if (port->port_dummy_timeout < 0)
  1793. {
  1794. port->port_dummy_timeout = port->port_dummy_packet_interval;
  1795. if (port->port_flags & PORT_async)
  1796. continue;
  1797. *length = 0;
  1798. return true;
  1799. }
  1800. if (!REMOTE_inflate(port, packet_receive, buffer, bufsize, length))
  1801. {
  1802. if (port->port_flags & (PORT_disconnect | PORT_connecting))
  1803. {
  1804. continue;
  1805. }
  1806. *length = 0;
  1807. }
  1808. #ifdef WIRE_COMPRESS_SUPPORT
  1809. if (port->port_z_data)
  1810. INET_select->setZDataPort(port);
  1811. #endif
  1812. return (*length) ? true : false;
  1813. }
  1814. if (!select_wait(main_port, &INET_select))
  1815. {
  1816. port = NULL;
  1817. return false;
  1818. }
  1819. }
  1820. }
  1821. static rem_port* select_accept( rem_port* main_port)
  1822. {
  1823. /**************************************
  1824. *
  1825. * s e l e c t _ a c c e p t
  1826. *
  1827. **************************************
  1828. *
  1829. * Functional description
  1830. * Accept a new connection request.
  1831. *
  1832. **************************************/
  1833. rem_port* const port = alloc_port(main_port);
  1834. inet_ports->registerPort(port);
  1835. port->port_handle = os_utils::accept(main_port->port_handle, NULL, NULL);
  1836. if (port->port_handle == INVALID_SOCKET)
  1837. {
  1838. inet_error(true, port, "accept", isc_net_connect_err, INET_ERRNO);
  1839. }
  1840. setKeepAlive(port->port_handle);
  1841. port->port_flags |= PORT_server;
  1842. if (main_port->port_server_flags & SRVR_thread_per_port)
  1843. {
  1844. port->port_server_flags = (SRVR_server | SRVR_inet | SRVR_thread_per_port);
  1845. return port;
  1846. }
  1847. return 0;
  1848. }
  1849. static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port)
  1850. {
  1851. /**************************************
  1852. *
  1853. * s e l e c t _ p o r t
  1854. *
  1855. **************************************
  1856. *
  1857. * Functional description
  1858. * Select a descriptor that is ready to read
  1859. * and return the port block. Additionally,
  1860. * check if a port's keepalive timer has
  1861. * expired and return the port block so that
  1862. * a keepalive packet can be queued. Return
  1863. * NULL if none are active.
  1864. *
  1865. **************************************/
  1866. MutexLockGuard guard(port_mutex, FB_FUNCTION);
  1867. while (true)
  1868. {
  1869. Select::HandleState result = selct->checkNext(port);
  1870. if (!port)
  1871. return;
  1872. switch (result)
  1873. {
  1874. case Select::SEL_BAD:
  1875. if (port->port_state == rem_port::BROKEN || (port->port_flags & PORT_connecting))
  1876. continue;
  1877. if (port->port_flags & PORT_async)
  1878. continue;
  1879. return;
  1880. case Select::SEL_DISCONNECTED:
  1881. continue;
  1882. case Select::SEL_READY:
  1883. port->port_dummy_timeout = port->port_dummy_packet_interval;
  1884. return;
  1885. default:
  1886. break;
  1887. }
  1888. if (port->port_dummy_timeout < 0)
  1889. return;
  1890. }
  1891. }
  1892. static bool select_wait( rem_port* main_port, Select* selct)
  1893. {
  1894. /**************************************
  1895. *
  1896. * s e l e c t _ w a i t
  1897. *
  1898. **************************************
  1899. *
  1900. * Functional description
  1901. * Select interesting descriptors from
  1902. * port blocks and wait for something
  1903. * to read from them.
  1904. *
  1905. **************************************/
  1906. struct timeval timeout;
  1907. bool checkPorts = false;
  1908. for (;;)
  1909. {
  1910. selct->clear();
  1911. bool found = false;
  1912. // Use the time interval between select() calls to expire
  1913. // keepalive timers on all ports.
  1914. time_t delta_time;
  1915. if (selct->slct_time)
  1916. {
  1917. delta_time = time(NULL) - selct->slct_time;
  1918. selct->slct_time += delta_time;
  1919. }
  1920. else
  1921. {
  1922. delta_time = 0;
  1923. selct->slct_time = time(NULL);
  1924. }
  1925. { // port_mutex scope
  1926. MutexLockGuard guard(port_mutex, FB_FUNCTION);
  1927. while (ports_to_close->hasData())
  1928. {
  1929. SOCKET s = ports_to_close->pop();
  1930. SOCLOSE(s);
  1931. }
  1932. for (rem_port* port = main_port; port; port = port->port_next)
  1933. {
  1934. if (port->port_state == rem_port::PENDING &&
  1935. // don't wait on still listening (not connected) async port
  1936. !(port->port_handle == INVALID_SOCKET && (port->port_flags & PORT_async)))
  1937. {
  1938. // Adjust down the port's keepalive timer.
  1939. if (port->port_dummy_packet_interval)
  1940. {
  1941. port->port_dummy_timeout -= delta_time;
  1942. }
  1943. if (checkPorts)
  1944. {
  1945. // select() returned EBADF\WSAENOTSOCK - we have a broken socket
  1946. // in current fdset. Search and return it to caller to close
  1947. // broken connection correctly
  1948. struct linger lngr;
  1949. socklen_t optlen = sizeof(lngr);
  1950. const bool badSocket =
  1951. #ifdef WIN_NT
  1952. false;
  1953. #else
  1954. (port->port_handle < 0 || port->port_handle >= FD_SETSIZE);
  1955. #endif
  1956. if (badSocket || getsockopt(port->port_handle,
  1957. SOL_SOCKET, SO_LINGER, (SCHAR*) &lngr, &optlen) != 0)
  1958. {
  1959. if (badSocket || INET_ERRNO == NOTASOCKET)
  1960. {
  1961. // not a socket, strange !
  1962. gds__log("INET/select_wait: found \"not a socket\" socket : %" HANDLEFORMAT,
  1963. port->port_handle);
  1964. // this will lead to receive() which will break bad connection
  1965. selct->clear();
  1966. if (!badSocket)
  1967. {
  1968. selct->set(port->port_handle);
  1969. }
  1970. return true;
  1971. }
  1972. }
  1973. }
  1974. // if process is shuting down - don't listen on main port
  1975. if (!INET_shutting_down || port != main_port)
  1976. {
  1977. selct->set(port->port_handle);
  1978. found = true;
  1979. }
  1980. }
  1981. }
  1982. checkPorts = false;
  1983. } // port_mutex scope
  1984. if (!found)
  1985. {
  1986. if (!INET_shutting_down && (main_port->port_server_flags & SRVR_multi_client))
  1987. gds__log("INET/select_wait: client rundown complete, server exiting");
  1988. return false;
  1989. }
  1990. for (;;)
  1991. {
  1992. // Before waiting for incoming packet, check for server shutdown
  1993. if (tryStopMainThread && tryStopMainThread())
  1994. {
  1995. // this is not server port any more
  1996. main_port->port_server_flags &= ~SRVR_multi_client;
  1997. return false;
  1998. }
  1999. // Some platforms change the timeout in the select call.
  2000. // Reset timeout for each iteration to avoid problems.
  2001. timeout.tv_sec = SELECT_TIMEOUT;
  2002. timeout.tv_usec = 0;
  2003. selct->select(&timeout);
  2004. const int inetErrNo = INET_ERRNO;
  2005. //if (INET_shutting_down) {
  2006. // return false;
  2007. //}
  2008. if (selct->getCount() != -1)
  2009. {
  2010. RemPortPtr p(main_port);
  2011. selct->checkStart(p);
  2012. // if selct->slct_count is zero it means that we timed out of
  2013. // select with nothing to read or accept, so clear the fd_set
  2014. // bit as this value is undefined on some platforms (eg. HP-UX),
  2015. // when the select call times out. Once these bits are cleared
  2016. // they can be used in select_port()
  2017. if (selct->getCount() == 0)
  2018. {
  2019. MutexLockGuard guard(port_mutex, FB_FUNCTION);
  2020. for (rem_port* port = main_port; port; port = port->port_next)
  2021. {
  2022. selct->unset(port->port_handle);
  2023. }
  2024. }
  2025. return true;
  2026. }
  2027. if (INTERRUPT_ERROR(inetErrNo))
  2028. continue;
  2029. if (inetErrNo == NOTASOCKET)
  2030. {
  2031. checkPorts = true;
  2032. break;
  2033. }
  2034. gds__log("INET/select_wait: select failed, errno = %d", inetErrNo);
  2035. return false;
  2036. } // for (;;)
  2037. }
  2038. }
  2039. static int send_full( rem_port* port, PACKET * packet)
  2040. {
  2041. /**************************************
  2042. *
  2043. * s e n d _ f u l l
  2044. *
  2045. **************************************
  2046. *
  2047. * Functional description
  2048. * Send a packet across a port to another process.
  2049. *
  2050. **************************************/
  2051. if (!xdr_protocol(port->port_send, packet))
  2052. return false;
  2053. #ifdef DEBUG
  2054. { // scope
  2055. static ULONG op_sent_count = 0;
  2056. op_sent_count++;
  2057. if (INET_trace & TRACE_operations)
  2058. {
  2059. fprintf(stdout, "%05u: OP Sent %5u opcode %d\n", inet_debug_timer(),
  2060. op_sent_count, packet->p_operation);
  2061. fflush(stdout);
  2062. }
  2063. } // end scope
  2064. #endif
  2065. return REMOTE_deflate(port->port_send, inet_write, packet_send, true);
  2066. }
  2067. static int send_partial( rem_port* port, PACKET * packet)
  2068. {
  2069. /**************************************
  2070. *
  2071. * s e n d _ p a r t i a l
  2072. *
  2073. **************************************
  2074. *
  2075. * Functional description
  2076. * Send a packet across a port to another process.
  2077. *
  2078. **************************************/
  2079. #ifdef DEBUG
  2080. { // scope
  2081. static ULONG op_sentp_count = 0;
  2082. op_sentp_count++;
  2083. if (INET_trace & TRACE_operations)
  2084. {
  2085. fprintf(stdout, "%05u: OP Sent %5u opcode %d (partial)\n", inet_debug_timer(),
  2086. op_sentp_count, packet->p_operation);
  2087. fflush(stdout);
  2088. }
  2089. } // end scope
  2090. #endif
  2091. return xdr_protocol(port->port_send, packet);
  2092. }
  2093. RemoteXdr* xdrinet_create(rem_port* port, UCHAR* buffer, USHORT length, enum xdr_op x_op)
  2094. {
  2095. /**************************************
  2096. *
  2097. * x d r i n e t _ c r e a t e
  2098. *
  2099. **************************************
  2100. *
  2101. * Functional description
  2102. * Initialize an XDR stream.
  2103. *
  2104. **************************************/
  2105. RemoteXdr* xdrs = FB_NEW InetXdr;
  2106. xdrs->x_public = port;
  2107. xdrs->create(reinterpret_cast<SCHAR*>(buffer), length, x_op);
  2108. return xdrs;
  2109. }
  2110. #ifdef HAVE_SETITIMER
  2111. static void alarm_handler( int x)
  2112. {
  2113. /**************************************
  2114. *
  2115. * a l a r m _ h a n d l e r
  2116. *
  2117. **************************************
  2118. *
  2119. * Functional description
  2120. * Handle an alarm clock interrupt. If we were waiting on
  2121. * a semaphone, zap it.
  2122. *
  2123. **************************************/
  2124. }
  2125. #endif
  2126. void get_peer_info(rem_port* port)
  2127. {
  2128. /**************************************
  2129. *
  2130. * g e t _ p e e r _ i n f o
  2131. *
  2132. **************************************
  2133. *
  2134. * Functional description
  2135. * Port just connected. Obtain some info about connection and peer.
  2136. *
  2137. **************************************/
  2138. port->port_protocol_id = "TCPv4";
  2139. SockAddr address;
  2140. if (address.getpeername(port->port_handle) == 0)
  2141. {
  2142. address.unmapV4(); // convert mapped IPv4 to regular IPv4
  2143. char host[64]; // 32 digits, 7 colons, 1 trailing null byte
  2144. char serv[16];
  2145. int nameinfo = getnameinfo(address.ptr(), address.length(), host, sizeof(host),
  2146. serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
  2147. if (!nameinfo)
  2148. port->port_address.printf("%s/%s", host, serv);
  2149. if (address.family() == AF_INET6)
  2150. port->port_protocol_id = "TCPv6";
  2151. }
  2152. }
  2153. static void inet_gen_error(bool releasePort, rem_port* port, const Arg::StatusVector& v)
  2154. {
  2155. /**************************************
  2156. *
  2157. * i n e t _ g e n _ e r r o r
  2158. *
  2159. **************************************
  2160. *
  2161. * Functional description
  2162. * An error has occurred. Mark the port as broken.
  2163. * Format the status vector if there is one and
  2164. * save the status vector strings in a permanent place.
  2165. *
  2166. **************************************/
  2167. port->port_state = rem_port::BROKEN;
  2168. string node_name(port->port_connection ? port->port_connection->str_data : "(unknown)");
  2169. if (releasePort)
  2170. {
  2171. disconnect(port);
  2172. }
  2173. Arg::Gds error(isc_network_error);
  2174. error << Arg::Str(node_name) << v;
  2175. error.raise();
  2176. }
  2177. bool_t InetXdr::x_getbytes(SCHAR* buff, unsigned bytecount)
  2178. {
  2179. /**************************************
  2180. *
  2181. * i n e t _ g e t b y t e s
  2182. *
  2183. **************************************
  2184. *
  2185. * Functional description
  2186. * Get a bunch of bytes from a memory stream if it fits.
  2187. *
  2188. **************************************/
  2189. if (x_public->port_flags & PORT_server)
  2190. return REMOTE_getbytes(this, buff, bytecount);
  2191. // Use memcpy to optimize bulk transfers.
  2192. while (bytecount > sizeof(ISC_QUAD))
  2193. {
  2194. if (x_handy >= bytecount)
  2195. {
  2196. memcpy(buff, x_private, bytecount);
  2197. x_private += bytecount;
  2198. x_handy -= bytecount;
  2199. return TRUE;
  2200. }
  2201. if (x_handy > 0)
  2202. {
  2203. memcpy(buff, x_private, x_handy);
  2204. x_private += x_handy;
  2205. buff += x_handy;
  2206. bytecount -= x_handy;
  2207. x_handy = 0;
  2208. }
  2209. if (!inet_read(this))
  2210. return FALSE;
  2211. }
  2212. // Scalar values and bulk transfer remainder fall thru
  2213. // to be moved byte-by-byte to avoid memcpy setup costs.
  2214. if (!bytecount)
  2215. return TRUE;
  2216. if (x_handy >= bytecount)
  2217. {
  2218. x_handy -= bytecount;
  2219. while (bytecount--)
  2220. *buff++ = *x_private++;
  2221. return TRUE;
  2222. }
  2223. while (bytecount--)
  2224. {
  2225. if (x_handy == 0 && !inet_read(this))
  2226. return FALSE;
  2227. *buff++ = *x_private++;
  2228. --x_handy;
  2229. }
  2230. return TRUE;
  2231. }
  2232. static void inet_error(bool releasePort, rem_port* port, const TEXT* function, ISC_STATUS operation, int status)
  2233. {
  2234. /**************************************
  2235. *
  2236. * i n e t _ e r r o r
  2237. *
  2238. **************************************
  2239. *
  2240. * Functional description
  2241. * An I/O error has occurred. Call
  2242. * inet_gen_error with the appropriate args
  2243. * to format the status vector if any.
  2244. *
  2245. **************************************/
  2246. if (status)
  2247. {
  2248. if (port->port_state == rem_port::PENDING)
  2249. {
  2250. string err;
  2251. err.printf("INET/inet_error: %s errno = %d", function, status);
  2252. if (port->port_peer_name.hasData() || port->port_address.hasData())
  2253. {
  2254. err.append(port->port_flags & PORT_async ? ", aux " : ", ");
  2255. err.append(port->port_server_flags ? "client" : "server");
  2256. if (port->port_peer_name.hasData())
  2257. {
  2258. err.append(" host = ");
  2259. err.append(port->port_peer_name);
  2260. }
  2261. if (port->port_address.hasData())
  2262. {
  2263. if (port->port_peer_name.hasData())
  2264. err.append(",");
  2265. err.append(" address = ");
  2266. err.append(port->port_address);
  2267. }
  2268. }
  2269. if (port->port_user_name.hasData())
  2270. {
  2271. err.append(", user = ");
  2272. err.append(port->port_user_name);
  2273. }
  2274. // Address could contain percent sign inside, therefore make
  2275. // sure error string not used as printf format string.
  2276. gds__log("%s", err.c_str());
  2277. }
  2278. inet_gen_error(releasePort, port, Arg::Gds(operation) << SYS_ERR(status));
  2279. }
  2280. else
  2281. {
  2282. // No status value, just format the basic arguments.
  2283. inet_gen_error(releasePort, port, Arg::Gds(operation));
  2284. }
  2285. }
  2286. bool_t InetXdr::x_putbytes(const SCHAR* buff, unsigned bytecount)
  2287. {
  2288. /**************************************
  2289. *
  2290. * i n e t _ p u t b y t e s
  2291. *
  2292. **************************************
  2293. *
  2294. * Functional description
  2295. * Put a bunch of bytes to a memory stream if it fits.
  2296. *
  2297. **************************************/
  2298. // Use memcpy to optimize bulk transfers.
  2299. while (bytecount > sizeof(ISC_QUAD))
  2300. {
  2301. if (x_handy >= bytecount)
  2302. {
  2303. memcpy(x_private, buff, bytecount);
  2304. x_private += bytecount;
  2305. x_handy -= bytecount;
  2306. return TRUE;
  2307. }
  2308. if (x_handy > 0)
  2309. {
  2310. memcpy(x_private, buff, x_handy);
  2311. x_private += x_handy;
  2312. buff += x_handy;
  2313. bytecount -= x_handy;
  2314. x_handy = 0;
  2315. }
  2316. if (!REMOTE_deflate(this, inet_write, packet_send, false))
  2317. {
  2318. return FALSE;
  2319. }
  2320. }
  2321. // Scalar values and bulk transfer remainder fall thru
  2322. // to be moved byte-by-byte to avoid memcpy setup costs.
  2323. if (!bytecount)
  2324. return TRUE;
  2325. if (x_handy >= bytecount)
  2326. {
  2327. x_handy -= bytecount;
  2328. while (bytecount--)
  2329. *x_private++ = *buff++;
  2330. return TRUE;
  2331. }
  2332. while (bytecount--)
  2333. {
  2334. if (x_handy == 0 && !REMOTE_deflate(this, inet_write, packet_send, false))
  2335. return FALSE;
  2336. --x_handy;
  2337. *x_private++ = *buff++;
  2338. }
  2339. return TRUE;
  2340. }
  2341. static bool inet_read( RemoteXdr* xdrs)
  2342. {
  2343. /**************************************
  2344. *
  2345. * i n e t _ r e a d
  2346. *
  2347. **************************************
  2348. *
  2349. * Functional description
  2350. * Read a buffer full of data. If we receive a bad packet,
  2351. * send the moral equivalent of a NAK and retry. ACK all
  2352. * partial packets. Don't ACK the last packet -- the next
  2353. * message sent will handle this.
  2354. *
  2355. **************************************/
  2356. rem_port* port = xdrs->x_public;
  2357. char* p = xdrs->x_base;
  2358. const char* const end = p + INET_remote_buffer;
  2359. // If buffer is not completely empty, slide down what's left
  2360. if (xdrs->x_handy > 0)
  2361. {
  2362. memmove(p, xdrs->x_private, xdrs->x_handy);
  2363. p += xdrs->x_handy;
  2364. }
  2365. SSHORT length = end - p;
  2366. port->port_z_data = false;
  2367. if (!REMOTE_inflate(port, packet_receive2, (UCHAR*)p, length, &length))
  2368. return false;
  2369. p += length;
  2370. xdrs->x_handy = (SCHAR *) p - xdrs->x_base;
  2371. xdrs->x_private = xdrs->x_base;
  2372. return true;
  2373. }
  2374. static bool packet_receive2(rem_port* port, UCHAR* p, SSHORT bufSize, SSHORT* length)
  2375. {
  2376. *length = 0;
  2377. while (true)
  2378. {
  2379. SSHORT l = bufSize - *length;
  2380. if (!packet_receive(port, p + *length, l, &l))
  2381. return false;
  2382. if (l >= 0)
  2383. {
  2384. *length += l;
  2385. break;
  2386. }
  2387. *length -= l;
  2388. if (!packet_send(port, 0, 0))
  2389. return false;
  2390. }
  2391. return true;
  2392. }
  2393. static rem_port* inet_try_connect(PACKET* packet,
  2394. Rdb* rdb,
  2395. const PathName& file_name,
  2396. const TEXT* node_name,
  2397. ClumpletReader& dpb,
  2398. RefPtr<const Config>* config,
  2399. const PathName* ref_db_name,
  2400. int af)
  2401. {
  2402. /**************************************
  2403. *
  2404. * i n e t _ t r y _ c o n n e c t
  2405. *
  2406. **************************************
  2407. *
  2408. * Functional description
  2409. * Given a packet with formatted protocol infomation,
  2410. * set header information and try the connection.
  2411. *
  2412. * If a connection is established, return a port block, otherwise
  2413. * return NULL.
  2414. *
  2415. **************************************/
  2416. P_CNCT* cnct = &packet->p_cnct;
  2417. packet->p_operation = op_connect;
  2418. cnct->p_cnct_operation = 0;
  2419. cnct->p_cnct_cversion = CONNECT_VERSION3;
  2420. cnct->p_cnct_client = ARCHITECTURE;
  2421. const PathName& cnct_file(ref_db_name ? (*ref_db_name) : file_name);
  2422. cnct->p_cnct_file.cstr_length = (ULONG) cnct_file.length();
  2423. cnct->p_cnct_file.cstr_address = reinterpret_cast<const UCHAR*>(cnct_file.c_str());
  2424. // If we can't talk to a server, punt. Let somebody else generate
  2425. // an error. status_vector will have the network error info.
  2426. rem_port* port = NULL;
  2427. try
  2428. {
  2429. port = INET_connect(node_name, packet, false, &dpb, config, af);
  2430. }
  2431. catch (const Exception&)
  2432. {
  2433. delete rdb;
  2434. throw;
  2435. }
  2436. // Get response packet from server.
  2437. rdb->rdb_port = port;
  2438. port->port_context = rdb;
  2439. if (!port->receive(packet))
  2440. {
  2441. rdb->rdb_port = NULL;
  2442. delete rdb;
  2443. inet_error(true, port, "receive in try_connect", isc_net_connect_err, INET_ERRNO);
  2444. }
  2445. return port;
  2446. }
  2447. static bool inet_write(RemoteXdr* xdrs)
  2448. {
  2449. /**************************************
  2450. *
  2451. * i n e t _ w r i t e
  2452. *
  2453. **************************************
  2454. *
  2455. * Functional description
  2456. * Write a buffer full of data.
  2457. *
  2458. **************************************/
  2459. // Encode the data portion of the packet
  2460. rem_port* port = xdrs->x_public;
  2461. const char* p = xdrs->x_base;
  2462. USHORT length = xdrs->x_private - p;
  2463. // Send data in manageable hunks. If a packet is partial, indicate
  2464. // that with a negative length. A positive length marks the end.
  2465. while (length)
  2466. {
  2467. const SSHORT l = (SSHORT) MIN(length, INET_remote_buffer);
  2468. length -= l;
  2469. if (!packet_send(port, p, (SSHORT) (length ? -l : l)))
  2470. return false;
  2471. p += l;
  2472. }
  2473. xdrs->x_private = xdrs->x_base;
  2474. xdrs->x_handy = INET_remote_buffer;
  2475. return true;
  2476. }
  2477. #ifdef DEBUG
  2478. static void packet_print(const TEXT* string, const UCHAR* packet, int length, ULONG counter)
  2479. {
  2480. /**************************************
  2481. *
  2482. * p a c k e t _ p r i n t
  2483. *
  2484. **************************************
  2485. *
  2486. * Functional description
  2487. * Print a summary of packet.
  2488. *
  2489. **************************************/
  2490. int sum = 0;
  2491. for (int l = length; l > 0; --l)
  2492. sum += *packet++;
  2493. fprintf(stdout, "%05u: PKT %s\t(%u): length = %4d, checksum = %d\n",
  2494. inet_debug_timer(), string, counter, length, sum);
  2495. fflush(stdout);
  2496. }
  2497. #endif
  2498. static bool packet_receive(rem_port* port, UCHAR* buffer, SSHORT buffer_length, SSHORT* length)
  2499. {
  2500. /**************************************
  2501. *
  2502. * p a c k e t _ r e c e i v e
  2503. *
  2504. **************************************
  2505. *
  2506. * Functional description
  2507. * Receive a packet and pass on it's goodness. If it's good,
  2508. * return true and the reported length of the packet, and update
  2509. * the receive sequence number. If it's bad, return false. If it's
  2510. * a duplicate message, just ignore it.
  2511. *
  2512. **************************************/
  2513. if (port->port_flags & PORT_disconnect) {
  2514. return false;
  2515. }
  2516. timeval timeout;
  2517. timeout.tv_usec = 0;
  2518. timeval* time_ptr = NULL;
  2519. if (port->port_protocol == 0)
  2520. {
  2521. // If the protocol is 0 we are still in the process of establishing
  2522. // a connection. Add a time out to the wait.
  2523. timeout.tv_sec = port->port_connect_timeout;
  2524. time_ptr = &timeout;
  2525. }
  2526. else if (port->port_dummy_packet_interval > 0)
  2527. {
  2528. // Set the time interval for sending dummy packets to the client
  2529. timeout.tv_sec = port->port_dummy_packet_interval;
  2530. time_ptr = &timeout;
  2531. }
  2532. // On Linux systems (and possibly others too) select will eventually
  2533. // change timout values so save it here for later reuse.
  2534. // Thanks to Brad Pepers who reported this bug FSG 3 MAY 2001
  2535. const timeval savetime = timeout;
  2536. const SOCKET ph = port->port_handle;
  2537. if (ph == INVALID_SOCKET)
  2538. {
  2539. const bool releasePort = (port->port_flags & PORT_server);
  2540. if (!(port->port_flags & PORT_disconnect) && releasePort)
  2541. inet_error(true, port, "invalid socket in packet_receive", isc_net_read_err, EINVAL);
  2542. return false;
  2543. }
  2544. // Unsed to send a dummy packet, but too big to be defined in the loop.
  2545. PACKET packet;
  2546. int n = 0;
  2547. int inetErrNo;
  2548. LocalStatus ls;
  2549. CheckStatusWrapper st(&ls);
  2550. for (;;)
  2551. {
  2552. // Implement an error-detection protocol to ensure that the client
  2553. // is still there. Use the select() call with a timeout to wait on
  2554. // the connection for an incoming packet. If none comes within a
  2555. // suitable time interval, write a dummy packet on the connection.
  2556. // If the client is not there, an error will be returned on the write.
  2557. // If the client is there, the dummy packet will be ignored by all
  2558. // InterBase clients V4 or greater. This protocol will detect when
  2559. // clients are lost abnormally through reboot or network disconnect.
  2560. // Don't send op_dummy packets on aux port; the server won't
  2561. // read them because it only writes to aux ports.
  2562. if ( !(port->port_flags & PORT_async) )
  2563. {
  2564. Select slct;
  2565. slct.set(ph);
  2566. int slct_count;
  2567. for (;;)
  2568. {
  2569. slct.select(time_ptr);
  2570. slct_count = slct.getCount();
  2571. inetErrNo = INET_ERRNO;
  2572. // restore original timeout value FSG 3 MAY 2001
  2573. timeout = savetime;
  2574. if (slct_count != -1 || !INTERRUPT_ERROR(inetErrNo))
  2575. {
  2576. break;
  2577. }
  2578. }
  2579. if (slct_count == -1)
  2580. {
  2581. if (!(port->port_flags & PORT_disconnect))
  2582. {
  2583. try
  2584. {
  2585. inet_error(false, port, "select in packet_receive", isc_net_read_err, inetErrNo);
  2586. }
  2587. catch (const Exception&) { }
  2588. }
  2589. return false;
  2590. }
  2591. if (!slct_count)
  2592. {
  2593. if (port->port_protocol == 0)
  2594. return false;
  2595. #ifdef DEBUG
  2596. if (INET_trace & TRACE_operations)
  2597. {
  2598. fprintf(stdout, "%05u: OP Sent: op_dummy\n", inet_debug_timer());
  2599. fflush(stdout);
  2600. }
  2601. #endif
  2602. packet.p_operation = op_dummy;
  2603. if (!send_full(port, &packet))
  2604. {
  2605. return false;
  2606. }
  2607. continue;
  2608. }
  2609. }
  2610. n = recv(port->port_handle, reinterpret_cast<char*>(buffer), buffer_length, 0);
  2611. inetErrNo = INET_ERRNO;
  2612. // decrypt
  2613. if (n > 0 && port->port_crypt_plugin)
  2614. {
  2615. port->port_crypt_plugin->decrypt(&st, n, buffer, buffer);
  2616. if (st.getState() & Firebird::IStatus::STATE_ERRORS)
  2617. {
  2618. status_exception::raise(&st);
  2619. }
  2620. }
  2621. if (n != -1 || !INTERRUPT_ERROR(inetErrNo))
  2622. break;
  2623. }
  2624. if (n <= 0 && (port->port_flags & PORT_disconnect)) {
  2625. return false;
  2626. }
  2627. if (n == -1)
  2628. {
  2629. try
  2630. {
  2631. inet_error(false, port, "read", isc_net_read_err, inetErrNo);
  2632. }
  2633. catch (const Exception&) { }
  2634. return false;
  2635. }
  2636. if (!n)
  2637. {
  2638. port->port_state = rem_port::BROKEN;
  2639. return false;
  2640. }
  2641. #ifdef DEBUG
  2642. { // scope
  2643. INET_count_recv++;
  2644. INET_bytes_recv += n;
  2645. if (INET_trace & TRACE_packets)
  2646. packet_print("receive", buffer, n, INET_count_recv);
  2647. INET_force_error--;
  2648. if (INET_force_error == 0)
  2649. {
  2650. INET_force_error = 1;
  2651. try
  2652. {
  2653. inet_error(false, port, "simulated error - read", isc_net_read_err);
  2654. }
  2655. catch (const Exception&) { }
  2656. return false;
  2657. }
  2658. } // end scope
  2659. #endif
  2660. port->port_rcv_packets++;
  2661. port->port_rcv_bytes += n;
  2662. *length = n;
  2663. return true;
  2664. }
  2665. static bool packet_send( rem_port* port, const SCHAR* buffer, SSHORT buffer_length)
  2666. {
  2667. /**************************************
  2668. *
  2669. * p a c k e t _ s e n d
  2670. *
  2671. **************************************
  2672. *
  2673. * Functional description
  2674. * Send some data on it's way.
  2675. *
  2676. **************************************/
  2677. SSHORT length = buffer_length;
  2678. const char* data = buffer;
  2679. // encrypt
  2680. HalfStaticArray<char, BUFFER_TINY> b;
  2681. if (port->port_crypt_plugin && port->port_crypt_complete)
  2682. {
  2683. LocalStatus ls;
  2684. CheckStatusWrapper st(&ls);
  2685. char* d = b.getBuffer(buffer_length);
  2686. port->port_crypt_plugin->encrypt(&st, buffer_length, data, d);
  2687. if (st.getState() & Firebird::IStatus::STATE_ERRORS)
  2688. {
  2689. status_exception::raise(&st);
  2690. }
  2691. data = d;
  2692. }
  2693. while (length)
  2694. {
  2695. #ifdef DEBUG
  2696. if (INET_trace & TRACE_operations)
  2697. {
  2698. fprintf(stdout, "Before Send\n");
  2699. fflush(stdout);
  2700. }
  2701. #endif
  2702. SSHORT n = send(port->port_handle, data, length, FB_SEND_FLAGS);
  2703. #if COMPRESS_DEBUG > 1
  2704. fprintf(stderr, "send(%d, %p, %d, FB_SEND_FLAGS) == %d\n", port->port_handle, data, length, n);
  2705. #endif
  2706. #ifdef DEBUG
  2707. if (INET_trace & TRACE_operations)
  2708. {
  2709. fprintf(stdout, "After Send n is %d\n", n);
  2710. fflush(stdout);
  2711. }
  2712. #endif
  2713. if (n == length) {
  2714. break;
  2715. }
  2716. if (n == -1)
  2717. {
  2718. if (INTERRUPT_ERROR(INET_ERRNO)) {
  2719. continue;
  2720. }
  2721. try
  2722. {
  2723. inet_error(false, port, "send", isc_net_write_err, INET_ERRNO);
  2724. }
  2725. catch (const Exception&) { }
  2726. return false;
  2727. }
  2728. data += n;
  2729. length -= n;
  2730. }
  2731. #ifdef HAVE_SETITIMER
  2732. struct itimerval internal_timer, client_timer;
  2733. struct sigaction internal_handler, client_handler;
  2734. #endif // HAVE_SETITIMER
  2735. if ((port->port_flags & PORT_async) && !(port->port_flags & PORT_no_oob))
  2736. {
  2737. int count = 0;
  2738. SSHORT n;
  2739. int inetErrNo = 0;
  2740. const char* b = buffer;
  2741. while ((n = send(port->port_handle, b, 1, MSG_OOB | FB_SEND_FLAGS)) == -1 &&
  2742. (INET_ERRNO == ENOBUFS || INTERRUPT_ERROR(INET_ERRNO)))
  2743. {
  2744. inetErrNo = INET_ERRNO;
  2745. if (count++ > 20) {
  2746. break;
  2747. }
  2748. #ifndef HAVE_SETITIMER
  2749. #ifdef WIN_NT
  2750. SleepEx(50, TRUE);
  2751. #else
  2752. sleep(1);
  2753. #endif
  2754. } // end of while() loop for systems without setitimer.
  2755. #else // HAVE_SETITIMER
  2756. if (count == 1)
  2757. {
  2758. // Wait in a loop until the lock becomes available
  2759. internal_timer.it_interval.tv_sec = 0;
  2760. internal_timer.it_interval.tv_usec = 0;
  2761. internal_timer.it_value.tv_sec = 0;
  2762. internal_timer.it_value.tv_usec = 0;
  2763. setitimer(ITIMER_REAL, &internal_timer, &client_timer);
  2764. internal_handler.sa_handler = alarm_handler;
  2765. sigemptyset(&internal_handler.sa_mask);
  2766. internal_handler.sa_flags = SA_RESTART;
  2767. sigaction(SIGALRM, &internal_handler, &client_handler);
  2768. }
  2769. internal_timer.it_value.tv_sec = 0;
  2770. internal_timer.it_value.tv_usec = 50000;
  2771. setitimer(ITIMER_REAL, &internal_timer, NULL);
  2772. pause();
  2773. } // end of while() loop for systems with setitimer
  2774. if (count)
  2775. {
  2776. // Restore user's outstanding alarm request and handler
  2777. internal_timer.it_value.tv_sec = 0;
  2778. internal_timer.it_value.tv_usec = 0;
  2779. setitimer(ITIMER_REAL, &internal_timer, NULL);
  2780. sigaction(SIGALRM, &client_handler, NULL);
  2781. setitimer(ITIMER_REAL, &client_timer, NULL);
  2782. }
  2783. #endif // HAVE_SETITIMER
  2784. if (n == -1)
  2785. {
  2786. try
  2787. {
  2788. inet_error(false, port, "send/oob", isc_net_write_err, inetErrNo);
  2789. }
  2790. catch (const Exception&) { }
  2791. return false;
  2792. }
  2793. }
  2794. #ifdef DEBUG
  2795. { // scope
  2796. INET_count_send++;
  2797. INET_bytes_send += buffer_length;
  2798. if (INET_trace & TRACE_packets)
  2799. packet_print("send", (const UCHAR*) buffer, buffer_length, INET_count_send);
  2800. INET_force_error--;
  2801. if (INET_force_error == 0)
  2802. {
  2803. INET_force_error = 1;
  2804. try
  2805. {
  2806. inet_error(false, port, "simulated error - send", isc_net_write_err, 0);
  2807. }
  2808. catch (const Exception&) { }
  2809. return false;
  2810. }
  2811. } // end scope
  2812. #endif
  2813. port->port_snd_packets++;
  2814. port->port_snd_bytes += buffer_length;
  2815. return true;
  2816. }
  2817. static bool setNoNagleOption(rem_port* port)
  2818. {
  2819. /**************************************
  2820. *
  2821. * s e t N o N a g l e O p t i o n
  2822. *
  2823. **************************************
  2824. *
  2825. * Functional description
  2826. * Set TCP_NODELAY, return false
  2827. * in case of unexpected error
  2828. *
  2829. **************************************/
  2830. if (port->getPortConfig()->getTcpNoNagle())
  2831. {
  2832. int optval = TRUE;
  2833. int n = setsockopt(port->port_handle, IPPROTO_TCP, TCP_NODELAY,
  2834. (SCHAR*) &optval, sizeof(optval));
  2835. if (n == -1)
  2836. {
  2837. return false;
  2838. }
  2839. }
  2840. return true;
  2841. }
  2842. static bool setKeepAlive(SOCKET s)
  2843. {
  2844. /**************************************
  2845. *
  2846. * s e t K e e p A l i v e
  2847. *
  2848. **************************************
  2849. *
  2850. * Functional description
  2851. * Set SO_KEEPALIVE, return false
  2852. * in case of unexpected error
  2853. *
  2854. **************************************/
  2855. int optval = 1;
  2856. int n = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
  2857. (SCHAR*) &optval, sizeof(optval));
  2858. return n != -1;
  2859. }
  2860. void setStopMainThread(FPTR_INT func)
  2861. {
  2862. /**************************************
  2863. *
  2864. * s e t S t o p M a i n T h r e a d
  2865. *
  2866. **************************************
  2867. *
  2868. * Functional description
  2869. * Set function called by main thread
  2870. * in order to check for shutdown.
  2871. *
  2872. **************************************/
  2873. tryStopMainThread = func;
  2874. }
  2875. namespace os_utils
  2876. {
  2877. // force socket descriptor to have SOCK_CLOEXEC set
  2878. SOCKET socket(int domain, int type, int protocol)
  2879. {
  2880. #ifdef WIN_NT
  2881. return ::socket(domain, type, protocol);
  2882. #else
  2883. int fd;
  2884. #if HAVE_DECL_SOCK_CLOEXEC
  2885. do {
  2886. fd = ::socket(domain, type | SOCK_CLOEXEC, protocol);
  2887. } while (fd < 0 && SYSCALL_INTERRUPTED(errno));
  2888. if (fd < 0 && errno == EINVAL) // probably SOCK_CLOEXEC not accepted
  2889. #endif
  2890. {
  2891. do {
  2892. fd = ::socket(domain, type, protocol);
  2893. } while (fd < 0 && SYSCALL_INTERRUPTED(errno));
  2894. }
  2895. setCloseOnExec(fd);
  2896. return fd;
  2897. #endif
  2898. }
  2899. // force socket descriptor to have SOCK_CLOEXEC set
  2900. SOCKET accept(SOCKET sockfd, struct sockaddr* addr, socklen_t* addrlen)
  2901. {
  2902. #ifdef WIN_NT
  2903. return ::accept(sockfd, addr, addrlen);
  2904. #else
  2905. int fd;
  2906. #if defined(HAVE_ACCEPT4) && HAVE_DECL_SOCK_CLOEXEC
  2907. do {
  2908. fd = ::accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
  2909. } while (fd < 0 && SYSCALL_INTERRUPTED(errno));
  2910. if (fd < 0 && errno == EINVAL) // probably SOCK_CLOEXEC not accepted
  2911. #endif
  2912. {
  2913. do {
  2914. fd = ::accept(sockfd, addr, addrlen);
  2915. } while (fd < 0 && SYSCALL_INTERRUPTED(errno));
  2916. }
  2917. setCloseOnExec(fd);
  2918. return fd;
  2919. #endif
  2920. }
  2921. } // namespace os_utils