blcksock.pas 135 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605
  1. {==============================================================================|
  2. | Project : Ararat Synapse | 009.010.002 |
  3. |==============================================================================|
  4. | Content: Library base |
  5. |==============================================================================|
  6. | Copyright (c)1999-2021, Lukas Gebauer |
  7. | All rights reserved. |
  8. | |
  9. | Redistribution and use in source and binary forms, with or without |
  10. | modification, are permitted provided that the following conditions are met: |
  11. | |
  12. | Redistributions of source code must retain the above copyright notice, this |
  13. | list of conditions and the following disclaimer. |
  14. | |
  15. | Redistributions in binary form must reproduce the above copyright notice, |
  16. | this list of conditions and the following disclaimer in the documentation |
  17. | and/or other materials provided with the distribution. |
  18. | |
  19. | Neither the name of Lukas Gebauer nor the names of its contributors may |
  20. | be used to endorse or promote products derived from this software without |
  21. | specific prior written permission. |
  22. | |
  23. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
  24. | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
  25. | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
  26. | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
  27. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
  28. | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
  29. | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
  30. | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
  31. | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
  32. | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
  33. | DAMAGE. |
  34. |==============================================================================|
  35. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  36. | Portions created by Lukas Gebauer are Copyright (c)1999-2021. |
  37. | All Rights Reserved. |
  38. |==============================================================================|
  39. | Contributor(s): |
  40. |==============================================================================|
  41. | History: see HISTORY.HTM from distribution package |
  42. | (Found at URL: http://www.ararat.cz/synapse/) |
  43. |==============================================================================}
  44. {
  45. Special thanks to Gregor Ibic <[email protected]>
  46. (Intelicom d.o.o., http://www.intelicom.si)
  47. for good inspiration about SSL programming.
  48. }
  49. {$DEFINE ONCEWINSOCK}
  50. {Note about define ONCEWINSOCK:
  51. If you remove this compiler directive, then socket interface is loaded and
  52. initialized on constructor of TBlockSocket class for each socket separately.
  53. Socket interface is used only if your need it.
  54. If you leave this directive here, then socket interface is loaded and
  55. initialized only once at start of your program! It boost performace on high
  56. count of created and destroyed sockets. It eliminate possible small resource
  57. leak on Windows systems too.
  58. }
  59. {$DEFINE RAISEEXCEPT}
  60. {When you enable this define, then is Raiseexcept property is on by default
  61. }
  62. {:@abstract(Synapse's library core)
  63. Core with implementation basic socket classes.
  64. }
  65. {$IFDEF FPC}
  66. {$MODE DELPHI}
  67. {$ENDIF}
  68. {$IFDEF VER125}
  69. {$DEFINE BCB}
  70. {$ENDIF}
  71. {$IFDEF BCB}
  72. {$ObjExportAll On}
  73. {$ENDIF}
  74. {$Q-}
  75. {$H+}
  76. {$M+}
  77. {$TYPEDADDRESS OFF}
  78. //old Delphi does not have MSWINDOWS define.
  79. {$IFDEF WIN32}
  80. {$IFNDEF MSWINDOWS}
  81. {$DEFINE MSWINDOWS}
  82. {$ENDIF}
  83. {$ENDIF}
  84. {$IFDEF UNICODE}
  85. {$WARN IMPLICIT_STRING_CAST OFF}
  86. {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
  87. {$ENDIF}
  88. unit blcksock;
  89. interface
  90. uses
  91. SysUtils, Classes,
  92. synafpc, synabyte,
  93. synsock, synautil, synacode, synaip
  94. {$IFDEF NEXTGEN}
  95. , System.Generics.Collections,
  96. System.Generics.Defaults
  97. {$ENDIF}
  98. {$IFDEF CIL}
  99. ,System.Net
  100. ,System.Net.Sockets
  101. ,System.Text
  102. {$ENDIF}
  103. ;
  104. const
  105. SynapseRelease = '40';
  106. cLocalhost = '127.0.0.1';
  107. cAnyHost = '0.0.0.0';
  108. cBroadcast = '255.255.255.255';
  109. c6Localhost = '::1';
  110. c6AnyHost = '::0';
  111. c6Broadcast = 'ffff::1';
  112. cAnyPort = '0';
  113. CR = #$0d;
  114. LF = #$0a;
  115. CRLF = CR + LF;
  116. c64k = 65536;
  117. type
  118. {:@abstract(Exception clas used by Synapse)
  119. When you enable generating of exceptions, this exception is raised by
  120. Synapse's units.}
  121. ESocketBindError = class(Exception);
  122. { ESynapseError }
  123. ESynapseError = class(Exception)
  124. private
  125. FErrorCode: Integer;
  126. FErrorMessage: string;
  127. public
  128. constructor CreateErrorCode(AErrorCode:Integer; const AErrorDesc: string);
  129. published
  130. {:Code of error. Value depending on used operating system}
  131. property ErrorCode: Integer read FErrorCode Write FErrorCode;
  132. {:Human readable description of error.}
  133. property ErrorMessage: string read FErrorMessage Write FErrorMessage;
  134. end;
  135. ESynProtocolError = class(ESynapseError);
  136. EResetByPeer = class (ESynapseError);
  137. ECouldNotBindSocket = class (ESynapseError);
  138. EConnectionResetByPeer = class (ESynapseError);
  139. ESockectIsnotConnected = class (ESynapseError);
  140. EConnectionTimedOut = class (ESynapseError);
  141. EConnectionRefused = class (ESynapseError);
  142. ECantAssignAddress = class (ESynapseError);
  143. ESocketMinus2 = class (ESynapseError);
  144. {:Types of OnStatus events}
  145. THookSocketReason = (
  146. {:Resolving is begin. Resolved IP and port is in parameter in format like:
  147. 'localhost.somewhere.com:25'.}
  148. HR_ResolvingBegin,
  149. {:Resolving is done. Resolved IP and port is in parameter in format like:
  150. 'localhost.somewhere.com:25'. It is always same as in HR_ResolvingBegin!}
  151. HR_ResolvingEnd,
  152. {:Socket created by CreateSocket method. It reporting Family of created
  153. socket too!}
  154. HR_SocketCreate,
  155. {:Socket closed by CloseSocket method.}
  156. HR_SocketClose,
  157. {:Socket binded to IP and Port. Binded IP and Port is in parameter in format
  158. like: 'localhost.somewhere.com:25'.}
  159. HR_Bind,
  160. {:Socket connected to IP and Port. Connected IP and Port is in parameter in
  161. format like: 'localhost.somewhere.com:25'.}
  162. HR_Connect,
  163. {:Called when CanRead method is used with @True result.}
  164. HR_CanRead,
  165. {:Called when CanWrite method is used with @True result.}
  166. HR_CanWrite,
  167. {:Socket is swithed to Listen mode. (TCP socket only)}
  168. HR_Listen,
  169. {:Socket Accepting client connection. (TCP socket only)}
  170. HR_Accept,
  171. {:report count of bytes readed from socket. Number is in parameter string.
  172. If you need is in integer, you must use StrToInt function!}
  173. HR_ReadCount,
  174. {:report count of bytes writed to socket. Number is in parameter string. If
  175. you need is in integer, you must use StrToInt function!}
  176. HR_WriteCount,
  177. {:If is limiting of bandwidth on, then this reason is called when sending or
  178. receiving is stopped for satisfy bandwidth limit. Parameter is count of
  179. waiting milliseconds.}
  180. HR_Wait,
  181. {:report situation where communication error occured. When raiseexcept is
  182. @true, then exception is called after this Hook reason.}
  183. HR_Error
  184. );
  185. {:Procedural type for OnStatus event. Sender is calling TBlockSocket object,
  186. Reason is one of set Status events and value is optional data.}
  187. THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason;
  188. const Value: string) of object;
  189. {:This procedural type is used for DataFilter hooks.}
  190. THookDataFilter = procedure(Sender: TObject; var Value: string) of object;
  191. {:This procedural type is used for hook OnCreateSocket. By this hook you can
  192. insert your code after initialisation of socket. (you can set special socket
  193. options, etc.)}
  194. THookCreateSocket = procedure(Sender: TObject) of object;
  195. {:This procedural type is used for monitoring of communication.}
  196. THookMonitor = procedure(Sender: TObject; Writing: Boolean;
  197. const Buffer: TMemory; Len: Integer) of object;
  198. {:This procedural type is used for hook OnAfterConnect. By this hook you can
  199. insert your code after TCP socket has been sucessfully connected.}
  200. THookAfterConnect = procedure(Sender: TObject) of object;
  201. {:This procedural type is used for hook OnVerifyCert. By this hook you can
  202. insert your additional certificate verification code. Usefull to verify server
  203. CN against URL. }
  204. THookVerifyCert = function(Sender: TObject):boolean of object;
  205. {:This procedural type is used for hook OnHeartbeat. By this hook you can
  206. call your code repeately during long socket operations.
  207. You must enable heartbeats by @Link(HeartbeatRate) property!}
  208. THookHeartbeat = procedure(Sender: TObject) of object;
  209. {:Specify family of socket.}
  210. TSocketFamily = (
  211. {:Default mode. Socket family is defined by target address for connection.
  212. It allows instant access to IPv4 and IPv6 nodes. When you need IPv6 address
  213. as destination, then is used IPv6 mode. othervise is used IPv4 mode.
  214. However this mode not working properly with preliminary IPv6 supports!}
  215. SF_Any,
  216. {:Turn this class to pure IPv4 mode. This mode is totally compatible with
  217. previous Synapse releases.}
  218. SF_IP4,
  219. {:Turn to only IPv6 mode.}
  220. SF_IP6
  221. );
  222. {:specify possible values of SOCKS modes.}
  223. TSocksType = (
  224. ST_Socks5,
  225. ST_Socks4
  226. );
  227. {:Specify requested SSL/TLS version for secure connection.}
  228. TSSLType = (
  229. LT_all,
  230. LT_SSLv2,
  231. LT_SSLv3,
  232. LT_TLSv1,
  233. LT_TLSv1_1,
  234. LT_TLSv1_2,
  235. LT_TLSv1_3,
  236. LT_SSHv2
  237. );
  238. {:Specify type of socket delayed option.}
  239. TSynaOptionType = (
  240. SOT_Linger,
  241. SOT_RecvBuff,
  242. SOT_SendBuff,
  243. SOT_NonBlock,
  244. SOT_RecvTimeout,
  245. SOT_SendTimeout,
  246. SOT_Reuse,
  247. SOT_TTL,
  248. SOT_Broadcast,
  249. SOT_MulticastTTL,
  250. SOT_MulticastLoop,
  251. SOT_NoDelay // TCP_NODELAY
  252. );
  253. {:@abstract(this object is used for remember delayed socket option set.)}
  254. TSynaOption = record
  255. Option: TSynaOptionType;
  256. Enabled: Boolean;
  257. Value: Integer;
  258. end;
  259. TCustomSSL = class;
  260. TSSLClass = class of TCustomSSL;
  261. TBlockSocket = class;
  262. {$IFDEF NEXTGEN}
  263. TOptionList = TList<TSynaOption>;
  264. TSocketList = TList<TBlockSocket>;
  265. {$ELSE}
  266. TOptionList = TArray<TSynaOption>;
  267. TSocketList = TList;
  268. {$ENDIF}
  269. {:@abstract(Basic IP object.)
  270. This is parent class for other class with protocol implementations. Do not
  271. use this class directly! Use @link(TICMPBlockSocket), @link(TRAWBlockSocket),
  272. @link(TTCPBlockSocket) or @link(TUDPBlockSocket) instead.}
  273. TBlockSocket = class(TObject)
  274. private
  275. FOnStatus: THookSocketStatus;
  276. FOnReadFilter: THookDataFilter;
  277. FOnCreateSocket: THookCreateSocket;
  278. FOnMonitor: THookMonitor;
  279. FOnHeartbeat: THookHeartbeat;
  280. FLocalSin: TVarSin;
  281. FRemoteSin: TVarSin;
  282. FTag: integer;
  283. FBuffer: TSynaBytes;
  284. FRaiseExcept: Boolean;
  285. FNonBlockMode: Boolean;
  286. FMaxLineLength: Integer;
  287. FMaxSendBandwidth: Integer;
  288. FNextSend: UInt32;
  289. FMaxRecvBandwidth: Integer;
  290. FNextRecv: UInt32;
  291. FConvertLineEnd: Boolean;
  292. FLastCR: Boolean;
  293. FLastLF: Boolean;
  294. FBinded: Boolean;
  295. FFamily: TSocketFamily;
  296. FFamilySave: TSocketFamily;
  297. FIP6used: Boolean;
  298. FPreferIP4: Boolean;
  299. FDelayedOptions: TOptionList;
  300. FInterPacketTimeout: Boolean;
  301. {$IFNDEF CIL}
  302. FFDSet: TFDSet;
  303. {$ENDIF}
  304. FRecvCounter: int64;
  305. FSendCounter: int64;
  306. FSendMaxChunk: int64;
  307. FStopFlag: Boolean;
  308. FNonblockSendTimeout: Integer;
  309. FHeartbeatRate: integer;
  310. FConnectionTimeout: integer;
  311. {$IFNDEF ONCEWINSOCK}
  312. FWsaDataOnce: TWSADATA;
  313. {$ENDIF}
  314. FSocket: TSocket;
  315. FLastError: Integer;
  316. FLastErrorDesc: string;
  317. FOwner: TObject;
  318. function GetSizeRecvBuffer: Integer;
  319. procedure SetSizeRecvBuffer(Size: Integer);
  320. function GetSizeSendBuffer: Integer;
  321. procedure SetSizeSendBuffer(Size: Integer);
  322. procedure SetNonBlockMode(Value: Boolean);
  323. procedure SetTTL(TTL: integer);
  324. function GetTTL:integer;
  325. procedure SetFamily(Value: TSocketFamily); virtual;
  326. procedure SetSocket(Value: TSocket); virtual;
  327. function GetWsaData: TWSAData;
  328. function FamilyToAF(f: TSocketFamily): TAddrFamily;
  329. procedure SetNagleMode(Value: Boolean);
  330. procedure SetDelayedOption(const Value: TSynaOption);
  331. procedure DelayedOption(const Value: TSynaOption);
  332. procedure ProcessDelayedOptions;
  333. procedure InternalCreateSocket(Sin: TVarSin);
  334. procedure SetSin(var Sin: TVarSin; const IP, Port: string);
  335. function GetSinIP(Sin: TVarSin): string;
  336. function GetSinPort(Sin: TVarSin): Integer;
  337. procedure DoStatus(Reason: THookSocketReason; const Value: string);
  338. procedure DoReadFilter(Buffer: TMemory; var Len: Integer);
  339. procedure DoMonitor(Writing: Boolean; const Buffer: TMemory; Len: Integer);
  340. procedure DoCreateSocket;
  341. procedure DoHeartbeat;
  342. procedure LimitBandwidth(Length: Integer; MaxB: integer; var Next: UInt32);
  343. procedure SetBandwidth(Value: Integer);
  344. function TestStopFlag: Boolean;
  345. procedure InternalSendStream(const Stream: TStream; WithSize, Indy: boolean); virtual;
  346. function InternalCanRead(Timeout: Integer): Boolean; virtual;
  347. function InternalCanWrite(Timeout: Integer): Boolean; virtual;
  348. protected
  349. FDisconnected: Boolean;
  350. public
  351. constructor Create;
  352. {:Create object and load all necessary socket library. What library is
  353. loaded is described by STUB parameter. If STUB is empty string, then is
  354. loaded default libraries.}
  355. constructor CreateAlternate(Stub: string);
  356. destructor Destroy; override;
  357. {:If @link(family) is not SF_Any, then create socket with type defined in
  358. @link(Family) property. If family is SF_Any, then do nothing! (socket is
  359. created automaticly when you know what type of socket you need to create.
  360. (i.e. inside @link(Connect) or @link(Bind) call.) When socket is created,
  361. then is aplyed all stored delayed socket options.}
  362. procedure CreateSocket;
  363. {:It create socket. Address resolving of Value tells what type of socket is
  364. created. If Value is resolved as IPv4 IP, then is created IPv4 socket. If
  365. value is resolved as IPv6 address, then is created IPv6 socket.}
  366. procedure CreateSocketByName(const Value: string);
  367. {:Destroy socket in use. This method is also automatically called from
  368. object destructor.}
  369. procedure CloseSocket; virtual;
  370. {:Abort any work on Socket and destroy them.}
  371. procedure AbortSocket; virtual;
  372. {:Connects socket to local IP address and PORT. IP address may be numeric or
  373. symbolic ('192.168.74.50', 'cosi.nekde.cz', 'ff08::1'). The same for PORT
  374. - it may be number or mnemonic port ('23', 'telnet').
  375. If port value is '0', system chooses itself and conects unused port in the
  376. range 1024 to 4096 (this depending by operating system!). Structure
  377. LocalSin is filled after calling this method.
  378. Note: If you call this on non-created socket, then socket is created
  379. automaticly.
  380. Warning: when you call : Bind('0.0.0.0','0'); then is nothing done! In this
  381. case is used implicit system bind instead.}
  382. procedure Bind(const IP, Port: string);
  383. {:Connects socket to remote IP address and PORT. The same rules as with
  384. @link(BIND) method are valid. The only exception is that PORT with 0 value
  385. will not be connected!
  386. Structures LocalSin and RemoteSin will be filled with valid values.
  387. When you call this on non-created socket, then socket is created
  388. automaticly. Type of created socket is by @link(Family) property. If is
  389. used SF_IP4, then is created socket for IPv4. If is used SF_IP6, then is
  390. created socket for IPv6. When you have family on SF_Any (default!), then
  391. type of created socket is determined by address resolving of destination
  392. address. (Not work properly on prilimitary winsock IPv6 support!)}
  393. procedure Connect(const IP, Port: string); virtual;
  394. {:Sets socket to receive mode for new incoming connections. It is necessary
  395. to use @link(TBlockSocket.BIND) function call before this method to select
  396. receiving port!}
  397. procedure Listen; virtual;
  398. {:Waits until new incoming connection comes. After it comes a new socket is
  399. automatically created (socket handler is returned by this function as
  400. result).}
  401. function Accept: TSocket; virtual;
  402. {:Sends data of LENGTH from BUFFER address via connected socket. System
  403. automatically splits data to packets.}
  404. function SendBuffer(const Buffer: Tmemory; Length: Integer): Integer; virtual;
  405. {:One data BYTE is sent via connected socket.}
  406. procedure SendByte(Data: Byte); virtual;
  407. {:Send data string via connected socket. Any terminator is not added! If you
  408. need send true string with CR-LF termination, you must add CR-LF characters
  409. to sended string! Because any termination is not added automaticly, you can
  410. use this function for sending any binary data in binary string.}
  411. procedure SendString(Data: TSynaBytes); virtual;
  412. {:Send integer as four bytes to socket.}
  413. procedure SendInteger(Data: integer); virtual;
  414. {:Send data as one block to socket. Each block begin with 4 bytes with
  415. length of data in block. This 4 bytes is added automaticly by this
  416. function.}
  417. procedure SendBlock(const Data: string); virtual;
  418. {:Send data from stream to socket.}
  419. procedure SendStreamRaw(const Stream: TStream); virtual;
  420. {:Send content of stream to socket. It using @link(SendBlock) method}
  421. procedure SendStream(const Stream: TStream); virtual;
  422. {:Send content of stream to socket. It using @link(SendBlock) method and
  423. this is compatible with streams in Indy library.}
  424. procedure SendStreamIndy(const Stream: TStream); virtual;
  425. {:Note: This is low-level receive function. You must be sure if data is
  426. waiting for read before call this function for avoid deadlock!
  427. Waits until allocated buffer is filled by received data. Returns number of
  428. data received, which equals to LENGTH value under normal operation. If it
  429. is not equal the communication channel is possibly broken.
  430. On stream oriented sockets if is received 0 bytes, it mean 'socket is
  431. closed!"
  432. On datagram socket is readed first waiting datagram.}
  433. function RecvBuffer(Buffer: TMemory; Length: Integer): Integer; virtual;
  434. {:Note: This is high-level receive function. It using internal
  435. @link(LineBuffer) and you can combine this function freely with other
  436. high-level functions!
  437. Method waits until data is received. If no data is received within TIMEOUT
  438. (in milliseconds) period, @link(LastError) is set to WSAETIMEDOUT. Methods
  439. serves for reading any size of data (i.e. one megabyte...). This method is
  440. preffered for reading from stream sockets (like TCP).}
  441. function RecvBufferEx(Buffer: Tmemory; Len: Integer;
  442. Timeout: Integer): Integer; virtual;
  443. {:Similar to @link(RecvBufferEx), but readed data is stored in binary
  444. string, not in memory buffer.}
  445. function RecvBufferStr(Len: Integer; Timeout: Integer): TSynaBytes; virtual;
  446. {:Note: This is high-level receive function. It using internal
  447. @link(LineBuffer) and you can combine this function freely with other
  448. high-level functions.
  449. Waits until one data byte is received which is also returned as function
  450. result. If no data is received within TIMEOUT (in milliseconds)period,
  451. @link(LastError) is set to WSAETIMEDOUT and result have value 0.}
  452. function RecvByte(Timeout: Integer): Byte; virtual;
  453. {:Note: This is high-level receive function. It using internal
  454. @link(LineBuffer) and you can combine this function freely with other
  455. high-level functions.
  456. Waits until one four bytes are received and return it as one Ineger Value.
  457. If no data is received within TIMEOUT (in milliseconds)period,
  458. @link(LastError) is set to WSAETIMEDOUT and result have value 0.}
  459. function RecvInteger(Timeout: Integer): Integer; virtual;
  460. {:Note: This is high-level receive function. It using internal
  461. @link(LineBuffer) and you can combine this function freely with other
  462. high-level functions.
  463. Method waits until data string is received. This string is terminated by
  464. CR-LF characters. The resulting string is returned without this termination
  465. (CR-LF)! If @link(ConvertLineEnd) is used, then CR-LF sequence may not be
  466. exactly CR-LF. See @link(ConvertLineEnd) description. If no data is
  467. received within TIMEOUT (in milliseconds) period, @link(LastError) is set
  468. to WSAETIMEDOUT. You may also specify maximum length of reading data by
  469. @link(MaxLineLength) property.}
  470. function RecvString(Timeout: Integer): string; virtual;
  471. {:Note: This is high-level receive function. It using internal
  472. @link(LineBuffer) and you can combine this function freely with other
  473. high-level functions.
  474. Method waits until data string is received. This string is terminated by
  475. Terminator string. The resulting string is returned without this
  476. termination. If no data is received within TIMEOUT (in milliseconds)
  477. period, @link(LastError) is set to WSAETIMEDOUT. You may also specify
  478. maximum length of reading data by @link(MaxLineLength) property.}
  479. function RecvTerminated(Timeout: Integer; const Terminator: string): string; virtual;
  480. {:Note: This is high-level receive function. It using internal
  481. @link(LineBuffer) and you can combine this function freely with other
  482. high-level functions.
  483. Method reads all data waiting for read. If no data is received within
  484. TIMEOUT (in milliseconds) period, @link(LastError) is set to WSAETIMEDOUT.
  485. Methods serves for reading unknown size of data. Because before call this
  486. function you don't know size of received data, returned data is stored in
  487. dynamic size binary string. This method is preffered for reading from
  488. stream sockets (like TCP). It is very goot for receiving datagrams too!
  489. (UDP protocol)}
  490. function RecvPacket(Timeout: Integer): TSynaBytes; virtual;
  491. {:Read one block of data from socket. Each block begin with 4 bytes with
  492. length of data in block. This function read first 4 bytes for get lenght,
  493. then it wait for reported count of bytes.}
  494. function RecvBlock(Timeout: Integer): string; virtual;
  495. {:Read all data from socket to stream until socket is closed (or any error
  496. occured.)}
  497. procedure RecvStreamRaw(const Stream: TStream; Timeout: Integer); virtual;
  498. {:Read requested count of bytes from socket to stream.}
  499. procedure RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: int64);
  500. {:Receive data to stream. It using @link(RecvBlock) method.}
  501. procedure RecvStream(const Stream: TStream; Timeout: Integer); virtual;
  502. {:Receive data to stream. This function is compatible with similar function
  503. in Indy library. It using @link(RecvBlock) method.}
  504. procedure RecvStreamIndy(const Stream: TStream; Timeout: Integer); virtual;
  505. {:Same as @link(RecvBuffer), but readed data stays in system input buffer.
  506. Warning: this function not respect data in @link(LineBuffer)! Is not
  507. recommended to use this function!}
  508. function PeekBuffer(Buffer: TMemory; Length: Integer): Integer; virtual;
  509. {:Same as @link(RecvByte), but readed data stays in input system buffer.
  510. Warning: this function not respect data in @link(LineBuffer)! Is not
  511. recommended to use this function!}
  512. function PeekByte(Timeout: Integer): Byte; virtual;
  513. {:On stream sockets it returns number of received bytes waiting for picking.
  514. 0 is returned when there is no such data. On datagram socket it returns
  515. length of the first waiting datagram. Returns 0 if no datagram is waiting.}
  516. function WaitingData: Integer; virtual;
  517. {:Same as @link(WaitingData), but if exists some of data in @link(Linebuffer),
  518. return their length instead.}
  519. function WaitingDataEx: Integer;
  520. {:Clear all waiting data for read from buffers.}
  521. procedure Purge;
  522. {:Sets linger. Enabled linger means that the system waits another LINGER
  523. (in milliseconds) time for delivery of sent data. This function is only for
  524. stream type of socket! (TCP)}
  525. procedure SetLinger(Enable: Boolean; Linger: Integer);
  526. {:Actualize values in @link(LocalSin).}
  527. procedure GetSinLocal;
  528. {:Actualize values in @link(RemoteSin).}
  529. procedure GetSinRemote;
  530. {:Actualize values in @link(LocalSin) and @link(RemoteSin).}
  531. procedure GetSins;
  532. {:Reset @link(LastError) and @link(LastErrorDesc) to non-error state.}
  533. procedure ResetLastError;
  534. {:If you "manually" call Socket API functions, forward their return code as
  535. parameter to this function, which evaluates it, eventually calls
  536. GetLastError and found error code returns and stores to @link(LastError).}
  537. function SockCheck(SockResult: Integer): Integer; virtual;
  538. {:If @link(LastError) contains some error code and @link(RaiseExcept)
  539. property is @true, raise adequate exception.}
  540. procedure ExceptCheck;
  541. {:Returns local computer name as numerical or symbolic value. It try get
  542. fully qualified domain name. Name is returned in the format acceptable by
  543. functions demanding IP as input parameter.}
  544. function LocalName: string;
  545. {:Try resolve name to all possible IP address. i.e. If you pass as name
  546. result of @link(LocalName) method, you get all IP addresses used by local
  547. system.}
  548. procedure ResolveNameToIP(const Name: string; const IPList: TStrings);
  549. {:Try resolve name to primary IP address. i.e. If you pass as name result of
  550. @link(LocalName) method, you get primary IP addresses used by local system.}
  551. function ResolveName(const Name: string): string;
  552. {:Try resolve IP to their primary domain name. If IP not have domain name,
  553. then is returned original IP.}
  554. function ResolveIPToName(IP: string): string;
  555. {:Try resolve symbolic port name to port number. (i.e. 'Echo' to 8)}
  556. function ResolvePort(const Port: string): Word;
  557. {:Set information about remote side socket. It is good for seting remote
  558. side for sending UDP packet, etc.}
  559. procedure SetRemoteSin(const IP, Port: string);
  560. {:Picks IP socket address from @link(LocalSin).}
  561. function GetLocalSinIP: string; virtual;
  562. {:Picks IP socket address from @link(RemoteSin).}
  563. function GetRemoteSinIP: string; virtual;
  564. {:Picks socket PORT number from @link(LocalSin).}
  565. function GetLocalSinPort: Integer; virtual;
  566. {:Picks socket PORT number from @link(RemoteSin).}
  567. function GetRemoteSinPort: Integer; virtual;
  568. {:Return @TRUE, if you can read any data from socket or is incoming
  569. connection on TCP based socket. Status is tested for time Timeout (in
  570. milliseconds). If value in Timeout is 0, status is only tested and
  571. continue. If value in Timeout is -1, run is breaked and waiting for read
  572. data maybe forever.
  573. This function is need only on special cases, when you need use
  574. @link(RecvBuffer) function directly! read functioms what have timeout as
  575. calling parameter, calling this function internally.}
  576. function CanRead(Timeout: Integer): Boolean; virtual;
  577. {:Same as @link(CanRead), but additionally return @TRUE if is some data in
  578. @link(LineBuffer).}
  579. function CanReadEx(Timeout: Integer): Boolean; virtual;
  580. {:Return @TRUE, if you can to socket write any data (not full sending
  581. buffer). Status is tested for time Timeout (in milliseconds). If value in
  582. Timeout is 0, status is only tested and continue. If value in Timeout is
  583. -1, run is breaked and waiting for write data maybe forever.
  584. This function is need only on special cases!}
  585. function CanWrite(Timeout: Integer): Boolean; virtual;
  586. {:Same as @link(SendBuffer), but send datagram to address from
  587. @link(RemoteSin). Usefull for sending reply to datagram received by
  588. function @link(RecvBufferFrom).}
  589. function SendBufferTo(const Buffer: TMemory; Length: Integer): Integer; virtual;
  590. {:Note: This is low-lever receive function. You must be sure if data is
  591. waiting for read before call this function for avoid deadlock!
  592. Receives first waiting datagram to allocated buffer. If there is no waiting
  593. one, then waits until one comes. Returns length of datagram stored in
  594. BUFFER. If length exceeds buffer datagram is truncated. After this
  595. @link(RemoteSin) structure contains information about sender of UDP packet.}
  596. function RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer; virtual;
  597. {$IFNDEF CIL}
  598. {:This function is for check for incoming data on set of sockets. Whitch
  599. sockets is checked is decribed by SocketList Tlist with TBlockSocket
  600. objects. TList may have maximal number of objects defined by FD_SETSIZE
  601. constant. Return @TRUE, if you can from some socket read any data or is
  602. incoming connection on TCP based socket. Status is tested for time Timeout
  603. (in milliseconds). If value in Timeout is 0, status is only tested and
  604. continue. If value in Timeout is -1, run is breaked and waiting for read
  605. data maybe forever. If is returned @TRUE, CanReadList TList is filled by all
  606. TBlockSocket objects what waiting for read.}
  607. function GroupCanRead(const SocketList: TSocketList; Timeout: Integer;
  608. const CanReadList: TSocketList): Boolean;
  609. {$ENDIF}
  610. {:By this method you may turn address reuse mode for local @link(bind). It
  611. is good specially for UDP protocol. Using this with TCP protocol is
  612. hazardous!}
  613. procedure EnableReuse(Value: Boolean);
  614. {:Try set timeout for all sending and receiving operations, if socket
  615. provider can do it. (It not supported by all socket providers!)}
  616. procedure SetTimeout(Timeout: Integer);
  617. {:Try set timeout for all sending operations, if socket provider can do it.
  618. (It not supported by all socket providers!)}
  619. procedure SetSendTimeout(Timeout: Integer);
  620. {:Try set timeout for all receiving operations, if socket provider can do
  621. it. (It not supported by all socket providers!)}
  622. procedure SetRecvTimeout(Timeout: Integer);
  623. function GetSendTimeout: Integer;
  624. function GetRecvTimeout: integer;
  625. {:Return value of socket type.}
  626. function GetSocketType: integer; Virtual;
  627. {:Return value of protocol type for socket creation.}
  628. function GetSocketProtocol: integer; Virtual;
  629. {:WSA structure with information about socket provider. On non-windows
  630. platforms this structure is simulated!}
  631. property WSAData: TWSADATA read GetWsaData;
  632. {:FDset structure prepared for usage with this socket.}
  633. property FDset: TFDSet read FFDset;
  634. {:Structure describing local socket side.}
  635. property LocalSin: TVarSin read FLocalSin write FLocalSin;
  636. {:Structure describing remote socket side.}
  637. property RemoteSin: TVarSin read FRemoteSin write FRemoteSin;
  638. {:Socket handler. Suitable for "manual" calls to socket API or manual
  639. connection of socket to a previously created socket (i.e by Accept method
  640. on TCP socket)}
  641. property Socket: TSocket read FSocket write SetSocket;
  642. {:Last socket operation error code. Error codes are described in socket
  643. documentation. Human readable error description is stored in
  644. @link(LastErrorDesc) property.}
  645. property LastError: Integer read FLastError;
  646. {:Human readable error description of @link(LastError) code.}
  647. property LastErrorDesc: string read FLastErrorDesc;
  648. {:Buffer used by all high-level receiving functions. This buffer is used for
  649. optimized reading of data from socket. In normal cases you not need access
  650. to this buffer directly!}
  651. property LineBuffer: TSynaBytes read FBuffer write FBuffer;
  652. {:Size of Winsock receive buffer. If it is not supported by socket provider,
  653. it return as size one kilobyte.}
  654. property SizeRecvBuffer: Integer read GetSizeRecvBuffer write SetSizeRecvBuffer;
  655. {:Size of Winsock send buffer. If it is not supported by socket provider, it
  656. return as size one kilobyte.}
  657. property SizeSendBuffer: Integer read GetSizeSendBuffer write SetSizeSendBuffer;
  658. {:If @True, turn class to non-blocking mode. Not all functions are working
  659. properly in this mode, you must know exactly what you are doing! However
  660. when you have big experience with non-blocking programming, then you can
  661. optimise your program by non-block mode!}
  662. property NonBlockMode: Boolean read FNonBlockMode Write SetNonBlockMode;
  663. {:Set Time-to-live value. (if system supporting it!)}
  664. property TTL: Integer read GetTTL Write SetTTL;
  665. {:If is @true, then class in in IPv6 mode.}
  666. property IP6used: Boolean read FIP6used;
  667. {:Return count of received bytes on this socket from begin of current
  668. connection.}
  669. property RecvCounter: int64 read FRecvCounter;
  670. {:Return count of sended bytes on this socket from begin of current
  671. connection.}
  672. property SendCounter: int64 read FSendCounter;
  673. published
  674. {:Return descriptive string for given error code. This is class function.
  675. You may call it without created object!}
  676. class function GetErrorDesc(ErrorCode: Integer): string;
  677. {:Return descriptive string for @link(LastError).}
  678. function GetErrorDescEx: string; virtual;
  679. {:this value is for free use.}
  680. property Tag: Integer read FTag write FTag;
  681. {:If @true, winsock errors raises exception. Otherwise is setted
  682. @link(LastError) value only and you must check it from your program! Default
  683. value is @false.}
  684. property RaiseExcept: Boolean read FRaiseExcept write FRaiseExcept;
  685. {:Define maximum length in bytes of @link(LineBuffer) for high-level
  686. receiving functions. If this functions try to read more data then this
  687. limit, error is returned! If value is 0 (default), no limitation is used.
  688. This is very good protection for stupid attacks to your server by sending
  689. lot of data without proper terminator... until all your memory is allocated
  690. by LineBuffer!
  691. Note: This maximum length is checked only in functions, what read unknown
  692. number of bytes! (like @link(RecvString) or @link(RecvTerminated))}
  693. property MaxLineLength: Integer read FMaxLineLength Write FMaxLineLength;
  694. {:Define maximal bandwidth for all sending operations in bytes per second.
  695. If value is 0 (default), bandwidth limitation is not used.}
  696. property MaxSendBandwidth: Integer read FMaxSendBandwidth Write FMaxSendBandwidth;
  697. {:Define maximal bandwidth for all receiving operations in bytes per second.
  698. If value is 0 (default), bandwidth limitation is not used.}
  699. property MaxRecvBandwidth: Integer read FMaxRecvBandwidth Write FMaxRecvBandwidth;
  700. {:Define maximal bandwidth for all sending and receiving operations in bytes
  701. per second. If value is 0 (default), bandwidth limitation is not used.}
  702. property MaxBandwidth: Integer Write SetBandwidth;
  703. {:Do a conversion of non-standard line terminators to CRLF. (Off by default)
  704. If @True, then terminators like sigle CR, single LF or LFCR are converted
  705. to CRLF internally. This have effect only in @link(RecvString) method!}
  706. property ConvertLineEnd: Boolean read FConvertLineEnd Write FConvertLineEnd;
  707. {:Specified Family of this socket. When you are using Windows preliminary
  708. support for IPv6, then I recommend to set this property!}
  709. property Family: TSocketFamily read FFamily Write SetFamily;
  710. {:When resolving of domain name return both IPv4 and IPv6 addresses, then
  711. specify if is used IPv4 (dafault - @true) or IPv6.}
  712. property PreferIP4: Boolean read FPreferIP4 Write FPreferIP4;
  713. {:By default (@true) is all timeouts used as timeout between two packets in
  714. reading operations. If you set this to @false, then Timeouts is for overall
  715. reading operation!}
  716. property InterPacketTimeout: Boolean read FInterPacketTimeout Write FInterPacketTimeout;
  717. {:All sended datas was splitted by this value.}
  718. property SendMaxChunk: int64 read FSendMaxChunk Write FSendMaxChunk;
  719. {:By setting this property to @true you can stop any communication. You can
  720. use this property for soft abort of communication.}
  721. property StopFlag: Boolean read FStopFlag Write FStopFlag;
  722. {:Timeout for data sending by non-blocking socket mode.}
  723. property NonblockSendTimeout: Integer read FNonblockSendTimeout Write FNonblockSendTimeout;
  724. property NagleMode: Boolean write SetNagleMode; // True (Default) - TCP_NODELAY OFF
  725. // False - TCP_NODELAY ON
  726. {:Timeout for @link(Connect) call. Default value 0 means default system timeout.
  727. Non-zero value means timeout in millisecond.}
  728. property ConnectionTimeout: Integer read FConnectionTimeout write FConnectionTimeout;
  729. {:This event is called by various reasons. It is good for monitoring socket,
  730. create gauges for data transfers, etc.}
  731. property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
  732. {:this event is good for some internal thinks about filtering readed datas.
  733. It is used by telnet client by example.}
  734. property OnReadFilter: THookDataFilter read FOnReadFilter write FOnReadFilter;
  735. {:This event is called after real socket creation for setting special socket
  736. options, because you not know when socket is created. (it is depended on
  737. Ipv4, IPv6 or automatic mode)}
  738. property OnCreateSocket: THookCreateSocket read FOnCreateSocket write FOnCreateSocket;
  739. {:This event is good for monitoring content of readed or writed datas.}
  740. property OnMonitor: THookMonitor read FOnMonitor write FOnMonitor;
  741. {:This event is good for calling your code during long socket operations.
  742. (Example, for refresing UI if class in not called within the thread.)
  743. Rate of heartbeats can be modified by @link(HeartbeatRate) property.}
  744. property OnHeartbeat: THookHeartbeat read FOnHeartbeat write FOnHeartbeat;
  745. {:Specify typical rate of @link(OnHeartbeat) event and @link(StopFlag) testing.
  746. Default value 0 disabling heartbeats! Value is in milliseconds.
  747. Real rate can be higher or smaller then this value, because it depending
  748. on real socket operations too!
  749. Note: Each heartbeat slowing socket processing.}
  750. property HeartbeatRate: integer read FHeartbeatRate Write FHeartbeatRate;
  751. {:What class own this socket? Used by protocol implementation classes.}
  752. property Owner: TObject read FOwner Write FOwner;
  753. end;
  754. {:@abstract(Support for SOCKS4 and SOCKS5 proxy)
  755. Layer with definition all necessary properties and functions for
  756. implementation SOCKS proxy client. Do not use this class directly.}
  757. TSocksBlockSocket = class(TBlockSocket)
  758. private
  759. FSocksIP: string;
  760. FSocksPort: string;
  761. FSocksTimeout: integer;
  762. FSocksUsername: string;
  763. FSocksPassword: string;
  764. FUsingSocks: Boolean;
  765. FSocksResolver: Boolean;
  766. FSocksLastError: integer;
  767. FSocksResponseIP: string;
  768. FSocksResponsePort: string;
  769. FSocksLocalIP: string;
  770. FSocksLocalPort: string;
  771. FSocksRemoteIP: string;
  772. FSocksRemotePort: string;
  773. FBypassFlag: Boolean;
  774. FSocksType: TSocksType;
  775. function SocksCode(IP: string; const Port: string): string;
  776. function SocksDecode(const Value: string): integer;
  777. public
  778. constructor Create;
  779. {:Open connection to SOCKS proxy and if @link(SocksUsername) is set, do
  780. authorisation to proxy. This is needed only in special cases! (it is called
  781. internally!)}
  782. function SocksOpen: Boolean;
  783. {:Send specified request to SOCKS proxy. This is needed only in special
  784. cases! (it is called internally!)}
  785. function SocksRequest(Cmd: Byte; const IP, Port: string): Boolean;
  786. {:Receive response to previosly sended request. This is needed only in
  787. special cases! (it is called internally!)}
  788. function SocksResponse: Boolean;
  789. {:Is @True when class is using SOCKS proxy.}
  790. property UsingSocks: Boolean read FUsingSocks;
  791. {:If SOCKS proxy failed, here is error code returned from SOCKS proxy.}
  792. property SocksLastError: integer read FSocksLastError;
  793. published
  794. {:Address of SOCKS server. If value is empty string, SOCKS support is
  795. disabled. Assingning any value to this property enable SOCKS mode.
  796. Warning: You cannot combine this mode with HTTP-tunneling mode!}
  797. property SocksIP: string read FSocksIP write FSocksIP;
  798. {:Port of SOCKS server. Default value is '1080'.}
  799. property SocksPort: string read FSocksPort write FSocksPort;
  800. {:If you need authorisation on SOCKS server, set username here.}
  801. property SocksUsername: string read FSocksUsername write FSocksUsername;
  802. {:If you need authorisation on SOCKS server, set password here.}
  803. property SocksPassword: string read FSocksPassword write FSocksPassword;
  804. {:Specify timeout for communicatin with SOCKS server. Default is one minute.}
  805. property SocksTimeout: integer read FSocksTimeout write FSocksTimeout;
  806. {:If @True, all symbolic names of target hosts is not translated to IP's
  807. locally, but resolving is by SOCKS proxy. Default is @True.}
  808. property SocksResolver: Boolean read FSocksResolver write FSocksResolver;
  809. {:Specify SOCKS type. By default is used SOCKS5, but you can use SOCKS4 too.
  810. When you select SOCKS4, then if @link(SOCKSResolver) is enabled, then is
  811. used SOCKS4a. Othervise is used pure SOCKS4.}
  812. property SocksType: TSocksType read FSocksType write FSocksType;
  813. end;
  814. {:@abstract(Implementation of TCP socket.)
  815. Supported features: IPv4, IPv6, SSL/TLS or SSH (depending on used plugin),
  816. SOCKS5 proxy (outgoing connections and limited incomming), SOCKS4/4a proxy
  817. (outgoing connections and limited incomming), TCP through HTTP proxy tunnel.}
  818. TTCPBlockSocket = class(TSocksBlockSocket)
  819. private
  820. FOnAfterConnect: THookAfterConnect;
  821. FSSL: TCustomSSL;
  822. FHTTPTunnelIP: string;
  823. FHTTPTunnelPort: string;
  824. FHTTPTunnel: Boolean;
  825. FHTTPTunnelRemoteIP: string;
  826. FHTTPTunnelRemotePort: string;
  827. FHTTPTunnelUser: string;
  828. FHTTPTunnelPass: string;
  829. FHTTPTunnelTimeout: integer;
  830. procedure SocksDoConnect(const IP, Port: string);
  831. procedure HTTPTunnelDoConnect(IP, Port: string);
  832. procedure DoAfterConnect;
  833. public
  834. {:Create TCP socket class with default plugin for SSL/TSL/SSH implementation
  835. (see @link(SSLImplementation))}
  836. constructor Create;
  837. {:Create TCP socket class with desired plugin for SSL/TSL/SSH implementation}
  838. constructor CreateWithSSL(SSLPlugin: TSSLClass);
  839. destructor Destroy; override;
  840. {:See @link(TBlockSocket.CloseSocket)}
  841. procedure CloseSocket; override;
  842. {:See @link(TBlockSocket.WaitingData)}
  843. function WaitingData: Integer; override;
  844. {:Sets socket to receive mode for new incoming connections. It is necessary
  845. to use @link(TBlockSocket.BIND) function call before this method to select
  846. receiving port!
  847. If you use SOCKS, activate incoming TCP connection by this proxy. (By BIND
  848. method of SOCKS.)}
  849. procedure Listen; override;
  850. {:Waits until new incoming connection comes. After it comes a new socket is
  851. automatically created (socket handler is returned by this function as
  852. result).
  853. If you use SOCKS, new socket is not created! In this case is used same
  854. socket as socket for listening! So, you can accept only one connection in
  855. SOCKS mode.}
  856. function Accept: TSocket; override;
  857. {:Connects socket to remote IP address and PORT. The same rules as with
  858. @link(TBlockSocket.BIND) method are valid. The only exception is that PORT
  859. with 0 value will not be connected. After call to this method
  860. a communication channel between local and remote socket is created. Local
  861. socket is assigned automatically if not controlled by previous call to
  862. @link(TBlockSocket.BIND) method. Structures @link(TBlockSocket.LocalSin)
  863. and @link(TBlockSocket.RemoteSin) will be filled with valid values.
  864. If you use SOCKS, activate outgoing TCP connection by SOCKS proxy specified
  865. in @link(TSocksBlockSocket.SocksIP). (By CONNECT method of SOCKS.)
  866. If you use HTTP-tunnel mode, activate outgoing TCP connection by HTTP
  867. tunnel specified in @link(HTTPTunnelIP). (By CONNECT method of HTTP
  868. protocol.)
  869. Note: If you call this on non-created socket, then socket is created
  870. automaticly.}
  871. procedure Connect(const IP, Port: string); override;
  872. {:If you need upgrade existing TCP connection to SSL/TLS (or SSH2, if plugin
  873. allows it) mode, then call this method. This method switch this class to
  874. SSL mode and do SSL/TSL handshake.}
  875. procedure SSLDoConnect;
  876. {:By this method you can downgrade existing SSL/TLS connection to normal TCP
  877. connection.}
  878. procedure SSLDoShutdown;
  879. {:If you need use this component as SSL/TLS TCP server, then after accepting
  880. of inbound connection you need start SSL/TLS session by this method. Before
  881. call this function, you must have assigned all neeeded certificates and
  882. keys!}
  883. function SSLAcceptConnection: Boolean;
  884. {:See @link(TBlockSocket.GetLocalSinIP)}
  885. function GetLocalSinIP: string; override;
  886. {:See @link(TBlockSocket.GetRemoteSinIP)}
  887. function GetRemoteSinIP: string; override;
  888. {:See @link(TBlockSocket.GetLocalSinPort)}
  889. function GetLocalSinPort: Integer; override;
  890. {:See @link(TBlockSocket.GetRemoteSinPort)}
  891. function GetRemoteSinPort: Integer; override;
  892. {:See @link(TBlockSocket.SendBuffer)}
  893. function SendBuffer(const Buffer: TMemory; Length: Integer): Integer; override;
  894. {:See @link(TBlockSocket.RecvBuffer)}
  895. function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
  896. {:Return value of socket type. For TCP return SOCK_STREAM.}
  897. function GetSocketType: integer; override;
  898. {:Return value of protocol type for socket creation. For TCP return
  899. IPPROTO_TCP.}
  900. function GetSocketProtocol: integer; override;
  901. function Connected: boolean;
  902. {:Class implementing SSL/TLS support. It is allways some descendant
  903. of @link(TCustomSSL) class. When programmer not select some SSL plugin
  904. class, then is used @link(TSSLNone)}
  905. property SSL: TCustomSSL read FSSL;
  906. {:@True if is used HTTP tunnel mode.}
  907. property HTTPTunnel: Boolean read FHTTPTunnel;
  908. property Disconnected: Boolean read FDisconnected write FDisconnected;
  909. published
  910. {:Return descriptive string for @link(LastError). On case of error
  911. in SSL/TLS subsystem, it returns right error description.}
  912. function GetErrorDescEx: string; override;
  913. {:Specify IP address of HTTP proxy. Assingning non-empty value to this
  914. property enable HTTP-tunnel mode. This mode is for tunnelling any outgoing
  915. TCP connection through HTTP proxy server. (If policy on HTTP proxy server
  916. allow this!) Warning: You cannot combine this mode with SOCK5 mode!}
  917. property HTTPTunnelIP: string read FHTTPTunnelIP Write FHTTPTunnelIP;
  918. {:Specify port of HTTP proxy for HTTP-tunneling.}
  919. property HTTPTunnelPort: string read FHTTPTunnelPort Write FHTTPTunnelPort;
  920. {:Specify authorisation username for access to HTTP proxy in HTTP-tunnel
  921. mode. If you not need authorisation, then let this property empty.}
  922. property HTTPTunnelUser: string read FHTTPTunnelUser Write FHTTPTunnelUser;
  923. {:Specify authorisation password for access to HTTP proxy in HTTP-tunnel
  924. mode.}
  925. property HTTPTunnelPass: string read FHTTPTunnelPass Write FHTTPTunnelPass;
  926. {:Specify timeout for communication with HTTP proxy in HTTPtunnel mode.}
  927. property HTTPTunnelTimeout: integer read FHTTPTunnelTimeout Write FHTTPTunnelTimeout;
  928. {:This event is called after sucessful TCP socket connection.}
  929. property OnAfterConnect: THookAfterConnect read FOnAfterConnect write FOnAfterConnect;
  930. end;
  931. {:@abstract(Datagram based communication)
  932. This class implementing datagram based communication instead default stream
  933. based communication style.}
  934. TDgramBlockSocket = class(TSocksBlockSocket)
  935. protected
  936. FUseConnect: Boolean;
  937. public
  938. {:Fill @link(TBlockSocket.RemoteSin) structure. This address is used for
  939. sending data.}
  940. procedure Connect(const IP, Port: string); override;
  941. {:Silently redirected to @link(TBlockSocket.SendBufferTo).}
  942. function SendBuffer(const Buffer: TMemory; Length: Integer): Integer; override;
  943. {:Silently redirected to @link(TBlockSocket.RecvBufferFrom).}
  944. function RecvBuffer(Buffer: TMemory; Length: Integer): Integer; override;
  945. {:Specify if connect should called on the underlying socket.}
  946. property UseConnect: Boolean read FUseConnect Write FUseConnect;
  947. end;
  948. {:@abstract(Implementation of UDP socket.)
  949. NOTE: in this class is all receiving redirected to RecvBufferFrom. You can
  950. use for reading any receive function. Preffered is RecvPacket! Similary all
  951. sending is redirected to SendbufferTo. You can use for sending UDP packet any
  952. sending function, like SendString.
  953. Supported features: IPv4, IPv6, unicasts, broadcasts, multicasts, SOCKS5
  954. proxy (only unicasts! Outgoing and incomming.)}
  955. TUDPBlockSocket = class(TDgramBlockSocket)
  956. protected
  957. FSocksControlSock: TTCPBlockSocket;
  958. function UdpAssociation: Boolean;
  959. procedure SetMulticastTTL(TTL: integer);
  960. function GetMulticastTTL:integer;
  961. public
  962. destructor Destroy; override;
  963. {:Enable or disable sending of broadcasts. If seting OK, result is @true.
  964. This method is not supported in SOCKS5 mode! IPv6 does not support
  965. broadcasts! In this case you must use Multicasts instead.}
  966. procedure EnableBroadcast(Value: Boolean);
  967. {:See @link(TBlockSocket.SendBufferTo)}
  968. function SendBufferTo(const Buffer: TMemory; Length: Integer): Integer; override;
  969. {:See @link(TBlockSocket.RecvBufferFrom)}
  970. function RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer; override;
  971. {$IFNDEF CIL}
  972. {:Add this socket to given multicast group. You cannot use Multicasts in
  973. SOCKS mode!}
  974. procedure AddMulticast(const MCastIP:string);
  975. {:Remove this socket from given multicast group.}
  976. procedure DropMulticast(const MCastIP:string);
  977. {$ENDIF}
  978. {:All sended multicast datagrams is loopbacked to your interface too. (you
  979. can read your sended datas.) You can disable this feature by this function.
  980. This function not working on some Windows systems!}
  981. procedure EnableMulticastLoop(Value: Boolean);
  982. {:Return value of socket type. For UDP return SOCK_DGRAM.}
  983. function GetSocketType: integer; override;
  984. {:Return value of protocol type for socket creation. For UDP return
  985. IPPROTO_UDP.}
  986. function GetSocketProtocol: integer; override;
  987. {:Set Time-to-live value for multicasts packets. It define number of routers
  988. for transfer of datas. If you set this to 1 (dafault system value), then
  989. multicasts packet goes only to you local network. If you need transport
  990. multicast packet to worldwide, then increase this value, but be carefull,
  991. lot of routers on internet does not transport multicasts packets!}
  992. property MulticastTTL: Integer read GetMulticastTTL Write SetMulticastTTL;
  993. end;
  994. {:@abstract(Implementation of RAW ICMP socket.)
  995. For this object you must have rights for creating RAW sockets!}
  996. TICMPBlockSocket = class(TDgramBlockSocket)
  997. public
  998. {:Return value of socket type. For RAW and ICMP return SOCK_RAW.}
  999. function GetSocketType: integer; override;
  1000. {:Return value of protocol type for socket creation. For ICMP returns
  1001. IPPROTO_ICMP or IPPROTO_ICMPV6}
  1002. function GetSocketProtocol: integer; override;
  1003. end;
  1004. {:@abstract(Implementation of RAW socket.)
  1005. For this object you must have rights for creating RAW sockets!}
  1006. TRAWBlockSocket = class(TBlockSocket)
  1007. public
  1008. {:Return value of socket type. For RAW and ICMP return SOCK_RAW.}
  1009. function GetSocketType: integer; override;
  1010. {:Return value of protocol type for socket creation. For RAW returns
  1011. IPPROTO_RAW.}
  1012. function GetSocketProtocol: integer; override;
  1013. end;
  1014. {:@abstract(Implementation of PGM-message socket.)
  1015. Not all systems supports this protocol!}
  1016. TPGMMessageBlockSocket = class(TBlockSocket)
  1017. public
  1018. {:Return value of socket type. For PGM-message return SOCK_RDM.}
  1019. function GetSocketType: integer; override;
  1020. {:Return value of protocol type for socket creation. For PGM-message returns
  1021. IPPROTO_RM.}
  1022. function GetSocketProtocol: integer; override;
  1023. end;
  1024. {:@abstract(Implementation of PGM-stream socket.)
  1025. Not all systems supports this protocol!}
  1026. TPGMStreamBlockSocket = class(TBlockSocket)
  1027. public
  1028. {:Return value of socket type. For PGM-stream return SOCK_STREAM.}
  1029. function GetSocketType: integer; override;
  1030. {:Return value of protocol type for socket creation. For PGM-stream returns
  1031. IPPROTO_RM.}
  1032. function GetSocketProtocol: integer; override;
  1033. end;
  1034. {:@abstract(Parent class for all SSL plugins.)
  1035. This is abstract class defining interface for other SSL plugins.
  1036. Instance of this class will be created for each @link(TTCPBlockSocket).
  1037. Warning: not all methods and propertis can work in all existing SSL plugins!
  1038. Please, read documentation of used SSL plugin.}
  1039. TCustomSSL = class(TObject)
  1040. private
  1041. FOnVerifyCert: THookVerifyCert;
  1042. FCertCA: string;
  1043. FTrustCertificate: string;
  1044. FTrustCertificateFile: string;
  1045. FUsername: string;
  1046. FPassword: string;
  1047. FSSHChannelType: string;
  1048. FSSHChannelArg1: string;
  1049. FSSHChannelArg2: string;
  1050. FCertComplianceLevel: integer;
  1051. FSNIHost: string;
  1052. procedure ReturnError;
  1053. procedure SetCertCAFile(const Value: string); virtual;
  1054. protected
  1055. FCiphers: string;
  1056. FPrivateKey: string;
  1057. FSSLEnabled: Boolean;
  1058. FSocket: TTCPBlockSocket;
  1059. FKeyPassword: string;
  1060. FSSLType: TSSLType;
  1061. FVerifyCert: Boolean;
  1062. FCertificateFile: string;
  1063. FCertCAFile: string;
  1064. FPFXfile: string;
  1065. FPFX: string;
  1066. FPrivateKeyFile: string;
  1067. FLastErrorDesc: string;
  1068. FLastError: integer;
  1069. FCertificate: string;
  1070. function DoVerifyCert:boolean;
  1071. function CreateSelfSignedCert(Host: string): Boolean; virtual;
  1072. public
  1073. {: Create plugin class. it is called internally from @link(TTCPBlockSocket)}
  1074. constructor Create(const Value: TTCPBlockSocket); virtual;
  1075. {: Assign settings (certificates and configuration) from another SSL plugin
  1076. class.}
  1077. procedure Assign(const Value: TCustomSSL); virtual;
  1078. {: return description of used plugin. It usually return name and version
  1079. of used SSL library.}
  1080. function LibVersion: string; virtual;
  1081. {: return name of used plugin.}
  1082. function LibName: string; virtual;
  1083. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1084. Here is needed code for start SSL connection.}
  1085. function Connect: boolean; virtual;
  1086. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1087. Here is needed code for acept new SSL connection.}
  1088. function Accept: boolean; virtual;
  1089. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1090. Here is needed code for hard shutdown of SSL connection. (for example,
  1091. before socket is closed)}
  1092. function Shutdown: boolean; virtual;
  1093. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1094. Here is needed code for soft shutdown of SSL connection. (for example,
  1095. when you need to continue with unprotected connection.)}
  1096. function BiShutdown: boolean; virtual;
  1097. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1098. Here is needed code for sending some datas by SSL connection.}
  1099. function SendBuffer(Buffer: TMemory; Len: Integer): Integer; virtual;
  1100. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1101. Here is needed code for receiving some datas by SSL connection.}
  1102. function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; virtual;
  1103. {: Do not call this directly. It is used internally by @link(TTCPBlockSocket)!
  1104. Here is needed code for getting count of datas what waiting for read.
  1105. If SSL plugin not allows this, then it should return 0.}
  1106. function WaitingData: Integer; virtual;
  1107. {:Return string with identificator of SSL/TLS version of existing
  1108. connection.}
  1109. function GetSSLVersion: string; virtual;
  1110. {:Return subject of remote SSL peer.}
  1111. function GetPeerSubject: string; virtual;
  1112. {:Return Serial number if remote X509 certificate.}
  1113. function GetPeerSerialNo: integer; virtual;
  1114. {:Return issuer certificate of remote SSL peer.}
  1115. function GetPeerIssuer: string; virtual;
  1116. {:Return peer name from remote side certificate. This is good for verify,
  1117. if certificate is generated for remote side IP name.}
  1118. function GetPeerName: string; virtual;
  1119. {:Returns has of peer name from remote side certificate. This is good
  1120. for fast remote side authentication.}
  1121. function GetPeerNameHash: cardinal; virtual;
  1122. {:Return fingerprint of remote SSL peer.}
  1123. function GetPeerFingerprint: string; virtual;
  1124. function GetPeerFingerprintDigest(const ADigest: string): string; virtual; abstract;
  1125. {:Return all detailed information about certificate from remote side of
  1126. SSL/TLS connection. Result string can be multilined! Each plugin can return
  1127. this informations in different format!}
  1128. function GetCertInfo: string; virtual;
  1129. {:Return currently used Cipher.}
  1130. function GetCipherName: string; virtual;
  1131. {:Return currently used number of bits in current Cipher algorythm.}
  1132. function GetCipherBits: integer; virtual;
  1133. {:Return number of bits in current Cipher algorythm.}
  1134. function GetCipherAlgBits: integer; virtual;
  1135. {:Return result value of verify remote side certificate. Look to OpenSSL
  1136. documentation for possible values. For example 0 is successfuly verified
  1137. certificate, or 18 is self-signed certificate.}
  1138. function GetVerifyCert: integer; virtual;
  1139. {: Resurn @true if SSL mode is enabled on existing cvonnection.}
  1140. property SSLEnabled: Boolean read FSSLEnabled;
  1141. {:Return error code of last SSL operation. 0 is OK.}
  1142. property LastError: integer read FLastError;
  1143. {:Return error description of last SSL operation.}
  1144. property LastErrorDesc: string read FLastErrorDesc;
  1145. published
  1146. {:Here you can specify requested SSL/TLS mode. Default is autodetection, but
  1147. on some servers autodetection not working properly. In this case you must
  1148. specify requested SSL/TLS mode by your hand!}
  1149. property SSLType: TSSLType read FSSLType write FSSLType;
  1150. {:Password for decrypting of encoded certificate or key.}
  1151. property KeyPassword: string read FKeyPassword write FKeyPassword;
  1152. {:Username for possible credentials.}
  1153. property Username: string read FUsername write FUsername;
  1154. {:password for possible credentials.}
  1155. property Password: string read FPassword write FPassword;
  1156. {:By this property you can modify default set of SSL/TLS ciphers.}
  1157. property Ciphers: string read FCiphers write FCiphers;
  1158. {:Used for loading certificate from disk file. See to plugin documentation
  1159. if this method is supported and how!}
  1160. property CertificateFile: string read FCertificateFile write FCertificateFile;
  1161. {:Used for loading private key from disk file. See to plugin documentation
  1162. if this method is supported and how!}
  1163. property PrivateKeyFile: string read FPrivateKeyFile write FPrivateKeyFile;
  1164. {:Used for loading certificate from binary string. See to plugin documentation
  1165. if this method is supported and how!}
  1166. property Certificate: string read FCertificate write FCertificate;
  1167. {:Used for loading private key from binary string. See to plugin documentation
  1168. if this method is supported and how!}
  1169. property PrivateKey: string read FPrivateKey write FPrivateKey;
  1170. {:Used for loading PFX from binary string. See to plugin documentation
  1171. if this method is supported and how!}
  1172. property PFX: string read FPFX write FPFX;
  1173. {:Used for loading PFX from disk file. See to plugin documentation
  1174. if this method is supported and how!}
  1175. property PFXfile: string read FPFXfile write FPFXfile;
  1176. {:Used for loading trusted certificates from disk file. See to plugin documentation
  1177. if this method is supported and how!}
  1178. property TrustCertificateFile: string read FTrustCertificateFile write FTrustCertificateFile;
  1179. {:Used for loading trusted certificates from binary string. See to plugin documentation
  1180. if this method is supported and how!}
  1181. property TrustCertificate: string read FTrustCertificate write FTrustCertificate;
  1182. {:Used for loading CA certificates from binary string. See to plugin documentation
  1183. if this method is supported and how!}
  1184. property CertCA: string read FCertCA write FCertCA;
  1185. {:Used for loading CA certificates from disk file. See to plugin documentation
  1186. if this method is supported and how!}
  1187. property CertCAFile: string read FCertCAFile write SetCertCAFile;
  1188. {:If @true, then is verified client certificate. (it is good for writing
  1189. SSL/TLS servers.) When you are not server, but you are client, then if this
  1190. property is @true, verify servers certificate.}
  1191. property VerifyCert: Boolean read FVerifyCert write FVerifyCert;
  1192. {:channel type for possible SSH connections}
  1193. property SSHChannelType: string read FSSHChannelType write FSSHChannelType;
  1194. {:First argument of channel type for possible SSH connections}
  1195. property SSHChannelArg1: string read FSSHChannelArg1 write FSSHChannelArg1;
  1196. {:Second argument of channel type for possible SSH connections}
  1197. property SSHChannelArg2: string read FSSHChannelArg2 write FSSHChannelArg2;
  1198. {: Level of standards compliance level
  1199. (CryptLib: values in cryptlib.pas, -1: use default value ) }
  1200. property CertComplianceLevel:integer read FCertComplianceLevel write FCertComplianceLevel;
  1201. {:This event is called when verifying the server certificate immediatally after
  1202. a successfull verification in the ssl library.}
  1203. property OnVerifyCert: THookVerifyCert read FOnVerifyCert write FOnVerifyCert;
  1204. {: Server Name Identification. Host name to send to server. If empty the host name
  1205. found in URL will be used, which should be the normal use (http Header Host = SNI Host).
  1206. The value is cleared after the connection is established.
  1207. (SNI support requires OpenSSL 0.9.8k or later. Cryptlib not supported, yet ) }
  1208. property SNIHost:string read FSNIHost write FSNIHost;
  1209. end;
  1210. {:@abstract(Default SSL plugin with no SSL support.)
  1211. Dummy SSL plugin implementation for applications without SSL/TLS support.}
  1212. TSSLNone = class (TCustomSSL)
  1213. public
  1214. {:See @inherited}
  1215. function LibVersion: string; override;
  1216. {:See @inherited}
  1217. function LibName: string; override;
  1218. end;
  1219. {:@abstract(Record with definition of IP packet header.)
  1220. For reading data from ICMP or RAW sockets.}
  1221. TIPHeader = record
  1222. VerLen: Byte;
  1223. TOS: Byte;
  1224. TotalLen: Word;
  1225. Identifer: Word;
  1226. FragOffsets: Word;
  1227. TTL: Byte;
  1228. Protocol: Byte;
  1229. CheckSum: Word;
  1230. SourceIp: UInt32;
  1231. DestIp: UInt32;
  1232. Options: UInt32;
  1233. end;
  1234. {:@abstract(Parent class of application protocol implementations.)
  1235. By this class is defined common properties.}
  1236. TSynaClient = Class(TObject)
  1237. protected
  1238. FTargetHost: string;
  1239. FTargetPort: string;
  1240. FIPInterface: string;
  1241. FTimeout: integer;
  1242. FUserName: string;
  1243. FPassword: string;
  1244. public
  1245. constructor Create;
  1246. published
  1247. {:Specify terget server IP (or symbolic name). Default is 'localhost'.}
  1248. property TargetHost: string read FTargetHost Write FTargetHost;
  1249. {:Specify terget server port (or symbolic name).}
  1250. property TargetPort: string read FTargetPort Write FTargetPort;
  1251. {:Defined local socket address. (outgoing IP address). By default is used
  1252. '0.0.0.0' as wildcard for default IP.}
  1253. property IPInterface: string read FIPInterface Write FIPInterface;
  1254. {:Specify default timeout for socket operations.}
  1255. property Timeout: integer read FTimeout Write FTimeout;
  1256. {:If protocol need user authorization, then fill here username.}
  1257. property UserName: string read FUserName Write FUserName;
  1258. {:If protocol need user authorization, then fill here password.}
  1259. property Password: string read FPassword Write FPassword;
  1260. end;
  1261. var
  1262. {:Selected SSL plugin. Default is @link(TSSLNone).
  1263. Do not change this value directly!!!
  1264. Just add your plugin unit to your project uses instead. Each plugin unit have
  1265. initialization code what modify this variable.}
  1266. SSLImplementation: TSSLClass = TSSLNone;
  1267. implementation
  1268. {$IFDEF ONCEWINSOCK}
  1269. var
  1270. WsaDataOnce: TWSADATA;
  1271. e: ESynapseError;
  1272. { ESynapseError }
  1273. constructor ESynapseError.CreateErrorCode(AErrorCode: Integer;
  1274. const AErrorDesc: string);
  1275. var
  1276. Z: string;
  1277. begin
  1278. Z := SysUtils.Trim(AErrorDesc);
  1279. inherited Create(Z);
  1280. FErrorCode := AErrorCode;
  1281. FErrorMessage := Z;
  1282. end;
  1283. {$ENDIF}
  1284. constructor TBlockSocket.Create;
  1285. begin
  1286. CreateAlternate('');
  1287. end;
  1288. constructor TBlockSocket.CreateAlternate(Stub: string);
  1289. {$IFNDEF ONCEWINSOCK}
  1290. var
  1291. e: ESynapseError;
  1292. {$ENDIF}
  1293. begin
  1294. inherited Create;
  1295. //FDelayedOptions := TOptionList.Create;
  1296. FRaiseExcept := False;
  1297. {$IFDEF RAISEEXCEPT}
  1298. FRaiseExcept := True;
  1299. {$ENDIF}
  1300. FSocket := INVALID_SOCKET;
  1301. FBuffer := '';
  1302. FLastCR := False;
  1303. FLastLF := False;
  1304. FBinded := False;
  1305. FNonBlockMode := False;
  1306. FMaxLineLength := 0;
  1307. FMaxSendBandwidth := 0;
  1308. FNextSend := 0;
  1309. FMaxRecvBandwidth := 0;
  1310. FNextRecv := 0;
  1311. FConvertLineEnd := False;
  1312. FFamily := SF_Any;
  1313. FFamilySave := SF_Any;
  1314. FIP6used := False;
  1315. FPreferIP4 := True;
  1316. FInterPacketTimeout := True;
  1317. FRecvCounter := 0;
  1318. FSendCounter := 0;
  1319. FSendMaxChunk := c64k;
  1320. FStopFlag := False;
  1321. FNonblockSendTimeout := 15000;
  1322. FHeartbeatRate := 0;
  1323. FConnectionTimeout := 0;
  1324. FOwner := nil;
  1325. {$IFNDEF ONCEWINSOCK}
  1326. if Stub = '' then
  1327. Stub := DLLStackName;
  1328. if not InitSocketInterface(Stub) then
  1329. begin
  1330. e := ESynapseError.Create('Error loading Socket interface (' + Stub + ')!');
  1331. e.ErrorCode := 0;
  1332. e.ErrorMessage := 'Error loading Socket interface (' + Stub + ')!';
  1333. raise e;
  1334. end;
  1335. SockCheck(synsock.WSAStartup(WinsockLevel, FWsaDataOnce));
  1336. ExceptCheck;
  1337. {$ENDIF}
  1338. end;
  1339. destructor TBlockSocket.Destroy;
  1340. //var
  1341. //n: integer;
  1342. // p: TSynaOption;
  1343. begin
  1344. CloseSocket;
  1345. {$IFNDEF ONCEWINSOCK}
  1346. synsock.WSACleanup;
  1347. DestroySocketInterface;
  1348. {$ENDIF}
  1349. {for n := FDelayedOptions.Count - 1 downto 0 do
  1350. begin
  1351. p := TSynaOption(FDelayedOptions[n]);
  1352. FreeAndNil(p);
  1353. end;}
  1354. //FreeAndNil(FDelayedOptions);
  1355. Finalize(FDelayedOptions);
  1356. inherited Destroy;
  1357. end;
  1358. function TBlockSocket.FamilyToAF(f: TSocketFamily): TAddrFamily;
  1359. begin
  1360. case f of
  1361. SF_ip4:
  1362. Result := AF_INET;
  1363. SF_ip6:
  1364. Result := AF_INET6;
  1365. else
  1366. Result := AF_UNSPEC;
  1367. end;
  1368. end;
  1369. procedure TBlockSocket.SetDelayedOption(const Value: TSynaOption);
  1370. var
  1371. li: TLinger;
  1372. x: integer;
  1373. buf: TMemory;
  1374. {$IFNDEF MSWINDOWS}
  1375. {$IFNDEF ULTIBO}
  1376. timeval: TTimeval;
  1377. {$ENDIF}
  1378. {$ENDIF}
  1379. begin
  1380. case value.Option of
  1381. SOT_Linger:
  1382. begin
  1383. {$IFDEF CIL}
  1384. li := TLinger.Create(Value.Enabled, Value.Value div 1000);
  1385. synsock.SetSockOptObj(FSocket, integer(SOL_SOCKET), integer(SO_LINGER), li);
  1386. {$ELSE}
  1387. li.l_onoff := Ord(Value.Enabled);
  1388. li.l_linger := Value.Value div 1000;
  1389. buf := @li;
  1390. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_LINGER), buf, SizeOf(li)));
  1391. ExceptCheck;
  1392. {$ENDIF}
  1393. end;
  1394. SOT_RecvBuff:
  1395. begin
  1396. {$IFDEF CIL}
  1397. buf := System.BitConverter.GetBytes(value.Value);
  1398. {$ELSE}
  1399. buf := @Value.Value;
  1400. {$ENDIF}
  1401. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVBUF),
  1402. buf, SizeOf(Value.Value)));
  1403. ExceptCheck;
  1404. end;
  1405. SOT_SendBuff:
  1406. begin
  1407. {$IFDEF CIL}
  1408. buf := System.BitConverter.GetBytes(value.Value);
  1409. {$ELSE}
  1410. buf := @Value.Value;
  1411. {$ENDIF}
  1412. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDBUF),
  1413. buf, SizeOf(Value.Value)));
  1414. ExceptCheck;
  1415. end;
  1416. SOT_NonBlock:
  1417. begin
  1418. FNonBlockMode := Value.Enabled;
  1419. x := Ord(FNonBlockMode);
  1420. SockCheck(synsock.IoctlSocket(FSocket, FIONBIO, x));
  1421. ExceptCheck;
  1422. end;
  1423. SOT_RecvTimeout:
  1424. begin
  1425. {$IFDEF CIL}
  1426. buf := System.BitConverter.GetBytes(value.Value);
  1427. synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
  1428. buf, SizeOf(Value.Value));
  1429. {$ELSE}
  1430. {$IFDEF MSWINDOWS}
  1431. buf := @Value.Value;
  1432. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
  1433. buf, SizeOf(Value.Value)));
  1434. ExceptCheck;
  1435. {$ELSE}
  1436. {$IFDEF ULTIBO}
  1437. buf := @Value.Value;
  1438. synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
  1439. buf, SizeOf(Value.Value));
  1440. {$ELSE}
  1441. timeval.tv_sec:=Value.Value div 1000;
  1442. timeval.tv_usec:=(Value.Value mod 1000) * 1000;
  1443. synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVTIMEO),
  1444. @timeval, SizeOf(timeval));
  1445. {$ENDIF}
  1446. {$ENDIF}
  1447. {$ENDIF}
  1448. end;
  1449. SOT_SendTimeout:
  1450. begin
  1451. {$IFDEF CIL}
  1452. buf := System.BitConverter.GetBytes(value.Value);
  1453. {$ELSE}
  1454. {$IFDEF MSWINDOWS}
  1455. buf := @Value.Value;
  1456. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDTIMEO),
  1457. buf, SizeOf(Value.Value)));
  1458. ExceptCheck;
  1459. {$ELSE}
  1460. {$IFDEF ULTIBO}
  1461. buf := @Value.Value;
  1462. synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDTIMEO),
  1463. buf, SizeOf(Value.Value));
  1464. {$ELSE}
  1465. timeval.tv_sec:=Value.Value div 1000;
  1466. timeval.tv_usec:=(Value.Value mod 1000) * 1000;
  1467. synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDTIMEO),
  1468. @timeval, SizeOf(timeval));
  1469. {$ENDIF}
  1470. {$ENDIF}
  1471. {$ENDIF}
  1472. end;
  1473. SOT_Reuse:
  1474. begin
  1475. x := Ord(Value.Enabled);
  1476. {$IFDEF CIL}
  1477. buf := System.BitConverter.GetBytes(x);
  1478. {$ELSE}
  1479. buf := @x;
  1480. {$ENDIF}
  1481. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_REUSEADDR), buf, SizeOf(x)));
  1482. ExceptCheck;
  1483. end;
  1484. SOT_TTL:
  1485. begin
  1486. {$IFDEF CIL}
  1487. buf := System.BitConverter.GetBytes(value.Value);
  1488. {$ELSE}
  1489. buf := @Value.Value;
  1490. {$ENDIF}
  1491. if FIP6Used then
  1492. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_UNICAST_HOPS),
  1493. buf, SizeOf(Value.Value)))
  1494. else
  1495. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_TTL),
  1496. buf, SizeOf(Value.Value)));
  1497. ExceptCheck;
  1498. end;
  1499. SOT_Broadcast:
  1500. begin
  1501. //#todo1 broadcasty na IP6
  1502. x := Ord(Value.Enabled);
  1503. {$IFDEF CIL}
  1504. buf := System.BitConverter.GetBytes(x);
  1505. {$ELSE}
  1506. buf := @x;
  1507. {$ENDIF}
  1508. SockCheck(synsock.SetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_BROADCAST), buf, SizeOf(x)));
  1509. ExceptCheck;
  1510. end;
  1511. SOT_MulticastTTL:
  1512. begin
  1513. {$IFDEF CIL}
  1514. buf := System.BitConverter.GetBytes(value.Value);
  1515. {$ELSE}
  1516. buf := @Value.Value;
  1517. {$ENDIF}
  1518. if FIP6Used then
  1519. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_MULTICAST_HOPS),
  1520. buf, SizeOf(Value.Value)))
  1521. else
  1522. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_MULTICAST_TTL),
  1523. buf, SizeOf(Value.Value)));
  1524. ExceptCheck;
  1525. end;
  1526. SOT_MulticastLoop:
  1527. begin
  1528. x := Ord(Value.Enabled);
  1529. {$IFDEF CIL}
  1530. buf := System.BitConverter.GetBytes(x);
  1531. {$ELSE}
  1532. buf := @x;
  1533. {$ENDIF}
  1534. if FIP6Used then
  1535. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IPV6), integer(IPV6_MULTICAST_LOOP), buf, SizeOf(x)))
  1536. else
  1537. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(IP_MULTICAST_LOOP), buf, SizeOf(x)));
  1538. ExceptCheck;
  1539. end;
  1540. SOT_NoDelay:
  1541. begin
  1542. {$IFDEF CIL}
  1543. buf := System.BitConverter.GetBytes(x);
  1544. {$ELSE}
  1545. buf := @x;
  1546. {$ENDIF}
  1547. x := Ord(Value.Enabled);
  1548. SockCheck(synsock.SetSockOpt(FSocket, integer(IPPROTO_IP), integer(TCP_NODELAY), buf, SizeOf(x)));
  1549. ExceptCheck;
  1550. end;
  1551. end;
  1552. //FreeAndNil(Value);
  1553. end;
  1554. procedure TBlockSocket.DelayedOption(const Value: TSynaOption);
  1555. begin
  1556. if FSocket = INVALID_SOCKET then
  1557. begin
  1558. SetLength(FDelayedOptions, Length(FDelayedOptions) + 1);
  1559. FDelayedOptions[High(FDelayedOptions)] := Value;
  1560. end
  1561. else
  1562. SetDelayedOption(Value);
  1563. end;
  1564. procedure TBlockSocket.ProcessDelayedOptions;
  1565. var
  1566. n: integer;
  1567. d: TSynaOption;
  1568. begin
  1569. for n := 0 to High(FDelayedOptions) do
  1570. begin
  1571. d := TSynaOption(FDelayedOptions[n]);
  1572. SetDelayedOption(d);
  1573. end;
  1574. Finalize(FDelayedOptions);
  1575. end;
  1576. procedure TBlockSocket.SetSin(var Sin: TVarSin; const IP, Port: string);
  1577. var
  1578. f: TSocketFamily;
  1579. begin
  1580. DoStatus(HR_ResolvingBegin, IP + ':' + Port);
  1581. ResetLastError;
  1582. //if socket exists, then use their type, else use users selection
  1583. f := SF_Any;
  1584. if (FSocket = INVALID_SOCKET) and (FFamily = SF_any) then
  1585. begin
  1586. if IsIP(IP) then
  1587. f := SF_IP4
  1588. else
  1589. if IsIP6(IP) then
  1590. f := SF_IP6;
  1591. end
  1592. else
  1593. f := FFamily;
  1594. FLastError := synsock.SetVarSin(sin, ip, port, FamilyToAF(f),
  1595. GetSocketprotocol, GetSocketType, FPreferIP4);
  1596. DoStatus(HR_ResolvingEnd, GetSinIP(sin) + ':' + IntTostr(GetSinPort(sin)));
  1597. end;
  1598. function TBlockSocket.GetSendTimeout: Integer;
  1599. var
  1600. l: integer;
  1601. begin
  1602. l:=SizeOf(Integer);
  1603. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDTIMEO, @Result, l));
  1604. ExceptCheck;
  1605. end;
  1606. function TBlockSocket.GetSinIP(Sin: TVarSin): string;
  1607. begin
  1608. Result := synsock.GetSinIP(sin);
  1609. end;
  1610. function TBlockSocket.GetSinPort(Sin: TVarSin): Integer;
  1611. begin
  1612. Result := synsock.GetSinPort(sin);
  1613. end;
  1614. procedure TBlockSocket.CreateSocket;
  1615. var
  1616. sin: TVarSin;
  1617. begin
  1618. //dummy for SF_Any Family mode
  1619. ResetLastError;
  1620. if (FFamily <> SF_Any) and (FSocket = INVALID_SOCKET) then
  1621. begin
  1622. {$IFDEF CIL}
  1623. if FFamily = SF_IP6 then
  1624. sin := TVarSin.Create(IPAddress.Parse('::0'), 0)
  1625. else
  1626. sin := TVarSin.Create(IPAddress.Parse('0.0.0.0'), 0);
  1627. {$ELSE}
  1628. FillChar(Sin, Sizeof(Sin), 0);
  1629. if FFamily = SF_IP6 then
  1630. sin.sin_family := AF_INET6
  1631. else
  1632. sin.sin_family := AF_INET;
  1633. {$ENDIF}
  1634. InternalCreateSocket(Sin);
  1635. end;
  1636. end;
  1637. procedure TBlockSocket.CreateSocketByName(const Value: string);
  1638. var
  1639. sin: TVarSin;
  1640. begin
  1641. ResetLastError;
  1642. if FSocket = INVALID_SOCKET then
  1643. begin
  1644. SetSin(sin, value, '0');
  1645. if FLastError = 0 then
  1646. InternalCreateSocket(Sin);
  1647. end;
  1648. end;
  1649. procedure TBlockSocket.InternalCreateSocket(Sin: TVarSin);
  1650. begin
  1651. FStopFlag := False;
  1652. FRecvCounter := 0;
  1653. FSendCounter := 0;
  1654. ResetLastError;
  1655. if FSocket = INVALID_SOCKET then
  1656. begin
  1657. FBuffer := '';
  1658. FBinded := False;
  1659. FIP6Used := Sin.AddressFamily = AF_INET6;
  1660. FSocket := synsock.Socket(integer(Sin.AddressFamily), GetSocketType, GetSocketProtocol);
  1661. if FSocket = INVALID_SOCKET then
  1662. FLastError := synsock.WSAGetLastError;
  1663. {$IFNDEF CIL}
  1664. FD_ZERO(FFDSet);
  1665. FD_SET(FSocket, FFDSet);
  1666. {$ENDIF}
  1667. ExceptCheck;
  1668. if FIP6used then
  1669. DoStatus(HR_SocketCreate, 'IPv6')
  1670. else
  1671. DoStatus(HR_SocketCreate, 'IPv4');
  1672. ProcessDelayedOptions;
  1673. DoCreateSocket;
  1674. end;
  1675. end;
  1676. procedure TBlockSocket.CloseSocket;
  1677. begin
  1678. AbortSocket;
  1679. end;
  1680. procedure TBlockSocket.AbortSocket;
  1681. //var
  1682. // n: integer;
  1683. // p: TSynaOption;
  1684. begin
  1685. if FSocket <> INVALID_SOCKET then
  1686. synsock.CloseSocket(FSocket);
  1687. FSocket := INVALID_SOCKET;
  1688. {for n := FDelayedOptions.Count - 1 downto 0 do
  1689. begin
  1690. p := TSynaOption(FDelayedOptions[n]);
  1691. FreeAndNil(p);
  1692. end;
  1693. FDelayedOptions.Clear;}
  1694. Finalize(FDelayedOptions);
  1695. FFamily := FFamilySave;
  1696. DoStatus(HR_SocketClose, '');
  1697. FDisconnected := False;
  1698. end;
  1699. procedure TBlockSocket.Bind(const IP, Port: string);
  1700. var
  1701. Sin: TVarSin;
  1702. begin
  1703. ResetLastError;
  1704. if (FSocket <> INVALID_SOCKET)
  1705. or not((FFamily = SF_ANY) and (IP = cAnyHost) and (Port = cAnyPort)) then
  1706. begin
  1707. SetSin(Sin, IP, Port);
  1708. if FLastError = 0 then
  1709. begin
  1710. if FSocket = INVALID_SOCKET then
  1711. InternalCreateSocket(Sin);
  1712. SockCheck(synsock.Bind(FSocket, Sin));
  1713. GetSinLocal;
  1714. FBuffer := '';
  1715. FBinded := True;
  1716. end;
  1717. ExceptCheck;
  1718. DoStatus(HR_Bind, IP + ':' + Port);
  1719. end;
  1720. end;
  1721. procedure TBlockSocket.Connect(const IP, Port: string);
  1722. var
  1723. Sin: TVarSin;
  1724. b: boolean;
  1725. {$IFDEF MSWINDOWS}
  1726. lError: Integer;
  1727. {$ENDIF}
  1728. begin
  1729. SetSin(Sin, IP, Port);
  1730. if FLastError = 0 then
  1731. begin
  1732. if FSocket = INVALID_SOCKET then
  1733. InternalCreateSocket(Sin);
  1734. if FConnectionTimeout > 0 then
  1735. begin
  1736. // connect in non-blocking mode
  1737. b := NonBlockMode;
  1738. NonBlockMode := true;
  1739. SockCheck(synsock.Connect(FSocket, Sin));
  1740. if (FLastError = WSAEINPROGRESS) OR (FLastError = WSAEWOULDBLOCK) then
  1741. if not CanWrite(FConnectionTimeout) then
  1742. FLastError := WSAETIMEDOUT;
  1743. {$IFDEF MSWINDOWS}
  1744. lError := FLastError;
  1745. {$ENDIF}
  1746. NonBlockMode := b;
  1747. {$IFDEF MSWINDOWS}
  1748. FLastError := lError;
  1749. {$ENDIF}
  1750. end
  1751. else
  1752. SockCheck(synsock.Connect(FSocket, Sin));
  1753. if FLastError = 0 then
  1754. GetSins;
  1755. FBuffer := '';
  1756. FLastCR := False;
  1757. FLastLF := False;
  1758. end;
  1759. ExceptCheck;
  1760. DoStatus(HR_Connect, IP + ':' + Port);
  1761. end;
  1762. procedure TBlockSocket.Listen;
  1763. begin
  1764. SockCheck(synsock.Listen(FSocket, SOMAXCONN));
  1765. GetSins;
  1766. ExceptCheck;
  1767. DoStatus(HR_Listen, '');
  1768. end;
  1769. function TBlockSocket.Accept: TSocket;
  1770. begin
  1771. Result := synsock.Accept(FSocket, FRemoteSin);
  1772. /// SockCheck(Result);
  1773. ExceptCheck;
  1774. DoStatus(HR_Accept, '');
  1775. end;
  1776. procedure TBlockSocket.GetSinLocal;
  1777. begin
  1778. synsock.GetSockName(FSocket, FLocalSin);
  1779. end;
  1780. procedure TBlockSocket.GetSinRemote;
  1781. begin
  1782. synsock.GetPeerName(FSocket, FRemoteSin);
  1783. end;
  1784. procedure TBlockSocket.GetSins;
  1785. begin
  1786. GetSinLocal;
  1787. GetSinRemote;
  1788. end;
  1789. procedure TBlockSocket.SetBandwidth(Value: Integer);
  1790. begin
  1791. MaxSendBandwidth := Value;
  1792. MaxRecvBandwidth := Value;
  1793. end;
  1794. procedure TBlockSocket.LimitBandwidth(Length: Integer; MaxB: integer; var Next: UInt32);
  1795. var
  1796. x: UInt32;
  1797. y: UInt32;
  1798. n: integer;
  1799. begin
  1800. if FStopFlag then
  1801. exit;
  1802. if MaxB > 0 then
  1803. begin
  1804. y := GetTick;
  1805. if Next > y then
  1806. begin
  1807. x := Next - y;
  1808. if x > 0 then
  1809. begin
  1810. DoStatus(HR_Wait, IntToStr(x));
  1811. sleep(x mod 250);
  1812. for n := 1 to x div 250 do
  1813. if FStopFlag then
  1814. Break
  1815. else
  1816. sleep(250);
  1817. end;
  1818. end;
  1819. Next := GetTick + Trunc((Length / MaxB) * 1000);
  1820. end;
  1821. end;
  1822. function TBlockSocket.TestStopFlag: Boolean;
  1823. begin
  1824. DoHeartbeat;
  1825. Result := FStopFlag;
  1826. if Result then
  1827. begin
  1828. FStopFlag := False;
  1829. FLastError := WSAECONNABORTED;
  1830. ExceptCheck;
  1831. end;
  1832. end;
  1833. function TBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  1834. {$IFNDEF CIL}
  1835. var
  1836. x, y: integer;
  1837. l, r: integer;
  1838. p: Pointer;
  1839. {$ENDIF}
  1840. begin
  1841. Result := 0;
  1842. if TestStopFlag then
  1843. Exit;
  1844. DoMonitor(True, Buffer, Length);
  1845. {$IFDEF CIL}
  1846. Result := synsock.Send(FSocket, Buffer, Length, 0);
  1847. {$ELSE}
  1848. l := Length;
  1849. x := 0;
  1850. while x < l do
  1851. begin
  1852. y := l - x;
  1853. if y > FSendMaxChunk then
  1854. y := FSendMaxChunk;
  1855. if y > 0 then
  1856. begin
  1857. LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
  1858. p := IncPoint(Buffer, x);
  1859. r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
  1860. SockCheck(r);
  1861. if FLastError = WSAEWOULDBLOCK then
  1862. begin
  1863. if CanWrite(FNonblockSendTimeout) then
  1864. begin
  1865. r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
  1866. SockCheck(r);
  1867. end
  1868. else
  1869. FLastError := WSAETIMEDOUT;
  1870. end;
  1871. if FLastError <> 0 then
  1872. Break;
  1873. Inc(x, r);
  1874. Inc(Result, r);
  1875. Inc(FSendCounter, r);
  1876. DoStatus(HR_WriteCount, IntToStr(r));
  1877. end
  1878. else
  1879. break;
  1880. end;
  1881. {$ENDIF}
  1882. ExceptCheck;
  1883. end;
  1884. procedure TBlockSocket.SendByte(Data: Byte);
  1885. {$IFDEF CIL}
  1886. var
  1887. buf: TMemory;
  1888. {$ENDIF}
  1889. begin
  1890. {$IFDEF CIL}
  1891. setlength(buf, 1);
  1892. buf[0] := Data;
  1893. SendBuffer(buf, 1);
  1894. {$ELSE}
  1895. SendBuffer(@Data, 1);
  1896. {$ENDIF}
  1897. end;
  1898. procedure TBlockSocket.SendString(Data: TSynaBytes);
  1899. var
  1900. buf: TMemory;
  1901. count: Integer;
  1902. begin
  1903. {$IFDEF CIL}
  1904. buf := BytesOf(Data);
  1905. count := Length(Data);
  1906. {$ELSE}
  1907. {$IFDEF UNICODE}
  1908. buf := TSynaBytes(Data).Data; //TSynaByte(Data)
  1909. count := Data.Length; // avoid conversion
  1910. {$ELSE}
  1911. buf := Pointer(data);
  1912. count := Length(Data);
  1913. {$ENDIF}
  1914. {$ENDIF}
  1915. SendBuffer(buf, count);
  1916. end;
  1917. procedure TBlockSocket.SendInteger(Data: integer);
  1918. var
  1919. buf: TMemory;
  1920. begin
  1921. {$IFDEF CIL}
  1922. buf := System.BitConverter.GetBytes(Data);
  1923. {$ELSE}
  1924. buf := @Data;
  1925. {$ENDIF}
  1926. SendBuffer(buf, SizeOf(Data));
  1927. end;
  1928. procedure TBlockSocket.SendBlock(const Data: string);
  1929. var
  1930. i: integer;
  1931. begin
  1932. i := SwapBytes(Length(data));
  1933. SendString(Codelongint(i) + Data);
  1934. end;
  1935. procedure TBlockSocket.InternalSendStream(const Stream: TStream; WithSize, Indy: boolean);
  1936. var
  1937. l: int64;
  1938. yr: integer;
  1939. s: string;
  1940. b: boolean;
  1941. {$IFDEF CIL}
  1942. buf: TMemory;
  1943. {$ENDIF}
  1944. begin
  1945. b := true;
  1946. l := 0;
  1947. if WithSize then
  1948. begin
  1949. l := Stream.Size - Stream.Position;;
  1950. if not Indy then
  1951. l := synsock.HToNL(l);
  1952. end;
  1953. repeat
  1954. {$IFDEF CIL}
  1955. Setlength(buf, FSendMaxChunk);
  1956. yr := Stream.read(buf, FSendMaxChunk);
  1957. if yr > 0 then
  1958. begin
  1959. if WithSize and b then
  1960. begin
  1961. b := false;
  1962. SendString(CodeLongInt(l));
  1963. end;
  1964. SendBuffer(buf, yr);
  1965. if FLastError <> 0 then
  1966. break;
  1967. end
  1968. {$ELSE}
  1969. Setlength(s, FSendMaxChunk);
  1970. yr := Stream.read(Pointer(s)^, FSendMaxChunk);
  1971. if yr > 0 then
  1972. begin
  1973. SetLength(s, yr);
  1974. if WithSize and b then
  1975. begin
  1976. b := false;
  1977. SendString(CodeLongInt(l) + s);
  1978. end
  1979. else
  1980. SendString(s);
  1981. if FLastError <> 0 then
  1982. break;
  1983. end
  1984. {$ENDIF}
  1985. until yr <= 0;
  1986. end;
  1987. procedure TBlockSocket.SendStreamRaw(const Stream: TStream);
  1988. begin
  1989. InternalSendStream(Stream, false, false);
  1990. end;
  1991. procedure TBlockSocket.SendStreamIndy(const Stream: TStream);
  1992. begin
  1993. InternalSendStream(Stream, true, true);
  1994. end;
  1995. procedure TBlockSocket.SendStream(const Stream: TStream);
  1996. begin
  1997. InternalSendStream(Stream, true, false);
  1998. end;
  1999. function TBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
  2000. begin
  2001. Result := 0;
  2002. if TestStopFlag then
  2003. Exit;
  2004. LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  2005. Result := synsock.Recv(FSocket, Buffer, Length, MSG_NOSIGNAL);
  2006. if Result = 0 then
  2007. FLastError := WSAECONNRESET
  2008. else
  2009. SockCheck(Result);
  2010. ExceptCheck;
  2011. if Result > 0 then
  2012. begin
  2013. Inc(FRecvCounter, Result);
  2014. DoStatus(HR_ReadCount, IntToStr(Result));
  2015. DoMonitor(False, Buffer, Result);
  2016. DoReadFilter(Buffer, Result);
  2017. end;
  2018. end;
  2019. function TBlockSocket.RecvBufferEx(Buffer: TMemory; Len: Integer;
  2020. Timeout: Integer): Integer;
  2021. var
  2022. s: TSynaBytes;
  2023. rl, l: integer;
  2024. ti: UInt32;
  2025. {$IFDEF CIL}
  2026. n: integer;
  2027. b: TMemory;
  2028. {$ENDIF}
  2029. begin
  2030. ResetLastError;
  2031. Result := 0;
  2032. if Len > 0 then
  2033. begin
  2034. rl := 0;
  2035. repeat
  2036. ti := GetTick;
  2037. s := RecvPacket(Timeout);
  2038. l := s.length;
  2039. if (rl + l) > Len then
  2040. l := Len - rl;
  2041. {$IFDEF CIL}
  2042. b := BytesOf(s);
  2043. for n := 0 to l do
  2044. Buffer[rl + n] := b[n];
  2045. {$ELSE}
  2046. Move({$IFNDEF UNICODE}Pointer(s)^{$ELSE}s.Bytes[0]{$ENDIF},
  2047. IncPoint(Buffer, rl)^, l);
  2048. {$ENDIF}
  2049. rl := rl + l;
  2050. if FLastError <> 0 then
  2051. Break;
  2052. if rl >= Len then
  2053. Break;
  2054. if not FInterPacketTimeout then
  2055. begin
  2056. Timeout := Timeout - integer(TickDelta(ti, GetTick));
  2057. if Timeout <= 0 then
  2058. begin
  2059. FLastError := WSAETIMEDOUT;
  2060. Break;
  2061. end;
  2062. end;
  2063. until False;
  2064. DeleteInternal(s, 1, l);
  2065. FBuffer := s;
  2066. Result := rl;
  2067. end;
  2068. end;
  2069. function TBlockSocket.RecvBufferStr(Len: Integer; Timeout: Integer): TSynaBytes;
  2070. var
  2071. x: integer;
  2072. buf: TBytes;
  2073. begin
  2074. Result := '';
  2075. if Len > 0 then
  2076. begin
  2077. Setlength(Buf, Len);
  2078. x := RecvBufferEx(@buf[0], Len, Timeout);
  2079. if FLastError = 0 then
  2080. begin
  2081. SetLength(Buf, x);
  2082. {$IFDEF UNICODE}
  2083. Result.Length := x;
  2084. Move(Buf[0], Result.Bytes[0], x);
  2085. {$ELSE}
  2086. Result := StringOf(Buf);
  2087. {$ENDIF}
  2088. end
  2089. else
  2090. Result := '';
  2091. Setlength(Buf, 0);
  2092. end;
  2093. end;
  2094. function TBlockSocket.RecvPacket(Timeout: Integer): TSynaBytes;
  2095. var
  2096. x: Integer;
  2097. buf: TBytes;
  2098. begin
  2099. Result := '';
  2100. ResetLastError;
  2101. if FBuffer <> '' then
  2102. begin
  2103. Result := FBuffer;
  2104. FBuffer := '';
  2105. end
  2106. else
  2107. begin
  2108. {$IFDEF MSWINDOWS}
  2109. //not drain CPU on large downloads...
  2110. Sleep(0);
  2111. {$ENDIF}
  2112. x := WaitingData;
  2113. if x > 0 then
  2114. begin
  2115. SetLength(Buf, x);
  2116. x := RecvBuffer(Buf, x);
  2117. if x >= 0 then
  2118. begin
  2119. SetLength(Buf, x);
  2120. {$IFDEF UNICODE} Result := TSynaBytes(buf); {$ELSE} Result := StringOf(buf); {$ENDIF}
  2121. end;
  2122. end
  2123. else
  2124. begin
  2125. if CanRead(Timeout) then
  2126. begin
  2127. x := WaitingData;
  2128. if x = 0 then
  2129. FLastError := WSAECONNRESET;
  2130. if x > 0 then
  2131. begin
  2132. SetLength(Buf, x);
  2133. x := RecvBuffer(Buf, x);
  2134. if x >= 0 then
  2135. begin
  2136. SetLength(Buf, x);
  2137. {$IFDEF UNICODE} Result := TSynaBytes(buf); {$ELSE} Result := StringOf(buf); {$ENDIF}
  2138. end;
  2139. SetLength(Buf, 0);
  2140. end;
  2141. end
  2142. else
  2143. FLastError := WSAETIMEDOUT;
  2144. end;
  2145. end;
  2146. if FConvertLineEnd and (Result <> '') then
  2147. begin
  2148. if FLastCR and (Result[1] = LF) then
  2149. DeleteInternal(Result, 1, 1);
  2150. if FLastLF and (Result[1] = CR) then
  2151. DeleteInternal(Result, 1, 1);
  2152. FLastCR := False;
  2153. FLastLF := False;
  2154. end;
  2155. ExceptCheck;
  2156. end;
  2157. function TBlockSocket.RecvByte(Timeout: Integer): Byte;
  2158. begin
  2159. Result := 0;
  2160. ResetLastError;
  2161. if FBuffer = '' then
  2162. FBuffer := RecvPacket(Timeout);
  2163. if (FLastError = 0) and (FBuffer <> '') then
  2164. begin
  2165. Result := Ord(FBuffer[1]);
  2166. {$IFNDEF UNICODE}
  2167. Delete(FBuffer, 1, 1);
  2168. {$ELSE}
  2169. FBuffer.Delete(1, 1); // TEST!
  2170. {$ENDIF}
  2171. end;
  2172. ExceptCheck;
  2173. end;
  2174. function TBlockSocket.RecvInteger(Timeout: Integer): Integer;
  2175. var
  2176. s: string;
  2177. begin
  2178. Result := 0;
  2179. s := RecvBufferStr(4, Timeout);
  2180. if FLastError = 0 then
  2181. Result := (ord(s[1]) + ord(s[2]) * 256) + (ord(s[3]) + ord(s[4]) * 256) * 65536;
  2182. end;
  2183. function TBlockSocket.RecvTerminated(Timeout: Integer; const Terminator: string): string;
  2184. var
  2185. x: Integer;
  2186. s: TSynaBytes;
  2187. l: Integer;
  2188. CorCRLF: Boolean;
  2189. t: string;
  2190. tl: integer;
  2191. ti: UInt32;
  2192. begin
  2193. ResetLastError;
  2194. Result := '';
  2195. l := Length(Terminator);
  2196. if l = 0 then
  2197. Exit;
  2198. tl := l;
  2199. CorCRLF := FConvertLineEnd and (Terminator = CRLF);
  2200. s := '';
  2201. x := 0;
  2202. repeat
  2203. //get rest of FBuffer or incomming new data...
  2204. ti := GetTick;
  2205. s := s + RecvPacket(Timeout);
  2206. if FLastError <> 0 then
  2207. Break;
  2208. x := 0;
  2209. if s.Length > 0 then
  2210. if CorCRLF then
  2211. begin
  2212. t := '';
  2213. x := PosCRLF(s, t);
  2214. tl := t.Length;
  2215. if t = CR then
  2216. FLastCR := True;
  2217. if t = LF then
  2218. FLastLF := True;
  2219. end
  2220. else
  2221. begin
  2222. x := pos(Terminator, s);
  2223. tl := l;
  2224. end;
  2225. if (FMaxLineLength <> 0) and (s.Length > FMaxLineLength) then
  2226. begin
  2227. FLastError := WSAENOBUFS;
  2228. Break;
  2229. end;
  2230. if x > 0 then
  2231. Break;
  2232. if not FInterPacketTimeout then
  2233. begin
  2234. Timeout := Timeout - integer(TickDelta(ti, GetTick));
  2235. if Timeout <= 0 then
  2236. begin
  2237. FLastError := WSAETIMEDOUT;
  2238. Break;
  2239. end;
  2240. end;
  2241. until False;
  2242. if x > 0 then
  2243. begin
  2244. Result := Copy(s, 1, x - 1);
  2245. DeleteInternal(s, 1, x + tl - 1);
  2246. end;
  2247. FBuffer := s;
  2248. ExceptCheck;
  2249. end;
  2250. function TBlockSocket.RecvString(Timeout: Integer): string;
  2251. var
  2252. s: string;
  2253. begin
  2254. Result := '';
  2255. s := RecvTerminated(Timeout, CRLF);
  2256. if FLastError = 0 then
  2257. Result := s;
  2258. end;
  2259. function TBlockSocket.RecvBlock(Timeout: Integer): string;
  2260. var
  2261. x: integer;
  2262. begin
  2263. Result := '';
  2264. x := RecvInteger(Timeout);
  2265. if FLastError = 0 then
  2266. Result := RecvBufferStr(x, Timeout);
  2267. end;
  2268. procedure TBlockSocket.RecvStreamRaw(const Stream: TStream; Timeout: Integer);
  2269. var
  2270. s: string;
  2271. begin
  2272. repeat
  2273. s := RecvPacket(Timeout);
  2274. if FLastError = 0 then
  2275. WriteStrToStream(Stream, s);
  2276. until FLastError <> 0;
  2277. end;
  2278. procedure TBlockSocket.RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: int64);
  2279. var
  2280. s: TSynaBytes;
  2281. n: int64;
  2282. {$IFDEF CIL}
  2283. buf: TMemory;
  2284. {$ENDIF}
  2285. begin
  2286. n := Size div int64(FSendMaxChunk);
  2287. while n > 0 do
  2288. begin
  2289. {$IFDEF CIL}
  2290. SetLength(buf, FSendMaxChunk);
  2291. RecvBufferEx(buf, FSendMaxChunk, Timeout);
  2292. if FLastError <> 0 then
  2293. Exit;
  2294. Stream.Write(buf, FSendMaxChunk);
  2295. {$ELSE}
  2296. s := RecvBufferStr(FSendMaxChunk, Timeout);
  2297. if FLastError <> 0 then
  2298. Exit;
  2299. WriteStrToStream(Stream, s);
  2300. {$ENDIF}
  2301. dec(n);
  2302. end;
  2303. n := Size mod int64(FSendMaxChunk);
  2304. if n > 0 then
  2305. begin
  2306. {$IFDEF CIL}
  2307. SetLength(buf, n);
  2308. RecvBufferEx(buf, n, Timeout);
  2309. if FLastError <> 0 then
  2310. Exit;
  2311. Stream.Write(buf, n);
  2312. {$ELSE}
  2313. s := RecvBufferStr(n, Timeout);
  2314. if FLastError <> 0 then
  2315. Exit;
  2316. WriteStrToStream(Stream, s);
  2317. {$ENDIF}
  2318. end;
  2319. end;
  2320. procedure TBlockSocket.RecvStreamIndy(const Stream: TStream; Timeout: Integer);
  2321. var
  2322. x: integer;
  2323. begin
  2324. x := RecvInteger(Timeout);
  2325. x := synsock.NToHL(x);
  2326. if FLastError = 0 then
  2327. RecvStreamSize(Stream, Timeout, x);
  2328. end;
  2329. procedure TBlockSocket.RecvStream(const Stream: TStream; Timeout: Integer);
  2330. var
  2331. x: integer;
  2332. begin
  2333. x := RecvInteger(Timeout);
  2334. if FLastError = 0 then
  2335. RecvStreamSize(Stream, Timeout, x);
  2336. end;
  2337. function TBlockSocket.PeekBuffer(Buffer: TMemory; Length: Integer): Integer;
  2338. begin
  2339. {$IFNDEF CIL}
  2340. // Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK + MSG_NOSIGNAL);
  2341. Result := synsock.Recv(FSocket, Buffer, Length, MSG_PEEK + MSG_NOSIGNAL);
  2342. SockCheck(Result);
  2343. ExceptCheck;
  2344. {$ENDIF}
  2345. end;
  2346. function TBlockSocket.PeekByte(Timeout: Integer): Byte;
  2347. var
  2348. s: string;
  2349. begin
  2350. {$IFNDEF CIL}
  2351. Result := 0;
  2352. if CanRead(Timeout) then
  2353. begin
  2354. SetLength(s, 1);
  2355. PeekBuffer(Pointer(s), 1);
  2356. if s <> '' then
  2357. Result := Ord(s[1]);
  2358. end
  2359. else
  2360. FLastError := WSAETIMEDOUT;
  2361. ExceptCheck;
  2362. {$ENDIF}
  2363. end;
  2364. procedure TBlockSocket.ResetLastError;
  2365. begin
  2366. FLastError := 0;
  2367. FLastErrorDesc := '';
  2368. end;
  2369. function TBlockSocket.SockCheck(SockResult: Integer): Integer;
  2370. begin
  2371. ResetLastError;
  2372. if SockResult = integer(SOCKET_ERROR) then
  2373. begin
  2374. FLastError := synsock.WSAGetLastError;
  2375. if FLastError <= WSABASEERR then
  2376. Inc(FLastError, WSABASEERR);
  2377. FLastErrorDesc := GetErrorDescEx;
  2378. end;
  2379. Result := FLastError;
  2380. end;
  2381. procedure TBlockSocket.ExceptCheck;
  2382. var
  2383. e: ESynapseError;
  2384. begin
  2385. FLastErrorDesc := GetErrorDescEx;
  2386. if (LastError <> 0) and (LastError <> WSAEINPROGRESS)
  2387. and (LastError <> WSAEWOULDBLOCK) then
  2388. begin
  2389. DoStatus(HR_Error, IntToStr(FLastError) + ',' + FLastErrorDesc);
  2390. FDisconnected := True;
  2391. if FRaiseExcept then
  2392. begin
  2393. if FLastError = 104 then
  2394. e := EResetByPeer.Create(Format('Synapse TCP/IP socket error. Reset by peer %d: %s',
  2395. [FLastError, FLastErrorDesc]))
  2396. else if FLastError = 10098 then
  2397. e := ECouldNotBindSocket.Create(Format('Synapse TCP/IP socket error. Could not bind socket %d: %s',
  2398. [FLastError, FLastErrorDesc]))
  2399. else if FLastError = 10054 then
  2400. e := EConnectionResetByPeer.Create(Format('Synapse TCP/IP socket error. Connection reset by peer %d: %s',
  2401. [FLastError, FLastErrorDesc]))
  2402. else if FLastError = 10057 then
  2403. e := ESockectIsnotConnected.Create(Format('Synapse TCP/IP socket error. Socket is not connected %d: %s',
  2404. [FLastError, FLastErrorDesc]))
  2405. else if FLastError = 10060 then
  2406. e := EConnectionTimedOut.Create(Format('Synapse TCP/IP socket error. Connection timed out %d: %s',
  2407. [FLastError, FLastErrorDesc]))
  2408. else if FLastError = 10061 then
  2409. e := EConnectionRefused.Create(Format('Synapse TCP/IP socket error. Connection refused %d: %s',
  2410. [FLastError, FLastErrorDesc]))
  2411. else if FLastError = 10049 then
  2412. e := ECantAssignAddress.Create(Format('Synapse TCP/IP socket error. Can''t assign requested address %d: %s',
  2413. [FLastError, FLastErrorDesc]))
  2414. else if FLastError = -2 then
  2415. e := ESocketMinus2.Create(Format('Synapse TCP/IP socket error %d: %s',
  2416. [FLastError, FLastErrorDesc]))
  2417. else e := ESynapseError.Create(Format('Synapse TCP/IP socket error %d: %s',
  2418. [FLastError, FLastErrorDesc]));
  2419. e.ErrorCode := FLastError;
  2420. e.ErrorMessage := FLastErrorDesc;
  2421. raise e;
  2422. end;
  2423. end;
  2424. end;
  2425. function TBlockSocket.WaitingData: Integer;
  2426. var
  2427. x: Integer;
  2428. begin
  2429. Result := 0;
  2430. if synsock.IoctlSocket(FSocket, FIONREAD, x) = 0 then
  2431. Result := x;
  2432. if Result > c64k then
  2433. Result := c64k;
  2434. end;
  2435. function TBlockSocket.WaitingDataEx: Integer;
  2436. begin
  2437. if FBuffer <> '' then
  2438. Result := FBuffer.Length
  2439. else
  2440. Result := WaitingData;
  2441. end;
  2442. procedure TBlockSocket.Purge;
  2443. begin
  2444. Sleep(1);
  2445. try
  2446. while (FBuffer.Length > 0) or (WaitingData > 0) do
  2447. begin
  2448. RecvPacket(0);
  2449. if FLastError <> 0 then
  2450. break;
  2451. end;
  2452. except
  2453. on exception do;
  2454. end;
  2455. ResetLastError;
  2456. end;
  2457. procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
  2458. var
  2459. d: TSynaOption;
  2460. begin
  2461. //d := TSynaOption.Create;
  2462. d.Option := SOT_Linger;
  2463. d.Enabled := Enable;
  2464. d.Value := Linger;
  2465. DelayedOption(d);
  2466. end;
  2467. function TBlockSocket.LocalName: string;
  2468. begin
  2469. Result := synsock.GetHostName;
  2470. if Result = '' then
  2471. Result := '127.0.0.1';
  2472. end;
  2473. procedure TBlockSocket.ResolveNameToIP(const Name: string; const IPList:
  2474. TStrings);
  2475. begin
  2476. IPList.Clear;
  2477. synsock.ResolveNameToIP(Name, FamilyToAF(FFamily), GetSocketprotocol, GetSocketType, IPList);
  2478. if IPList.Count = 0 then
  2479. IPList.Add(cAnyHost);
  2480. end;
  2481. function TBlockSocket.ResolveName(const Name: string): string;
  2482. var
  2483. l: TStringList;
  2484. begin
  2485. l := TStringList.Create;
  2486. try
  2487. ResolveNameToIP(Name, l);
  2488. Result := l[0];
  2489. finally
  2490. FreeAndNil(l);
  2491. end;
  2492. end;
  2493. function TBlockSocket.ResolvePort(const Port: string): Word;
  2494. begin
  2495. Result := synsock.ResolvePort(Port, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
  2496. end;
  2497. function TBlockSocket.ResolveIPToName(IP: string): string;
  2498. begin
  2499. if not IsIP(IP) and not IsIp6(IP) then
  2500. IP := ResolveName(IP);
  2501. Result := synsock.ResolveIPToName(IP, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
  2502. end;
  2503. procedure TBlockSocket.SetRemoteSin(const IP, Port: string);
  2504. begin
  2505. SetSin(FRemoteSin, IP, Port);
  2506. end;
  2507. function TBlockSocket.GetLocalSinIP: string;
  2508. begin
  2509. Result := GetSinIP(FLocalSin);
  2510. end;
  2511. function TBlockSocket.GetRecvTimeout: integer;
  2512. var
  2513. l: integer;
  2514. begin
  2515. l:=SizeOf(Integer);
  2516. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVTIMEO, @Result, l));
  2517. ExceptCheck;
  2518. end;
  2519. function TBlockSocket.GetRemoteSinIP: string;
  2520. begin
  2521. Result := GetSinIP(FRemoteSin);
  2522. end;
  2523. function TBlockSocket.GetLocalSinPort: Integer;
  2524. begin
  2525. Result := GetSinPort(FLocalSin);
  2526. end;
  2527. function TBlockSocket.GetRemoteSinPort: Integer;
  2528. begin
  2529. Result := GetSinPort(FRemoteSin);
  2530. end;
  2531. function TBlockSocket.InternalCanRead(Timeout: Integer): Boolean;
  2532. {$IFDEF CIL}
  2533. begin
  2534. Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectRead);
  2535. {$ELSE}
  2536. var
  2537. TimeVal: PTimeVal;
  2538. TimeV: TTimeVal;
  2539. x: Integer;
  2540. FDSet: TFDSet;
  2541. begin
  2542. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2543. TimeV.tv_sec := Timeout div 1000;
  2544. TimeVal := @TimeV;
  2545. if Timeout = -1 then
  2546. TimeVal := nil;
  2547. FDSet := FFdSet;
  2548. x := synsock.Select(integer(FSocket + 1), @FDSet, nil, nil, TimeVal);
  2549. SockCheck(x);
  2550. if FLastError <> 0 then
  2551. x := 0;
  2552. Result := x > 0;
  2553. {$ENDIF}
  2554. end;
  2555. function TBlockSocket.CanRead(Timeout: Integer): Boolean;
  2556. var
  2557. ti, tr: Integer;
  2558. n: integer;
  2559. begin
  2560. if (FHeartbeatRate <> 0) and (Timeout <> -1) then
  2561. begin
  2562. ti := Timeout div FHeartbeatRate;
  2563. tr := Timeout mod FHeartbeatRate;
  2564. end
  2565. else
  2566. begin
  2567. ti := 0;
  2568. tr := Timeout;
  2569. end;
  2570. Result := InternalCanRead(tr);
  2571. if not Result then
  2572. for n := 0 to ti do
  2573. begin
  2574. DoHeartbeat;
  2575. if FStopFlag then
  2576. begin
  2577. Result := False;
  2578. FStopFlag := False;
  2579. Break;
  2580. end;
  2581. Result := InternalCanRead(FHeartbeatRate);
  2582. if Result then
  2583. break;
  2584. end;
  2585. ExceptCheck;
  2586. if Result then
  2587. DoStatus(HR_CanRead, '');
  2588. end;
  2589. function TBlockSocket.InternalCanWrite(Timeout: Integer): Boolean;
  2590. {$IFDEF CIL}
  2591. begin
  2592. Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectWrite);
  2593. {$ELSE}
  2594. var
  2595. TimeVal: PTimeVal;
  2596. TimeV: TTimeVal;
  2597. x: Integer;
  2598. FDSet: TFDSet;
  2599. begin
  2600. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2601. TimeV.tv_sec := Timeout div 1000;
  2602. TimeVal := @TimeV;
  2603. if Timeout = -1 then
  2604. TimeVal := nil;
  2605. FDSet := FFdSet;
  2606. x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
  2607. SockCheck(x);
  2608. if FLastError <> 0 then
  2609. x := 0;
  2610. Result := x > 0;
  2611. {$ENDIF}
  2612. end;
  2613. function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
  2614. var
  2615. ti, tr: Integer;
  2616. n: integer;
  2617. begin
  2618. if (FHeartbeatRate <> 0) and (Timeout <> -1) then
  2619. begin
  2620. ti := Timeout div FHeartbeatRate;
  2621. tr := Timeout mod FHeartbeatRate;
  2622. end
  2623. else
  2624. begin
  2625. ti := 0;
  2626. tr := Timeout;
  2627. end;
  2628. Result := InternalCanWrite(tr);
  2629. if not Result then
  2630. for n := 0 to ti do
  2631. begin
  2632. DoHeartbeat;
  2633. if FStopFlag then
  2634. begin
  2635. Result := False;
  2636. FStopFlag := False;
  2637. Break;
  2638. end;
  2639. Result := InternalCanWrite(FHeartbeatRate);
  2640. if Result then
  2641. break;
  2642. end;
  2643. ExceptCheck;
  2644. if Result then
  2645. DoStatus(HR_CanWrite, '');
  2646. end;
  2647. function TBlockSocket.CanReadEx(Timeout: Integer): Boolean;
  2648. begin
  2649. if FBuffer <> '' then
  2650. Result := True
  2651. else
  2652. Result := CanRead(Timeout);
  2653. end;
  2654. function TBlockSocket.SendBufferTo(const Buffer: TMemory; Length: Integer): Integer;
  2655. begin
  2656. Result := 0;
  2657. if TestStopFlag then
  2658. Exit;
  2659. DoMonitor(True, Buffer, Length);
  2660. LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
  2661. Result := synsock.SendTo(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
  2662. SockCheck(Result);
  2663. ExceptCheck;
  2664. Inc(FSendCounter, Result);
  2665. DoStatus(HR_WriteCount, IntToStr(Result));
  2666. end;
  2667. function TBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
  2668. begin
  2669. Result := 0;
  2670. if TestStopFlag then
  2671. Exit;
  2672. LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  2673. Result := synsock.RecvFrom(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
  2674. SockCheck(Result);
  2675. ExceptCheck;
  2676. Inc(FRecvCounter, Result);
  2677. DoStatus(HR_ReadCount, IntToStr(Result));
  2678. DoMonitor(False, Buffer, Result);
  2679. end;
  2680. function TBlockSocket.GetSizeRecvBuffer: Integer;
  2681. var
  2682. l: Integer;
  2683. {$IFDEF CIL}
  2684. buf: TMemory;
  2685. {$ENDIF}
  2686. begin
  2687. {$IFDEF CIL}
  2688. setlength(buf, 4);
  2689. SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVBUF), buf, l));
  2690. Result := System.BitConverter.ToInt32(buf,0);
  2691. {$ELSE}
  2692. l := SizeOf(Result);
  2693. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
  2694. if FLastError <> 0 then
  2695. Result := 1024;
  2696. ExceptCheck;
  2697. {$ENDIF}
  2698. end;
  2699. procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
  2700. var
  2701. d: TSynaOption;
  2702. begin
  2703. //d := TSynaOption.Create;
  2704. d.Option := SOT_RecvBuff;
  2705. d.Value := Size;
  2706. DelayedOption(d);
  2707. end;
  2708. function TBlockSocket.GetSizeSendBuffer: Integer;
  2709. var
  2710. l: Integer;
  2711. {$IFDEF CIL}
  2712. buf: TMemory;
  2713. {$ENDIF}
  2714. begin
  2715. {$IFDEF CIL}
  2716. setlength(buf, 4);
  2717. SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDBUF), buf, l));
  2718. Result := System.BitConverter.ToInt32(buf,0);
  2719. {$ELSE}
  2720. l := SizeOf(Result);
  2721. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
  2722. if FLastError <> 0 then
  2723. Result := 1024;
  2724. ExceptCheck;
  2725. {$ENDIF}
  2726. end;
  2727. procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
  2728. var
  2729. d: TSynaOption;
  2730. begin
  2731. //d := TSynaOption.Create;
  2732. d.Option := SOT_SendBuff;
  2733. d.Value := Size;
  2734. DelayedOption(d);
  2735. end;
  2736. procedure TBlockSocket.SetNagleMode(Value: Boolean);
  2737. var
  2738. d: TSynaOption;
  2739. begin
  2740. //d := TSynaOption.Create;
  2741. d.Option := SOT_NoDelay;
  2742. d.Enabled := Value;
  2743. DelayedOption(d);
  2744. end;
  2745. procedure TBlockSocket.SetNonBlockMode(Value: Boolean);
  2746. var
  2747. d: TSynaOption;
  2748. begin
  2749. //d := TSynaOption.Create;
  2750. d.Option := SOT_nonblock;
  2751. d.Enabled := Value;
  2752. DelayedOption(d);
  2753. end;
  2754. procedure TBlockSocket.SetTimeout(Timeout: Integer);
  2755. begin
  2756. SetSendTimeout(Timeout);
  2757. SetRecvTimeout(Timeout);
  2758. end;
  2759. procedure TBlockSocket.SetSendTimeout(Timeout: Integer);
  2760. var
  2761. d: TSynaOption;
  2762. begin
  2763. //d := TSynaOption.Create;
  2764. d.Option := SOT_sendtimeout;
  2765. d.Value := Timeout;
  2766. DelayedOption(d);
  2767. end;
  2768. procedure TBlockSocket.SetRecvTimeout(Timeout: Integer);
  2769. var
  2770. d: TSynaOption;
  2771. begin
  2772. //d := TSynaOption.Create;
  2773. d.Option := SOT_recvtimeout;
  2774. d.Value := Timeout;
  2775. DelayedOption(d);
  2776. end;
  2777. {$IFNDEF CIL}
  2778. function TBlockSocket.GroupCanRead(const SocketList: TSocketList; Timeout: Integer;
  2779. const CanReadList: TSocketList): boolean;
  2780. var
  2781. FDSet: TFDSet;
  2782. TimeVal: PTimeVal;
  2783. TimeV: TTimeVal;
  2784. x, n: Integer;
  2785. Max: Integer;
  2786. begin
  2787. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2788. TimeV.tv_sec := Timeout div 1000;
  2789. TimeVal := @TimeV;
  2790. if Timeout = -1 then
  2791. TimeVal := nil;
  2792. FD_ZERO(FDSet);
  2793. Max := 0;
  2794. for n := 0 to SocketList.Count - 1 do
  2795. if TObject(SocketList.Items[n]) is TBlockSocket then
  2796. begin
  2797. if TBlockSocket(SocketList.Items[n]).Socket > Max then
  2798. Max := TBlockSocket(SocketList.Items[n]).Socket;
  2799. FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
  2800. end;
  2801. x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
  2802. SockCheck(x);
  2803. ExceptCheck;
  2804. if FLastError <> 0 then
  2805. x := 0;
  2806. Result := x > 0;
  2807. CanReadList.Clear;
  2808. if Result then
  2809. for n := 0 to SocketList.Count - 1 do
  2810. if TObject(SocketList.Items[n]) is TBlockSocket then
  2811. if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
  2812. CanReadList.Add(TBlockSocket(SocketList.Items[n]));
  2813. end;
  2814. {$ENDIF}
  2815. procedure TBlockSocket.EnableReuse(Value: Boolean);
  2816. var
  2817. d: TSynaOption;
  2818. begin
  2819. //d := TSynaOption.Create;
  2820. d.Option := SOT_reuse;
  2821. d.Enabled := Value;
  2822. DelayedOption(d);
  2823. end;
  2824. procedure TBlockSocket.SetTTL(TTL: integer);
  2825. var
  2826. d: TSynaOption;
  2827. begin
  2828. //d := TSynaOption.Create;
  2829. d.Option := SOT_TTL;
  2830. d.Value := TTL;
  2831. DelayedOption(d);
  2832. end;
  2833. function TBlockSocket.GetTTL:integer;
  2834. var
  2835. l: Integer;
  2836. begin
  2837. {$IFNDEF CIL}
  2838. l := SizeOf(Result);
  2839. if FIP6Used then
  2840. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, @Result, l))
  2841. else
  2842. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_TTL, @Result, l));
  2843. ExceptCheck;
  2844. {$ENDIF}
  2845. end;
  2846. procedure TBlockSocket.SetFamily(Value: TSocketFamily);
  2847. begin
  2848. FFamily := Value;
  2849. FFamilySave := Value;
  2850. end;
  2851. procedure TBlockSocket.SetSocket(Value: TSocket);
  2852. begin
  2853. FRecvCounter := 0;
  2854. FSendCounter := 0;
  2855. FSocket := Value;
  2856. {$IFNDEF CIL}
  2857. FD_ZERO(FFDSet);
  2858. FD_SET(FSocket, FFDSet);
  2859. {$ENDIF}
  2860. GetSins;
  2861. FIP6Used := FRemoteSin.AddressFamily = AF_INET6;
  2862. end;
  2863. function TBlockSocket.GetWsaData: TWSAData;
  2864. begin
  2865. {$IFDEF ONCEWINSOCK}
  2866. Result := WsaDataOnce;
  2867. {$ELSE}
  2868. Result := FWsaDataOnce;
  2869. {$ENDIF}
  2870. end;
  2871. function TBlockSocket.GetSocketType: integer;
  2872. begin
  2873. Result := 0;
  2874. end;
  2875. function TBlockSocket.GetSocketProtocol: integer;
  2876. begin
  2877. Result := integer(IPPROTO_IP);
  2878. end;
  2879. procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
  2880. begin
  2881. if assigned(OnStatus) then
  2882. OnStatus(Self, Reason, Value);
  2883. if Reason = HR_SocketClose then
  2884. FDisconnected := True;
  2885. end;
  2886. procedure TBlockSocket.DoReadFilter(Buffer: TMemory; var Len: Integer);
  2887. var
  2888. s: string;
  2889. begin
  2890. if assigned(OnReadFilter) then
  2891. if Len > 0 then
  2892. begin
  2893. {$IFDEF CIL}
  2894. s := StringOf(Buffer);
  2895. {$ELSE}
  2896. SetLength(s, Len);
  2897. Move(Buffer^, Pointer(s)^, Len);
  2898. {$ENDIF}
  2899. OnReadFilter(Self, s);
  2900. if s.Length > Len then
  2901. SetLength(s, Len);
  2902. Len := s.Length;
  2903. {$IFDEF CIL}
  2904. Buffer := BytesOf(s);
  2905. {$ELSE}
  2906. Move(Pointer(s)^, Buffer^, Len);
  2907. {$ENDIF}
  2908. end;
  2909. end;
  2910. procedure TBlockSocket.DoCreateSocket;
  2911. begin
  2912. if assigned(OnCreateSocket) then
  2913. OnCreateSocket(Self);
  2914. end;
  2915. procedure TBlockSocket.DoMonitor(Writing: Boolean; const Buffer: TMemory; Len: Integer);
  2916. begin
  2917. if assigned(OnMonitor) then
  2918. begin
  2919. OnMonitor(Self, Writing, Buffer, Len);
  2920. end;
  2921. end;
  2922. procedure TBlockSocket.DoHeartbeat;
  2923. begin
  2924. if assigned(OnHeartbeat) and (FHeartbeatRate <> 0) then
  2925. begin
  2926. OnHeartbeat(Self);
  2927. end;
  2928. end;
  2929. function TBlockSocket.GetErrorDescEx: string;
  2930. begin
  2931. Result := GetErrorDesc(FLastError);
  2932. end;
  2933. class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
  2934. begin
  2935. {$IFDEF CIL}
  2936. if ErrorCode = 0 then
  2937. Result := ''
  2938. else
  2939. begin
  2940. Result := WSAGetLastErrorDesc;
  2941. if Result = '' then
  2942. Result := 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
  2943. end;
  2944. {$ELSE}
  2945. case ErrorCode of
  2946. 0:
  2947. Result := '';
  2948. WSAEINTR: {10004}
  2949. Result := 'Interrupted system call';
  2950. WSAEBADF: {10009}
  2951. Result := 'Bad file number';
  2952. WSAEACCES: {10013}
  2953. Result := 'Permission denied';
  2954. WSAEFAULT: {10014}
  2955. Result := 'Bad address';
  2956. WSAEINVAL: {10022}
  2957. Result := 'Invalid argument';
  2958. WSAEMFILE: {10024}
  2959. Result := 'Too many open files';
  2960. WSAEWOULDBLOCK: {10035}
  2961. Result := 'Operation would block';
  2962. WSAEINPROGRESS: {10036}
  2963. Result := 'Operation now in progress';
  2964. WSAEALREADY: {10037}
  2965. Result := 'Operation already in progress';
  2966. WSAENOTSOCK: {10038}
  2967. Result := 'Socket operation on nonsocket';
  2968. WSAEDESTADDRREQ: {10039}
  2969. Result := 'Destination address required';
  2970. WSAEMSGSIZE: {10040}
  2971. Result := 'Message too long';
  2972. WSAEPROTOTYPE: {10041}
  2973. Result := 'Protocol wrong type for Socket';
  2974. WSAENOPROTOOPT: {10042}
  2975. Result := 'Protocol not available';
  2976. WSAEPROTONOSUPPORT: {10043}
  2977. Result := 'Protocol not supported';
  2978. WSAESOCKTNOSUPPORT: {10044}
  2979. Result := 'Socket not supported';
  2980. WSAEOPNOTSUPP: {10045}
  2981. Result := 'Operation not supported on Socket';
  2982. WSAEPFNOSUPPORT: {10046}
  2983. Result := 'Protocol family not supported';
  2984. WSAEAFNOSUPPORT: {10047}
  2985. Result := 'Address family not supported';
  2986. WSAEADDRINUSE: {10048}
  2987. Result := 'Address already in use';
  2988. WSAEADDRNOTAVAIL: {10049}
  2989. Result := 'Can''t assign requested address';
  2990. WSAENETDOWN: {10050}
  2991. Result := 'Network is down';
  2992. WSAENETUNREACH: {10051}
  2993. Result := 'Network is unreachable';
  2994. WSAENETRESET: {10052}
  2995. Result := 'Network dropped connection on reset';
  2996. WSAECONNABORTED: {10053}
  2997. Result := 'Software caused connection abort';
  2998. WSAECONNRESET: {10054}
  2999. Result := 'Connection reset by peer';
  3000. WSAENOBUFS: {10055}
  3001. Result := 'No Buffer space available';
  3002. WSAEISCONN: {10056}
  3003. Result := 'Socket is already connected';
  3004. WSAENOTCONN: {10057}
  3005. Result := 'Socket is not connected';
  3006. WSAESHUTDOWN: {10058}
  3007. Result := 'Can''t send after Socket shutdown';
  3008. WSAETOOMANYREFS: {10059}
  3009. Result := 'Too many references:can''t splice';
  3010. WSAETIMEDOUT: {10060}
  3011. Result := 'Connection timed out';
  3012. WSAECONNREFUSED: {10061}
  3013. Result := 'Connection refused';
  3014. WSAELOOP: {10062}
  3015. Result := 'Too many levels of symbolic links';
  3016. WSAENAMETOOLONG: {10063}
  3017. Result := 'File name is too long';
  3018. WSAEHOSTDOWN: {10064}
  3019. Result := 'Host is down';
  3020. WSAEHOSTUNREACH: {10065}
  3021. Result := 'No route to host';
  3022. WSAENOTEMPTY: {10066}
  3023. Result := 'Directory is not empty';
  3024. WSAEPROCLIM: {10067}
  3025. Result := 'Too many processes';
  3026. WSAEUSERS: {10068}
  3027. Result := 'Too many users';
  3028. WSAEDQUOT: {10069}
  3029. Result := 'Disk quota exceeded';
  3030. WSAESTALE: {10070}
  3031. Result := 'Stale NFS file handle';
  3032. WSAEREMOTE: {10071}
  3033. Result := 'Too many levels of remote in path';
  3034. WSASYSNOTREADY: {10091}
  3035. Result := 'Network subsystem is unusable';
  3036. WSAVERNOTSUPPORTED: {10092}
  3037. Result := 'Winsock DLL cannot support this application';
  3038. WSANOTINITIALISED: {10093}
  3039. Result := 'Winsock not initialized';
  3040. WSAEDISCON: {10101}
  3041. Result := 'Disconnect';
  3042. WSAHOST_NOT_FOUND: {11001}
  3043. Result := 'Host not found';
  3044. WSATRY_AGAIN: {11002}
  3045. Result := 'Non authoritative - host not found';
  3046. WSANO_RECOVERY: {11003}
  3047. Result := 'Non recoverable error';
  3048. WSANO_DATA: {11004}
  3049. Result := 'Valid name, no data record of requested type'
  3050. else
  3051. Result := SysErrorMessage(ErrorCode) // 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
  3052. end;
  3053. {$ENDIF}
  3054. end;
  3055. {======================================================================}
  3056. constructor TSocksBlockSocket.Create;
  3057. begin
  3058. inherited Create;
  3059. FSocksIP:= '';
  3060. FSocksPort:= '1080';
  3061. FSocksTimeout:= 60000;
  3062. FSocksUsername:= '';
  3063. FSocksPassword:= '';
  3064. FUsingSocks := False;
  3065. FSocksResolver := True;
  3066. FSocksLastError := 0;
  3067. FSocksResponseIP := '';
  3068. FSocksResponsePort := '';
  3069. FSocksLocalIP := '';
  3070. FSocksLocalPort := '';
  3071. FSocksRemoteIP := '';
  3072. FSocksRemotePort := '';
  3073. FBypassFlag := False;
  3074. FSocksType := ST_Socks5;
  3075. end;
  3076. function TSocksBlockSocket.SocksOpen: boolean;
  3077. var
  3078. Buf: string;
  3079. n: integer;
  3080. begin
  3081. Result := False;
  3082. FUsingSocks := False;
  3083. if FSocksType <> ST_Socks5 then
  3084. begin
  3085. FUsingSocks := True;
  3086. Result := True;
  3087. end
  3088. else
  3089. begin
  3090. FBypassFlag := True;
  3091. try
  3092. if FSocksUsername = '' then
  3093. Buf := #5 + #1 + #0
  3094. else
  3095. Buf := #5 + #2 + #2 +#0;
  3096. SendString(Buf);
  3097. Buf := RecvBufferStr(2, FSocksTimeout);
  3098. if Buf.Length < 2 then
  3099. Exit;
  3100. if Buf[1] <> #5 then
  3101. Exit;
  3102. n := Ord(Buf[2]);
  3103. case n of
  3104. 0: //not need authorisation
  3105. ;
  3106. 2:
  3107. begin
  3108. buf := #1 + Char(Length(FSocksUsername)) + FSocksUsername +
  3109. Char(Length(FSocksPassword)) + FSocksPassword;
  3110. SendString(Buf);
  3111. Buf := RecvBufferStr(2, FSocksTimeout);
  3112. if Length(Buf) < 2 then
  3113. Exit;
  3114. if Buf[2] <> #0 then
  3115. Exit;
  3116. end;
  3117. else
  3118. //other authorisation is not supported!
  3119. Exit;
  3120. end;
  3121. FUsingSocks := True;
  3122. Result := True;
  3123. finally
  3124. FBypassFlag := False;
  3125. end;
  3126. end;
  3127. end;
  3128. function TSocksBlockSocket.SocksRequest(Cmd: Byte;
  3129. const IP, Port: string): Boolean;
  3130. var
  3131. buf: string;
  3132. begin
  3133. FBypassFlag := True;
  3134. try
  3135. if FSocksType <> ST_Socks5 then
  3136. Buf := #4 + Char(Cmd) + SocksCode(IP, Port)
  3137. else
  3138. Buf := #5 + Char(Cmd) + #0 + SocksCode(IP, Port);
  3139. SendString(Buf);
  3140. Result := FLastError = 0;
  3141. finally
  3142. FBypassFlag := False;
  3143. end;
  3144. end;
  3145. function TSocksBlockSocket.SocksResponse: Boolean;
  3146. var
  3147. Buf, s, m, z: string;
  3148. x: integer;
  3149. begin
  3150. Result := False;
  3151. FBypassFlag := True;
  3152. try
  3153. FSocksResponseIP := '';
  3154. FSocksResponsePort := '';
  3155. FSocksLastError := -1;
  3156. if FSocksType <> ST_Socks5 then
  3157. begin
  3158. Buf := RecvBufferStr(8, FSocksTimeout);
  3159. if FLastError <> 0 then
  3160. Exit;
  3161. if Buf[1] <> #0 then
  3162. Exit;
  3163. FSocksLastError := Ord(Buf[2]);
  3164. end
  3165. else
  3166. begin
  3167. Buf := RecvBufferStr(4, FSocksTimeout);
  3168. if FLastError <> 0 then
  3169. Exit;
  3170. if Buf[1] <> #5 then
  3171. Exit;
  3172. case Ord(Buf[4]) of
  3173. 1:
  3174. s := RecvBufferStr(4, FSocksTimeout);
  3175. 3:
  3176. begin
  3177. x := RecvByte(FSocksTimeout);
  3178. if FLastError <> 0 then
  3179. Exit;
  3180. s := Char(x) + RecvBufferStr(x, FSocksTimeout);
  3181. end;
  3182. 4:
  3183. s := RecvBufferStr(16, FSocksTimeout);
  3184. else
  3185. Exit;
  3186. end;
  3187. Buf := Buf + s + RecvBufferStr(2, FSocksTimeout);
  3188. if FLastError <> 0 then
  3189. Exit;
  3190. FSocksLastError := Ord(Buf[2]);
  3191. end;
  3192. //---
  3193. if ((FSocksLastError <> 0) and (FSocksLastError <> $5A{90})) then
  3194. begin
  3195. case FSocksLastError of // http://en.wikipedia.org/wiki/SOCKS
  3196. // v4
  3197. $5a: m := 'request granted';
  3198. $5b: m := 'request rejected or failed';
  3199. $5c: m := 'request failed because client is not running identd (or not reachable from the server)';
  3200. $5d: m := 'request failed because client''s identd could not confirm the user ID string in the request';
  3201. // v5'
  3202. $00: m := 'request grant`ed';
  3203. $01: m := 'general failure';
  3204. $02: m := 'connection not allowed by ruleset';
  3205. $03: m := 'network unreachable';
  3206. $04: m := 'host unreachable';
  3207. $05: m := 'connection refused by destination host';
  3208. $06: m := 'TTL expired';
  3209. $07: m := 'command not supported / protocol error';
  3210. $08: m := 'address type not supported';
  3211. else
  3212. m := '';
  3213. end;
  3214. z := SysUtils.Format('Error 0x%x', [FSocksLastError]);
  3215. if m<>'' then
  3216. z := z + ' ' + m;
  3217. Exit;
  3218. end;
  3219. SocksDecode(Buf);
  3220. Result := True;
  3221. finally
  3222. FBypassFlag := False;
  3223. end;
  3224. end;
  3225. function TSocksBlockSocket.SocksCode(IP: string; const Port: string): string;
  3226. var
  3227. ip6: TIp6Bytes;
  3228. n: integer;
  3229. begin
  3230. if FSocksType <> ST_Socks5 then
  3231. begin
  3232. Result := CodeInt(ResolvePort(Port));
  3233. if not FSocksResolver then
  3234. IP := ResolveName(IP);
  3235. if IsIP(IP) then
  3236. begin
  3237. Result := Result + IPToID(IP);
  3238. Result := Result + FSocksUsername + #0;
  3239. end
  3240. else
  3241. begin
  3242. Result := Result + IPToID('0.0.0.1');
  3243. Result := Result + FSocksUsername + #0;
  3244. Result := Result + IP + #0;
  3245. end;
  3246. end
  3247. else
  3248. begin
  3249. if not FSocksResolver then
  3250. IP := ResolveName(IP);
  3251. if IsIP(IP) then
  3252. Result := #1 + IPToID(IP)
  3253. else
  3254. if IsIP6(IP) then
  3255. begin
  3256. ip6 := StrToIP6(IP);
  3257. Result := #4;
  3258. for n := 0 to 15 do
  3259. Result := Result + Char(ip6[n]);
  3260. end
  3261. else
  3262. Result := #3 + Char(Length(IP)) + IP;
  3263. Result := Result + CodeInt(ResolvePort(Port));
  3264. end;
  3265. end;
  3266. function TSocksBlockSocket.SocksDecode(const Value: string): integer;
  3267. var
  3268. Atyp: Byte;
  3269. y, n: integer;
  3270. w: Word;
  3271. ip6: TIp6Bytes;
  3272. begin
  3273. FSocksResponsePort := '0';
  3274. Result := 0;
  3275. if FSocksType <> ST_Socks5 then
  3276. begin
  3277. if Length(Value) < 8 then
  3278. Exit;
  3279. Result := 3;
  3280. w := DecodeInt(Value, Result);
  3281. FSocksResponsePort := IntToStr(w);
  3282. FSocksResponseIP := Format('%d.%d.%d.%d',
  3283. [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  3284. Result := 9;
  3285. end
  3286. else
  3287. begin
  3288. if Length(Value) < 4 then
  3289. Exit;
  3290. Atyp := Ord(Value[4]);
  3291. Result := 5;
  3292. case Atyp of
  3293. 1:
  3294. begin
  3295. if Length(Value) < 10 then
  3296. Exit;
  3297. FSocksResponseIP := Format('%d.%d.%d.%d',
  3298. [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  3299. Result := 9;
  3300. end;
  3301. 3:
  3302. begin
  3303. y := Ord(Value[5]);
  3304. if Length(Value) < (5 + y + 2) then
  3305. Exit;
  3306. for n := 6 to 6 + y - 1 do
  3307. FSocksResponseIP := FSocksResponseIP + Value[n];
  3308. Result := 5 + y + 1;
  3309. end;
  3310. 4:
  3311. begin
  3312. if Length(Value) < 22 then
  3313. Exit;
  3314. for n := 0 to 15 do
  3315. ip6[n] := ord(Value[n + 5]);
  3316. FSocksResponseIP := IP6ToStr(ip6);
  3317. Result := 21;
  3318. end;
  3319. else
  3320. Exit;
  3321. end;
  3322. w := DecodeInt(Value, Result);
  3323. FSocksResponsePort := IntToStr(w);
  3324. Result := Result + 2;
  3325. end;
  3326. end;
  3327. {======================================================================}
  3328. procedure TDgramBlockSocket.Connect(const IP, Port: string);
  3329. begin
  3330. SetRemoteSin(IP, Port);
  3331. InternalCreateSocket(FRemoteSin);
  3332. if UseConnect then
  3333. begin
  3334. SockCheck(synsock.Connect(FSocket, FRemoteSin));
  3335. if FLastError = 0 then
  3336. GetSins;
  3337. end;
  3338. FBuffer := '';
  3339. DoStatus(HR_Connect, IP + ':' + Port);
  3340. end;
  3341. function TDgramBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
  3342. begin
  3343. Result := RecvBufferFrom(Buffer, Length);
  3344. end;
  3345. function TDgramBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  3346. begin
  3347. Result := SendBufferTo(Buffer, Length);
  3348. end;
  3349. {======================================================================}
  3350. destructor TUDPBlockSocket.Destroy;
  3351. begin
  3352. if Assigned(FSocksControlSock) then
  3353. FreeAndNil(FSocksControlSock);
  3354. inherited;
  3355. end;
  3356. procedure TUDPBlockSocket.EnableBroadcast(Value: Boolean);
  3357. var
  3358. d: TSynaOption;
  3359. begin
  3360. //d := TSynaOption.Create;
  3361. d.Option := SOT_Broadcast;
  3362. d.Enabled := Value;
  3363. DelayedOption(d);
  3364. end;
  3365. function TUDPBlockSocket.UdpAssociation: Boolean;
  3366. var
  3367. b: Boolean;
  3368. begin
  3369. Result := True;
  3370. FUsingSocks := False;
  3371. if FSocksIP <> '' then
  3372. begin
  3373. Result := False;
  3374. if not Assigned(FSocksControlSock) then
  3375. FSocksControlSock := TTCPBlockSocket.Create;
  3376. FSocksControlSock.CloseSocket;
  3377. FSocksControlSock.CreateSocketByName(FSocksIP);
  3378. FSocksControlSock.Connect(FSocksIP, FSocksPort);
  3379. if FSocksControlSock.LastError <> 0 then
  3380. Exit;
  3381. // if not assigned local port, assign it!
  3382. if not FBinded then
  3383. Bind(cAnyHost, cAnyPort);
  3384. //open control TCP connection to SOCKS
  3385. FSocksControlSock.FSocksUsername := FSocksUsername;
  3386. FSocksControlSock.FSocksPassword := FSocksPassword;
  3387. b := FSocksControlSock.SocksOpen;
  3388. if b then
  3389. b := FSocksControlSock.SocksRequest(3, GetLocalSinIP, IntToStr(GetLocalSinPort));
  3390. if b then
  3391. b := FSocksControlSock.SocksResponse;
  3392. if not b and (FLastError = 0) then
  3393. FLastError := WSANO_RECOVERY;
  3394. FUsingSocks :=FSocksControlSock.UsingSocks;
  3395. FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
  3396. FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
  3397. Result := b and (FLastError = 0);
  3398. end;
  3399. end;
  3400. function TUDPBlockSocket.SendBufferTo(const Buffer: TMemory; Length: Integer): Integer;
  3401. var
  3402. SIp: string;
  3403. SPort: integer;
  3404. Buf: string;
  3405. begin
  3406. Result := 0;
  3407. FUsingSocks := False;
  3408. if (FSocksIP <> '') and (not UdpAssociation) then
  3409. FLastError := WSANO_RECOVERY
  3410. else
  3411. begin
  3412. if FUsingSocks then
  3413. begin
  3414. {$IFNDEF CIL}
  3415. Sip := GetRemoteSinIp;
  3416. SPort := GetRemoteSinPort;
  3417. SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
  3418. SetLength(Buf,Length);
  3419. Move(Buffer^, Pointer(Buf)^, Length);
  3420. Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
  3421. Result := inherited SendBufferTo(Pointer(Buf), buf.Length);
  3422. SetRemoteSin(Sip, IntToStr(SPort));
  3423. {$ENDIF}
  3424. end
  3425. else
  3426. Result := inherited SendBufferTo(Buffer, Length);
  3427. end;
  3428. end;
  3429. function TUDPBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
  3430. var
  3431. Buf: string;
  3432. x: integer;
  3433. begin
  3434. Result := inherited RecvBufferFrom(Buffer, Length);
  3435. if FUsingSocks then
  3436. begin
  3437. {$IFNDEF CIL}
  3438. SetLength(Buf, Result);
  3439. Move(Buffer^, Pointer(Buf)^, Result);
  3440. x := SocksDecode(Buf);
  3441. Result := Result - x + 1;
  3442. Buf := Copy(Buf, x, Result);
  3443. Move(Pointer(Buf)^, Buffer^, Result);
  3444. SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
  3445. {$ENDIF}
  3446. end;
  3447. end;
  3448. {$IFNDEF CIL}
  3449. procedure TUDPBlockSocket.AddMulticast(const MCastIP: string);
  3450. var
  3451. Multicast: TIP_mreq;
  3452. Multicast6: TIPv6_mreq;
  3453. n: integer;
  3454. ip6: Tip6bytes;
  3455. begin
  3456. if FIP6Used then
  3457. begin
  3458. ip6 := StrToIp6(MCastIP);
  3459. for n := 0 to 15 do
  3460. Multicast6.ipv6mr_multiaddr.{$IFDEF POSIX}s6_addr{$ELSE}u6_addr8{$ENDIF}[n] := Ip6[n];
  3461. Multicast6.ipv6mr_interface := 0;
  3462. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  3463. Pointer(@Multicast6), SizeOf(Multicast6)));
  3464. end
  3465. else
  3466. begin
  3467. Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
  3468. // Multicast.imr_interface.S_addr := INADDR_ANY;
  3469. Multicast.imr_interface.S_addr := FLocalSin.sin_addr.S_addr;
  3470. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  3471. Pointer(@Multicast), SizeOf(Multicast)));
  3472. end;
  3473. ExceptCheck;
  3474. end;
  3475. procedure TUDPBlockSocket.DropMulticast(const MCastIP: string);
  3476. var
  3477. Multicast: TIP_mreq;
  3478. Multicast6: TIPv6_mreq;
  3479. n: integer;
  3480. ip6: Tip6bytes;
  3481. begin
  3482. if FIP6Used then
  3483. begin
  3484. ip6 := StrToIp6(MCastIP);
  3485. for n := 0 to 15 do
  3486. Multicast6.ipv6mr_multiaddr.{$IFDEF POSIX}s6_addr{$ELSE}u6_addr8{$ENDIF}[n] := Ip6[n];
  3487. Multicast6.ipv6mr_interface := 0;
  3488. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  3489. Pointer(@Multicast6), SizeOf(Multicast6)));
  3490. end
  3491. else
  3492. begin
  3493. Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
  3494. // Multicast.imr_interface.S_addr := INADDR_ANY;
  3495. Multicast.imr_interface.S_addr := FLocalSin.sin_addr.S_addr;
  3496. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
  3497. Pointer(@Multicast), SizeOf(Multicast)));
  3498. end;
  3499. ExceptCheck;
  3500. end;
  3501. {$ENDIF}
  3502. procedure TUDPBlockSocket.SetMulticastTTL(TTL: integer);
  3503. var
  3504. d: TSynaOption;
  3505. begin
  3506. //d := TSynaOption.Create;
  3507. d.Option := SOT_MulticastTTL;
  3508. d.Value := TTL;
  3509. DelayedOption(d);
  3510. end;
  3511. function TUDPBlockSocket.GetMulticastTTL:integer;
  3512. var
  3513. l: Integer;
  3514. begin
  3515. {$IFNDEF CIL}
  3516. l := SizeOf(Result);
  3517. if FIP6Used then
  3518. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, @Result, l))
  3519. else
  3520. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_MULTICAST_TTL, @Result, l));
  3521. ExceptCheck;
  3522. {$ENDIF}
  3523. end;
  3524. procedure TUDPBlockSocket.EnableMulticastLoop(Value: Boolean);
  3525. var
  3526. d: TSynaOption;
  3527. begin
  3528. //d := TSynaOption.Create;
  3529. d.Option := SOT_MulticastLoop;
  3530. d.Enabled := Value;
  3531. DelayedOption(d);
  3532. end;
  3533. function TUDPBlockSocket.GetSocketType: integer;
  3534. begin
  3535. Result := integer(SOCK_DGRAM);
  3536. end;
  3537. function TUDPBlockSocket.GetSocketProtocol: integer;
  3538. begin
  3539. Result := integer(IPPROTO_UDP);
  3540. end;
  3541. {======================================================================}
  3542. constructor TTCPBlockSocket.CreateWithSSL(SSLPlugin: TSSLClass);
  3543. begin
  3544. inherited Create;
  3545. FSSL := SSLPlugin.Create(self);
  3546. FHTTPTunnelIP := '';
  3547. FHTTPTunnelPort := '';
  3548. FHTTPTunnel := False;
  3549. FHTTPTunnelRemoteIP := '';
  3550. FHTTPTunnelRemotePort := '';
  3551. FHTTPTunnelUser := '';
  3552. FHTTPTunnelPass := '';
  3553. FHTTPTunnelTimeout := 30000;
  3554. end;
  3555. constructor TTCPBlockSocket.Create;
  3556. begin
  3557. CreateWithSSL(SSLImplementation);
  3558. end;
  3559. destructor TTCPBlockSocket.Destroy;
  3560. begin
  3561. inherited Destroy;
  3562. FreeAndNil(FSSL);
  3563. end;
  3564. function TTCPBlockSocket.GetErrorDescEx: string;
  3565. begin
  3566. Result := inherited GetErrorDescEx;
  3567. if (FLastError = WSASYSNOTREADY) and (self.SSL.LastError <> 0) then
  3568. begin
  3569. Result := self.SSL.LastErrorDesc;
  3570. end;
  3571. end;
  3572. const
  3573. SHUT_RDWR = 2;
  3574. procedure TTCPBlockSocket.CloseSocket;
  3575. begin
  3576. if FSSL.SSLEnabled then
  3577. FSSL.Shutdown;
  3578. if (FSocket <> INVALID_SOCKET) and (FLastError = 0) then
  3579. begin
  3580. SockCheck(Synsock.Shutdown(FSocket, SHUT_RDWR));
  3581. //ExceptCheck;
  3582. Purge;
  3583. SetLinger(True, 0);
  3584. end;
  3585. inherited CloseSocket;
  3586. end;
  3587. procedure TTCPBlockSocket.DoAfterConnect;
  3588. begin
  3589. if Assigned(OnAfterConnect) then
  3590. begin
  3591. OnAfterConnect(Self);
  3592. end;
  3593. end;
  3594. function TTCPBlockSocket.WaitingData: Integer;
  3595. begin
  3596. Result := 0;
  3597. if FSSL.SSLEnabled and (FSocket <> INVALID_SOCKET) then
  3598. Result := FSSL.WaitingData;
  3599. if Result = 0 then
  3600. Result := inherited WaitingData;
  3601. end;
  3602. procedure TTCPBlockSocket.Listen;
  3603. var
  3604. b: Boolean;
  3605. Sip,SPort: string;
  3606. begin
  3607. if FSocksIP = '' then
  3608. begin
  3609. inherited Listen;
  3610. end
  3611. else
  3612. begin
  3613. Sip := GetLocalSinIP;
  3614. if Sip = cAnyHost then
  3615. Sip := LocalName;
  3616. SPort := IntToStr(GetLocalSinPort);
  3617. inherited Connect(FSocksIP, FSocksPort);
  3618. b := SocksOpen;
  3619. if b then
  3620. b := SocksRequest(2, Sip, SPort);
  3621. if b then
  3622. b := SocksResponse;
  3623. if not b and (FLastError = 0) then
  3624. FLastError := WSANO_RECOVERY;
  3625. FSocksLocalIP := FSocksResponseIP;
  3626. if FSocksLocalIP = cAnyHost then
  3627. FSocksLocalIP := FSocksIP;
  3628. FSocksLocalPort := FSocksResponsePort;
  3629. FSocksRemoteIP := '';
  3630. FSocksRemotePort := '';
  3631. ExceptCheck;
  3632. DoStatus(HR_Listen, '');
  3633. end;
  3634. end;
  3635. function TTCPBlockSocket.Accept: TSocket;
  3636. begin
  3637. if FUsingSocks then
  3638. begin
  3639. if not SocksResponse and (FLastError = 0) then
  3640. FLastError := WSANO_RECOVERY;
  3641. FSocksRemoteIP := FSocksResponseIP;
  3642. FSocksRemotePort := FSocksResponsePort;
  3643. Result := FSocket;
  3644. ExceptCheck;
  3645. DoStatus(HR_Accept, '');
  3646. end
  3647. else
  3648. begin
  3649. result := inherited Accept;
  3650. end;
  3651. end;
  3652. procedure TTCPBlockSocket.Connect(const IP, Port: string);
  3653. begin
  3654. FDisconnected := False;
  3655. if FSocksIP <> '' then
  3656. SocksDoConnect(IP, Port)
  3657. else
  3658. if FHTTPTunnelIP <> '' then
  3659. HTTPTunnelDoConnect(IP, Port)
  3660. else
  3661. inherited Connect(IP, Port);
  3662. if FLasterror = 0 then
  3663. DoAfterConnect;
  3664. end;
  3665. function TTCPBlockSocket.Connected: boolean;
  3666. begin
  3667. Result := (FSocket <> INVALID_SOCKET) and not FDisconnected;
  3668. {$IFNDEF UNIX}
  3669. if Result then
  3670. begin
  3671. CanRead(0);
  3672. Result := not FDisconnected;
  3673. end;
  3674. {$ENDIF}
  3675. end;
  3676. procedure TTCPBlockSocket.SocksDoConnect(const IP, Port: string);
  3677. var
  3678. b: Boolean;
  3679. begin
  3680. inherited Connect(FSocksIP, FSocksPort);
  3681. if FLastError = 0 then
  3682. begin
  3683. b := SocksOpen;
  3684. if b then
  3685. b := SocksRequest(1, IP, Port);
  3686. if b then
  3687. b := SocksResponse;
  3688. if not b and (FLastError = 0) then
  3689. FLastError := WSASYSNOTREADY;
  3690. FSocksLocalIP := FSocksResponseIP;
  3691. FSocksLocalPort := FSocksResponsePort;
  3692. FSocksRemoteIP := IP;
  3693. FSocksRemotePort := Port;
  3694. end;
  3695. ExceptCheck;
  3696. DoStatus(HR_Connect, IP + ':' + Port);
  3697. end;
  3698. procedure TTCPBlockSocket.HTTPTunnelDoConnect(IP, Port: string);
  3699. //bugfixed by Mike Green ([email protected])
  3700. var
  3701. s: string;
  3702. begin
  3703. Port := IntToStr(ResolvePort(Port));
  3704. inherited Connect(FHTTPTunnelIP, FHTTPTunnelPort);
  3705. if FLastError <> 0 then
  3706. Exit;
  3707. FHTTPTunnel := False;
  3708. if IsIP6(IP) then
  3709. IP := '[' + IP + ']';
  3710. SendString('CONNECT ' + IP + ':' + Port + ' HTTP/1.0' + CRLF);
  3711. if FHTTPTunnelUser <> '' then
  3712. Sendstring('Proxy-Authorization: Basic ' +
  3713. EncodeBase64(FHTTPTunnelUser + ':' + FHTTPTunnelPass) + CRLF);
  3714. SendString(CRLF);
  3715. repeat
  3716. s := RecvTerminated(FHTTPTunnelTimeout, #$0a);
  3717. if FLastError <> 0 then
  3718. Break;
  3719. if (Pos('HTTP/', s) = 1) and (Length(s) > 11) then
  3720. FHTTPTunnel := s[10] = '2';
  3721. until (s = '') or (s = #$0d);
  3722. if (FLasterror = 0) and not FHTTPTunnel then
  3723. FLastError := WSAECONNREFUSED;
  3724. FHTTPTunnelRemoteIP := IP;
  3725. FHTTPTunnelRemotePort := Port;
  3726. ExceptCheck;
  3727. end;
  3728. procedure TTCPBlockSocket.SSLDoConnect;
  3729. begin
  3730. ResetLastError;
  3731. if not FSSL.Connect then
  3732. FLastError := WSASYSNOTREADY;
  3733. ExceptCheck;
  3734. end;
  3735. procedure TTCPBlockSocket.SSLDoShutdown;
  3736. begin
  3737. ResetLastError;
  3738. FSSL.BiShutdown;
  3739. end;
  3740. function TTCPBlockSocket.GetLocalSinIP: string;
  3741. begin
  3742. if FUsingSocks then
  3743. Result := FSocksLocalIP
  3744. else
  3745. Result := inherited GetLocalSinIP;
  3746. end;
  3747. function TTCPBlockSocket.GetRemoteSinIP: string;
  3748. begin
  3749. if FUsingSocks then
  3750. Result := FSocksRemoteIP
  3751. else
  3752. if FHTTPTunnel then
  3753. Result := FHTTPTunnelRemoteIP
  3754. else
  3755. Result := inherited GetRemoteSinIP;
  3756. end;
  3757. function TTCPBlockSocket.GetLocalSinPort: Integer;
  3758. begin
  3759. if FUsingSocks then
  3760. Result := StrToIntDef(FSocksLocalPort, 0)
  3761. else
  3762. Result := inherited GetLocalSinPort;
  3763. end;
  3764. function TTCPBlockSocket.GetRemoteSinPort: Integer;
  3765. begin
  3766. if FUsingSocks then
  3767. Result := ResolvePort(FSocksRemotePort)
  3768. else
  3769. if FHTTPTunnel then
  3770. Result := StrToIntDef(FHTTPTunnelRemotePort, 0)
  3771. else
  3772. Result := inherited GetRemoteSinPort;
  3773. end;
  3774. function TTCPBlockSocket.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  3775. begin
  3776. if FSSL.SSLEnabled then
  3777. begin
  3778. Result := 0;
  3779. if TestStopFlag then
  3780. Exit;
  3781. ResetLastError;
  3782. LimitBandwidth(Len, FMaxRecvBandwidth, FNextRecv);
  3783. Result := FSSL.RecvBuffer(Buffer, Len);
  3784. if FSSL.LastError <> 0 then
  3785. FLastError := WSASYSNOTREADY;
  3786. ExceptCheck;
  3787. Inc(FRecvCounter, Result);
  3788. DoStatus(HR_ReadCount, IntToStr(Result));
  3789. DoMonitor(False, Buffer, Result);
  3790. DoReadFilter(Buffer, Result);
  3791. end
  3792. else
  3793. Result := inherited RecvBuffer(Buffer, Len);
  3794. end;
  3795. function TTCPBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  3796. var
  3797. x, y: integer;
  3798. l, r: integer;
  3799. {$IFNDEF CIL}
  3800. p: Pointer;
  3801. {$ENDIF}
  3802. begin
  3803. if FSSL.SSLEnabled then
  3804. begin
  3805. Result := 0;
  3806. if TestStopFlag then
  3807. Exit;
  3808. ResetLastError;
  3809. DoMonitor(True, Buffer, Length);
  3810. {$IFDEF CIL}
  3811. Result := FSSL.SendBuffer(Buffer, Length);
  3812. if FSSL.LastError <> 0 then
  3813. FLastError := WSASYSNOTREADY;
  3814. Inc(FSendCounter, Result);
  3815. DoStatus(HR_WriteCount, IntToStr(Result));
  3816. {$ELSE}
  3817. l := Length;
  3818. x := 0;
  3819. while x < l do
  3820. begin
  3821. y := l - x;
  3822. if y > FSendMaxChunk then
  3823. y := FSendMaxChunk;
  3824. if y > 0 then
  3825. begin
  3826. LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
  3827. p := IncPoint(Buffer, x);
  3828. r := FSSL.SendBuffer(p, y);
  3829. if FSSL.LastError <> 0 then
  3830. FLastError := WSASYSNOTREADY;
  3831. if Flasterror <> 0 then
  3832. Break;
  3833. Inc(x, r);
  3834. Inc(Result, r);
  3835. Inc(FSendCounter, r);
  3836. DoStatus(HR_WriteCount, IntToStr(r));
  3837. end
  3838. else
  3839. break;
  3840. end;
  3841. {$ENDIF}
  3842. ExceptCheck;
  3843. end
  3844. else
  3845. Result := inherited SendBuffer(Buffer, Length);
  3846. end;
  3847. function TTCPBlockSocket.SSLAcceptConnection: Boolean;
  3848. begin
  3849. ResetLastError;
  3850. if not FSSL.Accept then
  3851. FLastError := WSASYSNOTREADY;
  3852. ExceptCheck;
  3853. Result := FLastError = 0;
  3854. end;
  3855. function TTCPBlockSocket.GetSocketType: integer;
  3856. begin
  3857. Result := integer(SOCK_STREAM);
  3858. end;
  3859. function TTCPBlockSocket.GetSocketProtocol: integer;
  3860. begin
  3861. Result := integer(IPPROTO_TCP);
  3862. end;
  3863. {======================================================================}
  3864. function TICMPBlockSocket.GetSocketType: integer;
  3865. begin
  3866. Result := integer(SOCK_RAW);
  3867. end;
  3868. function TICMPBlockSocket.GetSocketProtocol: integer;
  3869. begin
  3870. if FIP6Used then
  3871. Result := integer(IPPROTO_ICMPV6)
  3872. else
  3873. Result := integer(IPPROTO_ICMP);
  3874. end;
  3875. {======================================================================}
  3876. function TRAWBlockSocket.GetSocketType: integer;
  3877. begin
  3878. Result := integer(SOCK_RAW);
  3879. end;
  3880. function TRAWBlockSocket.GetSocketProtocol: integer;
  3881. begin
  3882. Result := integer(IPPROTO_RAW);
  3883. end;
  3884. {======================================================================}
  3885. function TPGMmessageBlockSocket.GetSocketType: integer;
  3886. begin
  3887. Result := integer(SOCK_RDM);
  3888. end;
  3889. function TPGMmessageBlockSocket.GetSocketProtocol: integer;
  3890. begin
  3891. Result := integer(IPPROTO_RM);
  3892. end;
  3893. {======================================================================}
  3894. function TPGMstreamBlockSocket.GetSocketType: integer;
  3895. begin
  3896. Result := integer(SOCK_STREAM);
  3897. end;
  3898. function TPGMstreamBlockSocket.GetSocketProtocol: integer;
  3899. begin
  3900. Result := integer(IPPROTO_RM);
  3901. end;
  3902. {======================================================================}
  3903. constructor TSynaClient.Create;
  3904. begin
  3905. inherited Create;
  3906. FIPInterface := cAnyHost;
  3907. FTargetHost := cLocalhost;
  3908. FTargetPort := cAnyPort;
  3909. FTimeout := 5000;
  3910. FUsername := '';
  3911. FPassword := '';
  3912. end;
  3913. {======================================================================}
  3914. constructor TCustomSSL.Create(const Value: TTCPBlockSocket);
  3915. begin
  3916. inherited Create;
  3917. FSocket := Value;
  3918. FSSLEnabled := False;
  3919. FUsername := '';
  3920. FPassword := '';
  3921. FLastError := 0;
  3922. FLastErrorDesc := '';
  3923. FVerifyCert := False;
  3924. FSSLType := LT_all;
  3925. FKeyPassword := '';
  3926. FCiphers := '';
  3927. FCertificateFile := '';
  3928. FPrivateKeyFile := '';
  3929. FCertCAFile := '';
  3930. FCertCA := '';
  3931. FTrustCertificate := '';
  3932. FTrustCertificateFile := '';
  3933. FCertificate := '';
  3934. FPrivateKey := '';
  3935. FPFX := '';
  3936. FPFXfile := '';
  3937. FSSHChannelType := '';
  3938. FSSHChannelArg1 := '';
  3939. FSSHChannelArg2 := '';
  3940. FCertComplianceLevel := -1; //default
  3941. FSNIHost := '';
  3942. end;
  3943. procedure TCustomSSL.Assign(const Value: TCustomSSL);
  3944. begin
  3945. FUsername := Value.Username;
  3946. FPassword := Value.Password;
  3947. FVerifyCert := Value.VerifyCert;
  3948. FSSLType := Value.SSLType;
  3949. FKeyPassword := Value.KeyPassword;
  3950. FCiphers := Value.Ciphers;
  3951. FCertificateFile := Value.CertificateFile;
  3952. FPrivateKeyFile := Value.PrivateKeyFile;
  3953. FCertCAFile := Value.CertCAFile;
  3954. FCertCA := Value.CertCA;
  3955. FTrustCertificate := Value.TrustCertificate;
  3956. FTrustCertificateFile := Value.TrustCertificateFile;
  3957. FCertificate := Value.Certificate;
  3958. FPrivateKey := Value.PrivateKey;
  3959. FPFX := Value.PFX;
  3960. FPFXfile := Value.PFXfile;
  3961. FCertComplianceLevel := Value.CertComplianceLevel;
  3962. FSNIHost := Value.FSNIHost;
  3963. end;
  3964. procedure TCustomSSL.ReturnError;
  3965. begin
  3966. FLastError := -1;
  3967. FLastErrorDesc := 'SSL/TLS support is not compiled!';
  3968. end;
  3969. function TCustomSSL.LibVersion: string;
  3970. begin
  3971. Result := '';
  3972. end;
  3973. function TCustomSSL.LibName: string;
  3974. begin
  3975. Result := '';
  3976. end;
  3977. function TCustomSSL.CreateSelfSignedCert(Host: string): Boolean;
  3978. begin
  3979. Result := False;
  3980. end;
  3981. function TCustomSSL.Connect: boolean;
  3982. begin
  3983. ReturnError;
  3984. Result := False;
  3985. end;
  3986. function TCustomSSL.Accept: boolean;
  3987. begin
  3988. ReturnError;
  3989. Result := False;
  3990. end;
  3991. function TCustomSSL.Shutdown: boolean;
  3992. begin
  3993. ReturnError;
  3994. Result := False;
  3995. end;
  3996. function TCustomSSL.BiShutdown: boolean;
  3997. begin
  3998. ReturnError;
  3999. Result := False;
  4000. end;
  4001. function TCustomSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
  4002. begin
  4003. ReturnError;
  4004. Result := integer(SOCKET_ERROR);
  4005. end;
  4006. procedure TCustomSSL.SetCertCAFile(const Value: string);
  4007. begin
  4008. FCertCAFile := Value;
  4009. end;
  4010. function TCustomSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  4011. begin
  4012. ReturnError;
  4013. Result := integer(SOCKET_ERROR);
  4014. end;
  4015. function TCustomSSL.WaitingData: Integer;
  4016. begin
  4017. ReturnError;
  4018. Result := 0;
  4019. end;
  4020. function TCustomSSL.GetSSLVersion: string;
  4021. begin
  4022. Result := '';
  4023. end;
  4024. function TCustomSSL.GetPeerSubject: string;
  4025. begin
  4026. Result := '';
  4027. end;
  4028. function TCustomSSL.GetPeerSerialNo: integer;
  4029. begin
  4030. Result := -1;
  4031. end;
  4032. function TCustomSSL.GetPeerName: string;
  4033. begin
  4034. Result := '';
  4035. end;
  4036. function TCustomSSL.GetPeerNameHash: cardinal;
  4037. begin
  4038. Result := 0;
  4039. end;
  4040. function TCustomSSL.GetPeerIssuer: string;
  4041. begin
  4042. Result := '';
  4043. end;
  4044. function TCustomSSL.GetPeerFingerprint: string;
  4045. begin
  4046. Result := '';
  4047. end;
  4048. function TCustomSSL.GetCertInfo: string;
  4049. begin
  4050. Result := '';
  4051. end;
  4052. function TCustomSSL.GetCipherName: string;
  4053. begin
  4054. Result := '';
  4055. end;
  4056. function TCustomSSL.GetCipherBits: integer;
  4057. begin
  4058. Result := 0;
  4059. end;
  4060. function TCustomSSL.GetCipherAlgBits: integer;
  4061. begin
  4062. Result := 0;
  4063. end;
  4064. function TCustomSSL.GetVerifyCert: integer;
  4065. begin
  4066. Result := 1;
  4067. end;
  4068. function TCustomSSL.DoVerifyCert:boolean;
  4069. begin
  4070. if assigned(OnVerifyCert) then
  4071. begin
  4072. result:=OnVerifyCert(Self);
  4073. end
  4074. else
  4075. result:=true;
  4076. end;
  4077. {======================================================================}
  4078. function TSSLNone.LibVersion: string;
  4079. begin
  4080. Result := 'Without SSL support';
  4081. end;
  4082. function TSSLNone.LibName: string;
  4083. begin
  4084. Result := 'ssl_none';
  4085. end;
  4086. {======================================================================}
  4087. initialization
  4088. begin
  4089. {$IFDEF ONCEWINSOCK}
  4090. if not InitSocketInterface(DLLStackName) then
  4091. begin
  4092. e := ESynapseError.Create('Error loading Socket interface (' + DLLStackName + ')!');
  4093. e.ErrorCode := 0;
  4094. e.ErrorMessage := 'Error loading Socket interface (' + DLLStackName + ')!';
  4095. raise e;
  4096. end;
  4097. synsock.WSAStartup(WinsockLevel, WsaDataOnce);
  4098. {$ENDIF}
  4099. end;
  4100. finalization
  4101. begin
  4102. {$IFDEF ONCEWINSOCK}
  4103. synsock.WSACleanup;
  4104. DestroySocketInterface;
  4105. {$ENDIF}
  4106. end;
  4107. end.