blcksock.pas 135 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604
  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: FixedUInt;
  289. FMaxRecvBandwidth: Integer;
  290. FNextRecv: FixedUInt;
  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: FixedUInt);
  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: FixedUInt;
  1231. DestIp: FixedUInt;
  1232. Options: FixedUInt;
  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. FDelayedOptions := FDelayedOptions + [Value];
  1559. end
  1560. else
  1561. SetDelayedOption(Value);
  1562. end;
  1563. procedure TBlockSocket.ProcessDelayedOptions;
  1564. var
  1565. n: integer;
  1566. d: TSynaOption;
  1567. begin
  1568. for n := 0 to High(FDelayedOptions) do
  1569. begin
  1570. d := TSynaOption(FDelayedOptions[n]);
  1571. SetDelayedOption(d);
  1572. end;
  1573. Finalize(FDelayedOptions);
  1574. end;
  1575. procedure TBlockSocket.SetSin(var Sin: TVarSin; const IP, Port: string);
  1576. var
  1577. f: TSocketFamily;
  1578. begin
  1579. DoStatus(HR_ResolvingBegin, IP + ':' + Port);
  1580. ResetLastError;
  1581. //if socket exists, then use their type, else use users selection
  1582. f := SF_Any;
  1583. if (FSocket = INVALID_SOCKET) and (FFamily = SF_any) then
  1584. begin
  1585. if IsIP(IP) then
  1586. f := SF_IP4
  1587. else
  1588. if IsIP6(IP) then
  1589. f := SF_IP6;
  1590. end
  1591. else
  1592. f := FFamily;
  1593. FLastError := synsock.SetVarSin(sin, ip, port, FamilyToAF(f),
  1594. GetSocketprotocol, GetSocketType, FPreferIP4);
  1595. DoStatus(HR_ResolvingEnd, GetSinIP(sin) + ':' + IntTostr(GetSinPort(sin)));
  1596. end;
  1597. function TBlockSocket.GetSendTimeout: Integer;
  1598. var
  1599. l: integer;
  1600. begin
  1601. l:=SizeOf(Integer);
  1602. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDTIMEO, @Result, l));
  1603. ExceptCheck;
  1604. end;
  1605. function TBlockSocket.GetSinIP(Sin: TVarSin): string;
  1606. begin
  1607. Result := synsock.GetSinIP(sin);
  1608. end;
  1609. function TBlockSocket.GetSinPort(Sin: TVarSin): Integer;
  1610. begin
  1611. Result := synsock.GetSinPort(sin);
  1612. end;
  1613. procedure TBlockSocket.CreateSocket;
  1614. var
  1615. sin: TVarSin;
  1616. begin
  1617. //dummy for SF_Any Family mode
  1618. ResetLastError;
  1619. if (FFamily <> SF_Any) and (FSocket = INVALID_SOCKET) then
  1620. begin
  1621. {$IFDEF CIL}
  1622. if FFamily = SF_IP6 then
  1623. sin := TVarSin.Create(IPAddress.Parse('::0'), 0)
  1624. else
  1625. sin := TVarSin.Create(IPAddress.Parse('0.0.0.0'), 0);
  1626. {$ELSE}
  1627. FillChar(Sin, Sizeof(Sin), 0);
  1628. if FFamily = SF_IP6 then
  1629. sin.sin_family := AF_INET6
  1630. else
  1631. sin.sin_family := AF_INET;
  1632. {$ENDIF}
  1633. InternalCreateSocket(Sin);
  1634. end;
  1635. end;
  1636. procedure TBlockSocket.CreateSocketByName(const Value: string);
  1637. var
  1638. sin: TVarSin;
  1639. begin
  1640. ResetLastError;
  1641. if FSocket = INVALID_SOCKET then
  1642. begin
  1643. SetSin(sin, value, '0');
  1644. if FLastError = 0 then
  1645. InternalCreateSocket(Sin);
  1646. end;
  1647. end;
  1648. procedure TBlockSocket.InternalCreateSocket(Sin: TVarSin);
  1649. begin
  1650. FStopFlag := False;
  1651. FRecvCounter := 0;
  1652. FSendCounter := 0;
  1653. ResetLastError;
  1654. if FSocket = INVALID_SOCKET then
  1655. begin
  1656. FBuffer := '';
  1657. FBinded := False;
  1658. FIP6Used := Sin.AddressFamily = AF_INET6;
  1659. FSocket := synsock.Socket(integer(Sin.AddressFamily), GetSocketType, GetSocketProtocol);
  1660. if FSocket = INVALID_SOCKET then
  1661. FLastError := synsock.WSAGetLastError;
  1662. {$IFNDEF CIL}
  1663. FD_ZERO(FFDSet);
  1664. FD_SET(FSocket, FFDSet);
  1665. {$ENDIF}
  1666. ExceptCheck;
  1667. if FIP6used then
  1668. DoStatus(HR_SocketCreate, 'IPv6')
  1669. else
  1670. DoStatus(HR_SocketCreate, 'IPv4');
  1671. ProcessDelayedOptions;
  1672. DoCreateSocket;
  1673. end;
  1674. end;
  1675. procedure TBlockSocket.CloseSocket;
  1676. begin
  1677. AbortSocket;
  1678. end;
  1679. procedure TBlockSocket.AbortSocket;
  1680. //var
  1681. // n: integer;
  1682. // p: TSynaOption;
  1683. begin
  1684. if FSocket <> INVALID_SOCKET then
  1685. synsock.CloseSocket(FSocket);
  1686. FSocket := INVALID_SOCKET;
  1687. {for n := FDelayedOptions.Count - 1 downto 0 do
  1688. begin
  1689. p := TSynaOption(FDelayedOptions[n]);
  1690. FreeAndNil(p);
  1691. end;
  1692. FDelayedOptions.Clear;}
  1693. Finalize(FDelayedOptions);
  1694. FFamily := FFamilySave;
  1695. DoStatus(HR_SocketClose, '');
  1696. FDisconnected := False;
  1697. end;
  1698. procedure TBlockSocket.Bind(const IP, Port: string);
  1699. var
  1700. Sin: TVarSin;
  1701. begin
  1702. ResetLastError;
  1703. if (FSocket <> INVALID_SOCKET)
  1704. or not((FFamily = SF_ANY) and (IP = cAnyHost) and (Port = cAnyPort)) then
  1705. begin
  1706. SetSin(Sin, IP, Port);
  1707. if FLastError = 0 then
  1708. begin
  1709. if FSocket = INVALID_SOCKET then
  1710. InternalCreateSocket(Sin);
  1711. SockCheck(synsock.Bind(FSocket, Sin));
  1712. GetSinLocal;
  1713. FBuffer := '';
  1714. FBinded := True;
  1715. end;
  1716. ExceptCheck;
  1717. DoStatus(HR_Bind, IP + ':' + Port);
  1718. end;
  1719. end;
  1720. procedure TBlockSocket.Connect(const IP, Port: string);
  1721. var
  1722. Sin: TVarSin;
  1723. b: boolean;
  1724. {$IFDEF MSWINDOWS}
  1725. lError: Integer;
  1726. {$ENDIF}
  1727. begin
  1728. SetSin(Sin, IP, Port);
  1729. if FLastError = 0 then
  1730. begin
  1731. if FSocket = INVALID_SOCKET then
  1732. InternalCreateSocket(Sin);
  1733. if FConnectionTimeout > 0 then
  1734. begin
  1735. // connect in non-blocking mode
  1736. b := NonBlockMode;
  1737. NonBlockMode := true;
  1738. SockCheck(synsock.Connect(FSocket, Sin));
  1739. if (FLastError = WSAEINPROGRESS) OR (FLastError = WSAEWOULDBLOCK) then
  1740. if not CanWrite(FConnectionTimeout) then
  1741. FLastError := WSAETIMEDOUT;
  1742. {$IFDEF MSWINDOWS}
  1743. lError := FLastError;
  1744. {$ENDIF}
  1745. NonBlockMode := b;
  1746. {$IFDEF MSWINDOWS}
  1747. FLastError := lError;
  1748. {$ENDIF}
  1749. end
  1750. else
  1751. SockCheck(synsock.Connect(FSocket, Sin));
  1752. if FLastError = 0 then
  1753. GetSins;
  1754. FBuffer := '';
  1755. FLastCR := False;
  1756. FLastLF := False;
  1757. end;
  1758. ExceptCheck;
  1759. DoStatus(HR_Connect, IP + ':' + Port);
  1760. end;
  1761. procedure TBlockSocket.Listen;
  1762. begin
  1763. SockCheck(synsock.Listen(FSocket, SOMAXCONN));
  1764. GetSins;
  1765. ExceptCheck;
  1766. DoStatus(HR_Listen, '');
  1767. end;
  1768. function TBlockSocket.Accept: TSocket;
  1769. begin
  1770. Result := synsock.Accept(FSocket, FRemoteSin);
  1771. /// SockCheck(Result);
  1772. ExceptCheck;
  1773. DoStatus(HR_Accept, '');
  1774. end;
  1775. procedure TBlockSocket.GetSinLocal;
  1776. begin
  1777. synsock.GetSockName(FSocket, FLocalSin);
  1778. end;
  1779. procedure TBlockSocket.GetSinRemote;
  1780. begin
  1781. synsock.GetPeerName(FSocket, FRemoteSin);
  1782. end;
  1783. procedure TBlockSocket.GetSins;
  1784. begin
  1785. GetSinLocal;
  1786. GetSinRemote;
  1787. end;
  1788. procedure TBlockSocket.SetBandwidth(Value: Integer);
  1789. begin
  1790. MaxSendBandwidth := Value;
  1791. MaxRecvBandwidth := Value;
  1792. end;
  1793. procedure TBlockSocket.LimitBandwidth(Length: Integer; MaxB: integer; var Next: FixedUInt);
  1794. var
  1795. x: FixedUInt;
  1796. y: FixedUInt;
  1797. n: integer;
  1798. begin
  1799. if FStopFlag then
  1800. exit;
  1801. if MaxB > 0 then
  1802. begin
  1803. y := GetTick;
  1804. if Next > y then
  1805. begin
  1806. x := Next - y;
  1807. if x > 0 then
  1808. begin
  1809. DoStatus(HR_Wait, IntToStr(x));
  1810. sleep(x mod 250);
  1811. for n := 1 to x div 250 do
  1812. if FStopFlag then
  1813. Break
  1814. else
  1815. sleep(250);
  1816. end;
  1817. end;
  1818. Next := GetTick + Trunc((Length / MaxB) * 1000);
  1819. end;
  1820. end;
  1821. function TBlockSocket.TestStopFlag: Boolean;
  1822. begin
  1823. DoHeartbeat;
  1824. Result := FStopFlag;
  1825. if Result then
  1826. begin
  1827. FStopFlag := False;
  1828. FLastError := WSAECONNABORTED;
  1829. ExceptCheck;
  1830. end;
  1831. end;
  1832. function TBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  1833. {$IFNDEF CIL}
  1834. var
  1835. x, y: integer;
  1836. l, r: integer;
  1837. p: Pointer;
  1838. {$ENDIF}
  1839. begin
  1840. Result := 0;
  1841. if TestStopFlag then
  1842. Exit;
  1843. DoMonitor(True, Buffer, Length);
  1844. {$IFDEF CIL}
  1845. Result := synsock.Send(FSocket, Buffer, Length, 0);
  1846. {$ELSE}
  1847. l := Length;
  1848. x := 0;
  1849. while x < l do
  1850. begin
  1851. y := l - x;
  1852. if y > FSendMaxChunk then
  1853. y := FSendMaxChunk;
  1854. if y > 0 then
  1855. begin
  1856. LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
  1857. p := IncPoint(Buffer, x);
  1858. r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
  1859. SockCheck(r);
  1860. if FLastError = WSAEWOULDBLOCK then
  1861. begin
  1862. if CanWrite(FNonblockSendTimeout) then
  1863. begin
  1864. r := synsock.Send(FSocket, p, y, MSG_NOSIGNAL);
  1865. SockCheck(r);
  1866. end
  1867. else
  1868. FLastError := WSAETIMEDOUT;
  1869. end;
  1870. if FLastError <> 0 then
  1871. Break;
  1872. Inc(x, r);
  1873. Inc(Result, r);
  1874. Inc(FSendCounter, r);
  1875. DoStatus(HR_WriteCount, IntToStr(r));
  1876. end
  1877. else
  1878. break;
  1879. end;
  1880. {$ENDIF}
  1881. ExceptCheck;
  1882. end;
  1883. procedure TBlockSocket.SendByte(Data: Byte);
  1884. {$IFDEF CIL}
  1885. var
  1886. buf: TMemory;
  1887. {$ENDIF}
  1888. begin
  1889. {$IFDEF CIL}
  1890. setlength(buf, 1);
  1891. buf[0] := Data;
  1892. SendBuffer(buf, 1);
  1893. {$ELSE}
  1894. SendBuffer(@Data, 1);
  1895. {$ENDIF}
  1896. end;
  1897. procedure TBlockSocket.SendString(Data: TSynaBytes);
  1898. var
  1899. buf: TMemory;
  1900. count: Integer;
  1901. begin
  1902. {$IFDEF CIL}
  1903. buf := BytesOf(Data);
  1904. count := Length(Data);
  1905. {$ELSE}
  1906. {$IFDEF UNICODE}
  1907. buf := TSynaBytes(Data).Data; //TSynaByte(Data)
  1908. count := Data.Length; // avoid conversion
  1909. {$ELSE}
  1910. buf := Pointer(data);
  1911. count := Length(Data);
  1912. {$ENDIF}
  1913. {$ENDIF}
  1914. SendBuffer(buf, count);
  1915. end;
  1916. procedure TBlockSocket.SendInteger(Data: integer);
  1917. var
  1918. buf: TMemory;
  1919. begin
  1920. {$IFDEF CIL}
  1921. buf := System.BitConverter.GetBytes(Data);
  1922. {$ELSE}
  1923. buf := @Data;
  1924. {$ENDIF}
  1925. SendBuffer(buf, SizeOf(Data));
  1926. end;
  1927. procedure TBlockSocket.SendBlock(const Data: string);
  1928. var
  1929. i: integer;
  1930. begin
  1931. i := SwapBytes(Length(data));
  1932. SendString(Codelongint(i) + Data);
  1933. end;
  1934. procedure TBlockSocket.InternalSendStream(const Stream: TStream; WithSize, Indy: boolean);
  1935. var
  1936. l: int64;
  1937. yr: integer;
  1938. s: string;
  1939. b: boolean;
  1940. {$IFDEF CIL}
  1941. buf: TMemory;
  1942. {$ENDIF}
  1943. begin
  1944. b := true;
  1945. l := 0;
  1946. if WithSize then
  1947. begin
  1948. l := Stream.Size - Stream.Position;;
  1949. if not Indy then
  1950. l := synsock.HToNL(l);
  1951. end;
  1952. repeat
  1953. {$IFDEF CIL}
  1954. Setlength(buf, FSendMaxChunk);
  1955. yr := Stream.read(buf, FSendMaxChunk);
  1956. if yr > 0 then
  1957. begin
  1958. if WithSize and b then
  1959. begin
  1960. b := false;
  1961. SendString(CodeLongInt(l));
  1962. end;
  1963. SendBuffer(buf, yr);
  1964. if FLastError <> 0 then
  1965. break;
  1966. end
  1967. {$ELSE}
  1968. Setlength(s, FSendMaxChunk);
  1969. yr := Stream.read(Pointer(s)^, FSendMaxChunk);
  1970. if yr > 0 then
  1971. begin
  1972. SetLength(s, yr);
  1973. if WithSize and b then
  1974. begin
  1975. b := false;
  1976. SendString(CodeLongInt(l) + s);
  1977. end
  1978. else
  1979. SendString(s);
  1980. if FLastError <> 0 then
  1981. break;
  1982. end
  1983. {$ENDIF}
  1984. until yr <= 0;
  1985. end;
  1986. procedure TBlockSocket.SendStreamRaw(const Stream: TStream);
  1987. begin
  1988. InternalSendStream(Stream, false, false);
  1989. end;
  1990. procedure TBlockSocket.SendStreamIndy(const Stream: TStream);
  1991. begin
  1992. InternalSendStream(Stream, true, true);
  1993. end;
  1994. procedure TBlockSocket.SendStream(const Stream: TStream);
  1995. begin
  1996. InternalSendStream(Stream, true, false);
  1997. end;
  1998. function TBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
  1999. begin
  2000. Result := 0;
  2001. if TestStopFlag then
  2002. Exit;
  2003. LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  2004. Result := synsock.Recv(FSocket, Buffer, Length, MSG_NOSIGNAL);
  2005. if Result = 0 then
  2006. FLastError := WSAECONNRESET
  2007. else
  2008. SockCheck(Result);
  2009. ExceptCheck;
  2010. if Result > 0 then
  2011. begin
  2012. Inc(FRecvCounter, Result);
  2013. DoStatus(HR_ReadCount, IntToStr(Result));
  2014. DoMonitor(False, Buffer, Result);
  2015. DoReadFilter(Buffer, Result);
  2016. end;
  2017. end;
  2018. function TBlockSocket.RecvBufferEx(Buffer: TMemory; Len: Integer;
  2019. Timeout: Integer): Integer;
  2020. var
  2021. s: TSynaBytes;
  2022. rl, l: integer;
  2023. ti: FixedUInt;
  2024. {$IFDEF CIL}
  2025. n: integer;
  2026. b: TMemory;
  2027. {$ENDIF}
  2028. begin
  2029. ResetLastError;
  2030. Result := 0;
  2031. if Len > 0 then
  2032. begin
  2033. rl := 0;
  2034. repeat
  2035. ti := GetTick;
  2036. s := RecvPacket(Timeout);
  2037. l := s.length;
  2038. if (rl + l) > Len then
  2039. l := Len - rl;
  2040. {$IFDEF CIL}
  2041. b := BytesOf(s);
  2042. for n := 0 to l do
  2043. Buffer[rl + n] := b[n];
  2044. {$ELSE}
  2045. Move({$IFNDEF UNICODE}Pointer(s)^{$ELSE}s.Bytes[0]{$ENDIF},
  2046. IncPoint(Buffer, rl)^, l);
  2047. {$ENDIF}
  2048. rl := rl + l;
  2049. if FLastError <> 0 then
  2050. Break;
  2051. if rl >= Len then
  2052. Break;
  2053. if not FInterPacketTimeout then
  2054. begin
  2055. Timeout := Timeout - integer(TickDelta(ti, GetTick));
  2056. if Timeout <= 0 then
  2057. begin
  2058. FLastError := WSAETIMEDOUT;
  2059. Break;
  2060. end;
  2061. end;
  2062. until False;
  2063. DeleteInternal(s, 1, l);
  2064. FBuffer := s;
  2065. Result := rl;
  2066. end;
  2067. end;
  2068. function TBlockSocket.RecvBufferStr(Len: Integer; Timeout: Integer): TSynaBytes;
  2069. var
  2070. x: integer;
  2071. buf: TBytes;
  2072. begin
  2073. Result := '';
  2074. if Len > 0 then
  2075. begin
  2076. Setlength(Buf, Len);
  2077. x := RecvBufferEx(@buf[0], Len, Timeout);
  2078. if FLastError = 0 then
  2079. begin
  2080. SetLength(Buf, x);
  2081. {$IFDEF UNICODE}
  2082. Result.Length := x;
  2083. Move(Buf[0], Result.Bytes[0], x);
  2084. {$ELSE}
  2085. Result := StringOf(Buf);
  2086. {$ENDIF}
  2087. end
  2088. else
  2089. Result := '';
  2090. Setlength(Buf, 0);
  2091. end;
  2092. end;
  2093. function TBlockSocket.RecvPacket(Timeout: Integer): TSynaBytes;
  2094. var
  2095. x: Integer;
  2096. buf: TBytes;
  2097. begin
  2098. Result := '';
  2099. ResetLastError;
  2100. if FBuffer <> '' then
  2101. begin
  2102. Result := FBuffer;
  2103. FBuffer := '';
  2104. end
  2105. else
  2106. begin
  2107. {$IFDEF MSWINDOWS}
  2108. //not drain CPU on large downloads...
  2109. //Sleep(10{0});
  2110. {$ENDIF}
  2111. x := WaitingData;
  2112. if x > 0 then
  2113. begin
  2114. SetLength(Buf, x);
  2115. x := RecvBuffer(Buf, x);
  2116. if x >= 0 then
  2117. begin
  2118. SetLength(Buf, x);
  2119. {$IFDEF UNICODE} Result := TSynaBytes(buf); {$ELSE} Result := StringOf(buf); {$ENDIF}
  2120. end;
  2121. end
  2122. else
  2123. begin
  2124. if CanRead(Timeout) then
  2125. begin
  2126. x := WaitingData;
  2127. if x = 0 then
  2128. FLastError := WSAECONNRESET;
  2129. if x > 0 then
  2130. begin
  2131. SetLength(Buf, x);
  2132. x := RecvBuffer(Buf, x);
  2133. if x >= 0 then
  2134. begin
  2135. SetLength(Buf, x);
  2136. {$IFDEF UNICODE} Result := TSynaBytes(buf); {$ELSE} Result := StringOf(buf); {$ENDIF}
  2137. end;
  2138. SetLength(Buf, 0);
  2139. end;
  2140. end
  2141. else
  2142. FLastError := WSAETIMEDOUT;
  2143. end;
  2144. end;
  2145. if FConvertLineEnd and (Result <> '') then
  2146. begin
  2147. if FLastCR and (Result[1] = LF) then
  2148. DeleteInternal(Result, 1, 1);
  2149. if FLastLF and (Result[1] = CR) then
  2150. DeleteInternal(Result, 1, 1);
  2151. FLastCR := False;
  2152. FLastLF := False;
  2153. end;
  2154. ExceptCheck;
  2155. end;
  2156. function TBlockSocket.RecvByte(Timeout: Integer): Byte;
  2157. begin
  2158. Result := 0;
  2159. ResetLastError;
  2160. if FBuffer = '' then
  2161. FBuffer := RecvPacket(Timeout);
  2162. if (FLastError = 0) and (FBuffer <> '') then
  2163. begin
  2164. Result := Ord(FBuffer[1]);
  2165. {$IFNDEF UNICODE}
  2166. Delete(FBuffer, 1, 1);
  2167. {$ELSE}
  2168. FBuffer.Delete(1, 1); // TEST!
  2169. {$ENDIF}
  2170. end;
  2171. ExceptCheck;
  2172. end;
  2173. function TBlockSocket.RecvInteger(Timeout: Integer): Integer;
  2174. var
  2175. s: string;
  2176. begin
  2177. Result := 0;
  2178. s := RecvBufferStr(4, Timeout);
  2179. if FLastError = 0 then
  2180. Result := (ord(s[1]) + ord(s[2]) * 256) + (ord(s[3]) + ord(s[4]) * 256) * 65536;
  2181. end;
  2182. function TBlockSocket.RecvTerminated(Timeout: Integer; const Terminator: string): string;
  2183. var
  2184. x: Integer;
  2185. s: TSynaBytes;
  2186. l: Integer;
  2187. CorCRLF: Boolean;
  2188. t: string;
  2189. tl: integer;
  2190. ti: FixedUInt;
  2191. begin
  2192. ResetLastError;
  2193. Result := '';
  2194. l := Length(Terminator);
  2195. if l = 0 then
  2196. Exit;
  2197. tl := l;
  2198. CorCRLF := FConvertLineEnd and (Terminator = CRLF);
  2199. s := '';
  2200. x := 0;
  2201. repeat
  2202. //get rest of FBuffer or incomming new data...
  2203. ti := GetTick;
  2204. s := s + RecvPacket(Timeout);
  2205. if FLastError <> 0 then
  2206. Break;
  2207. x := 0;
  2208. if s.Length > 0 then
  2209. if CorCRLF then
  2210. begin
  2211. t := '';
  2212. x := PosCRLF(s, t);
  2213. tl := t.Length;
  2214. if t = CR then
  2215. FLastCR := True;
  2216. if t = LF then
  2217. FLastLF := True;
  2218. end
  2219. else
  2220. begin
  2221. x := pos(Terminator, s);
  2222. tl := l;
  2223. end;
  2224. if (FMaxLineLength <> 0) and (s.Length > FMaxLineLength) then
  2225. begin
  2226. FLastError := WSAENOBUFS;
  2227. Break;
  2228. end;
  2229. if x > 0 then
  2230. Break;
  2231. if not FInterPacketTimeout then
  2232. begin
  2233. Timeout := Timeout - integer(TickDelta(ti, GetTick));
  2234. if Timeout <= 0 then
  2235. begin
  2236. FLastError := WSAETIMEDOUT;
  2237. Break;
  2238. end;
  2239. end;
  2240. until False;
  2241. if x > 0 then
  2242. begin
  2243. Result := Copy(s, 1, x - 1);
  2244. DeleteInternal(s, 1, x + tl - 1);
  2245. end;
  2246. FBuffer := s;
  2247. ExceptCheck;
  2248. end;
  2249. function TBlockSocket.RecvString(Timeout: Integer): string;
  2250. var
  2251. s: string;
  2252. begin
  2253. Result := '';
  2254. s := RecvTerminated(Timeout, CRLF);
  2255. if FLastError = 0 then
  2256. Result := s;
  2257. end;
  2258. function TBlockSocket.RecvBlock(Timeout: Integer): string;
  2259. var
  2260. x: integer;
  2261. begin
  2262. Result := '';
  2263. x := RecvInteger(Timeout);
  2264. if FLastError = 0 then
  2265. Result := RecvBufferStr(x, Timeout);
  2266. end;
  2267. procedure TBlockSocket.RecvStreamRaw(const Stream: TStream; Timeout: Integer);
  2268. var
  2269. s: string;
  2270. begin
  2271. repeat
  2272. s := RecvPacket(Timeout);
  2273. if FLastError = 0 then
  2274. WriteStrToStream(Stream, s);
  2275. until FLastError <> 0;
  2276. end;
  2277. procedure TBlockSocket.RecvStreamSize(const Stream: TStream; Timeout: Integer; Size: int64);
  2278. var
  2279. s: TSynaBytes;
  2280. n: int64;
  2281. {$IFDEF CIL}
  2282. buf: TMemory;
  2283. {$ENDIF}
  2284. begin
  2285. n := Size div int64(FSendMaxChunk);
  2286. while n > 0 do
  2287. begin
  2288. {$IFDEF CIL}
  2289. SetLength(buf, FSendMaxChunk);
  2290. RecvBufferEx(buf, FSendMaxChunk, Timeout);
  2291. if FLastError <> 0 then
  2292. Exit;
  2293. Stream.Write(buf, FSendMaxChunk);
  2294. {$ELSE}
  2295. s := RecvBufferStr(FSendMaxChunk, Timeout);
  2296. if FLastError <> 0 then
  2297. Exit;
  2298. WriteStrToStream(Stream, s);
  2299. {$ENDIF}
  2300. dec(n);
  2301. end;
  2302. n := Size mod int64(FSendMaxChunk);
  2303. if n > 0 then
  2304. begin
  2305. {$IFDEF CIL}
  2306. SetLength(buf, n);
  2307. RecvBufferEx(buf, n, Timeout);
  2308. if FLastError <> 0 then
  2309. Exit;
  2310. Stream.Write(buf, n);
  2311. {$ELSE}
  2312. s := RecvBufferStr(n, Timeout);
  2313. if FLastError <> 0 then
  2314. Exit;
  2315. WriteStrToStream(Stream, s);
  2316. {$ENDIF}
  2317. end;
  2318. end;
  2319. procedure TBlockSocket.RecvStreamIndy(const Stream: TStream; Timeout: Integer);
  2320. var
  2321. x: integer;
  2322. begin
  2323. x := RecvInteger(Timeout);
  2324. x := synsock.NToHL(x);
  2325. if FLastError = 0 then
  2326. RecvStreamSize(Stream, Timeout, x);
  2327. end;
  2328. procedure TBlockSocket.RecvStream(const Stream: TStream; Timeout: Integer);
  2329. var
  2330. x: integer;
  2331. begin
  2332. x := RecvInteger(Timeout);
  2333. if FLastError = 0 then
  2334. RecvStreamSize(Stream, Timeout, x);
  2335. end;
  2336. function TBlockSocket.PeekBuffer(Buffer: TMemory; Length: Integer): Integer;
  2337. begin
  2338. {$IFNDEF CIL}
  2339. // Result := synsock.Recv(FSocket, Buffer^, Length, MSG_PEEK + MSG_NOSIGNAL);
  2340. Result := synsock.Recv(FSocket, Buffer, Length, MSG_PEEK + MSG_NOSIGNAL);
  2341. SockCheck(Result);
  2342. ExceptCheck;
  2343. {$ENDIF}
  2344. end;
  2345. function TBlockSocket.PeekByte(Timeout: Integer): Byte;
  2346. var
  2347. s: string;
  2348. begin
  2349. {$IFNDEF CIL}
  2350. Result := 0;
  2351. if CanRead(Timeout) then
  2352. begin
  2353. SetLength(s, 1);
  2354. PeekBuffer(Pointer(s), 1);
  2355. if s <> '' then
  2356. Result := Ord(s[1]);
  2357. end
  2358. else
  2359. FLastError := WSAETIMEDOUT;
  2360. ExceptCheck;
  2361. {$ENDIF}
  2362. end;
  2363. procedure TBlockSocket.ResetLastError;
  2364. begin
  2365. FLastError := 0;
  2366. FLastErrorDesc := '';
  2367. end;
  2368. function TBlockSocket.SockCheck(SockResult: Integer): Integer;
  2369. begin
  2370. ResetLastError;
  2371. if SockResult = integer(SOCKET_ERROR) then
  2372. begin
  2373. FLastError := synsock.WSAGetLastError;
  2374. if FLastError <= WSABASEERR then
  2375. Inc(FLastError, WSABASEERR);
  2376. FLastErrorDesc := GetErrorDescEx;
  2377. end;
  2378. Result := FLastError;
  2379. end;
  2380. procedure TBlockSocket.ExceptCheck;
  2381. var
  2382. e: ESynapseError;
  2383. begin
  2384. FLastErrorDesc := GetErrorDescEx;
  2385. if (LastError <> 0) and (LastError <> WSAEINPROGRESS)
  2386. and (LastError <> WSAEWOULDBLOCK) then
  2387. begin
  2388. DoStatus(HR_Error, IntToStr(FLastError) + ',' + FLastErrorDesc);
  2389. FDisconnected := True;
  2390. if FRaiseExcept then
  2391. begin
  2392. if FLastError = 104 then
  2393. e := EResetByPeer.Create(Format('Synapse TCP/IP socket error. Reset by peer %d: %s',
  2394. [FLastError, FLastErrorDesc]))
  2395. else if FLastError = 10098 then
  2396. e := ECouldNotBindSocket.Create(Format('Synapse TCP/IP socket error. Could not bind socket %d: %s',
  2397. [FLastError, FLastErrorDesc]))
  2398. else if FLastError = 10054 then
  2399. e := EConnectionResetByPeer.Create(Format('Synapse TCP/IP socket error. Connection reset by peer %d: %s',
  2400. [FLastError, FLastErrorDesc]))
  2401. else if FLastError = 10057 then
  2402. e := ESockectIsnotConnected.Create(Format('Synapse TCP/IP socket error. Socket is not connected %d: %s',
  2403. [FLastError, FLastErrorDesc]))
  2404. else if FLastError = 10060 then
  2405. e := EConnectionTimedOut.Create(Format('Synapse TCP/IP socket error. Connection timed out %d: %s',
  2406. [FLastError, FLastErrorDesc]))
  2407. else if FLastError = 10061 then
  2408. e := EConnectionRefused.Create(Format('Synapse TCP/IP socket error. Connection refused %d: %s',
  2409. [FLastError, FLastErrorDesc]))
  2410. else if FLastError = 10049 then
  2411. e := ECantAssignAddress.Create(Format('Synapse TCP/IP socket error. Can''t assign requested address %d: %s',
  2412. [FLastError, FLastErrorDesc]))
  2413. else if FLastError = -2 then
  2414. e := ESocketMinus2.Create(Format('Synapse TCP/IP socket error %d: %s',
  2415. [FLastError, FLastErrorDesc]))
  2416. else e := ESynapseError.Create(Format('Synapse TCP/IP socket error %d: %s',
  2417. [FLastError, FLastErrorDesc]));
  2418. e.ErrorCode := FLastError;
  2419. e.ErrorMessage := FLastErrorDesc;
  2420. raise e;
  2421. end;
  2422. end;
  2423. end;
  2424. function TBlockSocket.WaitingData: Integer;
  2425. var
  2426. x: Integer;
  2427. begin
  2428. Result := 0;
  2429. if synsock.IoctlSocket(FSocket, FIONREAD, x) = 0 then
  2430. Result := x;
  2431. if Result > c64k then
  2432. Result := c64k;
  2433. end;
  2434. function TBlockSocket.WaitingDataEx: Integer;
  2435. begin
  2436. if FBuffer <> '' then
  2437. Result := FBuffer.Length
  2438. else
  2439. Result := WaitingData;
  2440. end;
  2441. procedure TBlockSocket.Purge;
  2442. begin
  2443. Sleep(1);
  2444. try
  2445. while (FBuffer.Length > 0) or (WaitingData > 0) do
  2446. begin
  2447. RecvPacket(0);
  2448. if FLastError <> 0 then
  2449. break;
  2450. end;
  2451. except
  2452. on exception do;
  2453. end;
  2454. ResetLastError;
  2455. end;
  2456. procedure TBlockSocket.SetLinger(Enable: Boolean; Linger: Integer);
  2457. var
  2458. d: TSynaOption;
  2459. begin
  2460. //d := TSynaOption.Create;
  2461. d.Option := SOT_Linger;
  2462. d.Enabled := Enable;
  2463. d.Value := Linger;
  2464. DelayedOption(d);
  2465. end;
  2466. function TBlockSocket.LocalName: string;
  2467. begin
  2468. Result := synsock.GetHostName;
  2469. if Result = '' then
  2470. Result := '127.0.0.1';
  2471. end;
  2472. procedure TBlockSocket.ResolveNameToIP(const Name: string; const IPList:
  2473. TStrings);
  2474. begin
  2475. IPList.Clear;
  2476. synsock.ResolveNameToIP(Name, FamilyToAF(FFamily), GetSocketprotocol, GetSocketType, IPList);
  2477. if IPList.Count = 0 then
  2478. IPList.Add(cAnyHost);
  2479. end;
  2480. function TBlockSocket.ResolveName(const Name: string): string;
  2481. var
  2482. l: TStringList;
  2483. begin
  2484. l := TStringList.Create;
  2485. try
  2486. ResolveNameToIP(Name, l);
  2487. Result := l[0];
  2488. finally
  2489. FreeAndNil(l);
  2490. end;
  2491. end;
  2492. function TBlockSocket.ResolvePort(const Port: string): Word;
  2493. begin
  2494. Result := synsock.ResolvePort(Port, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
  2495. end;
  2496. function TBlockSocket.ResolveIPToName(IP: string): string;
  2497. begin
  2498. if not IsIP(IP) and not IsIp6(IP) then
  2499. IP := ResolveName(IP);
  2500. Result := synsock.ResolveIPToName(IP, FamilyToAF(FFamily), GetSocketProtocol, GetSocketType);
  2501. end;
  2502. procedure TBlockSocket.SetRemoteSin(const IP, Port: string);
  2503. begin
  2504. SetSin(FRemoteSin, IP, Port);
  2505. end;
  2506. function TBlockSocket.GetLocalSinIP: string;
  2507. begin
  2508. Result := GetSinIP(FLocalSin);
  2509. end;
  2510. function TBlockSocket.GetRecvTimeout: integer;
  2511. var
  2512. l: integer;
  2513. begin
  2514. l:=SizeOf(Integer);
  2515. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVTIMEO, @Result, l));
  2516. ExceptCheck;
  2517. end;
  2518. function TBlockSocket.GetRemoteSinIP: string;
  2519. begin
  2520. Result := GetSinIP(FRemoteSin);
  2521. end;
  2522. function TBlockSocket.GetLocalSinPort: Integer;
  2523. begin
  2524. Result := GetSinPort(FLocalSin);
  2525. end;
  2526. function TBlockSocket.GetRemoteSinPort: Integer;
  2527. begin
  2528. Result := GetSinPort(FRemoteSin);
  2529. end;
  2530. function TBlockSocket.InternalCanRead(Timeout: Integer): Boolean;
  2531. {$IFDEF CIL}
  2532. begin
  2533. Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectRead);
  2534. {$ELSE}
  2535. var
  2536. TimeVal: PTimeVal;
  2537. TimeV: TTimeVal;
  2538. x: Integer;
  2539. FDSet: TFDSet;
  2540. begin
  2541. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2542. TimeV.tv_sec := Timeout div 1000;
  2543. TimeVal := @TimeV;
  2544. if Timeout = -1 then
  2545. TimeVal := nil;
  2546. FDSet := FFdSet;
  2547. x := synsock.Select(integer(FSocket + 1), @FDSet, nil, nil, TimeVal);
  2548. SockCheck(x);
  2549. if FLastError <> 0 then
  2550. x := 0;
  2551. Result := x > 0;
  2552. {$ENDIF}
  2553. end;
  2554. function TBlockSocket.CanRead(Timeout: Integer): Boolean;
  2555. var
  2556. ti, tr: Integer;
  2557. n: integer;
  2558. begin
  2559. if (FHeartbeatRate <> 0) and (Timeout <> -1) then
  2560. begin
  2561. ti := Timeout div FHeartbeatRate;
  2562. tr := Timeout mod FHeartbeatRate;
  2563. end
  2564. else
  2565. begin
  2566. ti := 0;
  2567. tr := Timeout;
  2568. end;
  2569. Result := InternalCanRead(tr);
  2570. if not Result then
  2571. for n := 0 to ti do
  2572. begin
  2573. DoHeartbeat;
  2574. if FStopFlag then
  2575. begin
  2576. Result := False;
  2577. FStopFlag := False;
  2578. Break;
  2579. end;
  2580. Result := InternalCanRead(FHeartbeatRate);
  2581. if Result then
  2582. break;
  2583. end;
  2584. ExceptCheck;
  2585. if Result then
  2586. DoStatus(HR_CanRead, '');
  2587. end;
  2588. function TBlockSocket.InternalCanWrite(Timeout: Integer): Boolean;
  2589. {$IFDEF CIL}
  2590. begin
  2591. Result := FSocket.Poll(Timeout * 1000, SelectMode.SelectWrite);
  2592. {$ELSE}
  2593. var
  2594. TimeVal: PTimeVal;
  2595. TimeV: TTimeVal;
  2596. x: Integer;
  2597. FDSet: TFDSet;
  2598. begin
  2599. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2600. TimeV.tv_sec := Timeout div 1000;
  2601. TimeVal := @TimeV;
  2602. if Timeout = -1 then
  2603. TimeVal := nil;
  2604. FDSet := FFdSet;
  2605. x := synsock.Select(FSocket + 1, nil, @FDSet, nil, TimeVal);
  2606. SockCheck(x);
  2607. if FLastError <> 0 then
  2608. x := 0;
  2609. Result := x > 0;
  2610. {$ENDIF}
  2611. end;
  2612. function TBlockSocket.CanWrite(Timeout: Integer): Boolean;
  2613. var
  2614. ti, tr: Integer;
  2615. n: integer;
  2616. begin
  2617. if (FHeartbeatRate <> 0) and (Timeout <> -1) then
  2618. begin
  2619. ti := Timeout div FHeartbeatRate;
  2620. tr := Timeout mod FHeartbeatRate;
  2621. end
  2622. else
  2623. begin
  2624. ti := 0;
  2625. tr := Timeout;
  2626. end;
  2627. Result := InternalCanWrite(tr);
  2628. if not Result then
  2629. for n := 0 to ti do
  2630. begin
  2631. DoHeartbeat;
  2632. if FStopFlag then
  2633. begin
  2634. Result := False;
  2635. FStopFlag := False;
  2636. Break;
  2637. end;
  2638. Result := InternalCanWrite(FHeartbeatRate);
  2639. if Result then
  2640. break;
  2641. end;
  2642. ExceptCheck;
  2643. if Result then
  2644. DoStatus(HR_CanWrite, '');
  2645. end;
  2646. function TBlockSocket.CanReadEx(Timeout: Integer): Boolean;
  2647. begin
  2648. if FBuffer <> '' then
  2649. Result := True
  2650. else
  2651. Result := CanRead(Timeout);
  2652. end;
  2653. function TBlockSocket.SendBufferTo(const Buffer: TMemory; Length: Integer): Integer;
  2654. begin
  2655. Result := 0;
  2656. if TestStopFlag then
  2657. Exit;
  2658. DoMonitor(True, Buffer, Length);
  2659. LimitBandwidth(Length, FMaxSendBandwidth, FNextsend);
  2660. Result := synsock.SendTo(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
  2661. SockCheck(Result);
  2662. ExceptCheck;
  2663. Inc(FSendCounter, Result);
  2664. DoStatus(HR_WriteCount, IntToStr(Result));
  2665. end;
  2666. function TBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
  2667. begin
  2668. Result := 0;
  2669. if TestStopFlag then
  2670. Exit;
  2671. LimitBandwidth(Length, FMaxRecvBandwidth, FNextRecv);
  2672. Result := synsock.RecvFrom(FSocket, Buffer, Length, MSG_NOSIGNAL, FRemoteSin);
  2673. SockCheck(Result);
  2674. ExceptCheck;
  2675. Inc(FRecvCounter, Result);
  2676. DoStatus(HR_ReadCount, IntToStr(Result));
  2677. DoMonitor(False, Buffer, Result);
  2678. end;
  2679. function TBlockSocket.GetSizeRecvBuffer: Integer;
  2680. var
  2681. l: Integer;
  2682. {$IFDEF CIL}
  2683. buf: TMemory;
  2684. {$ENDIF}
  2685. begin
  2686. {$IFDEF CIL}
  2687. setlength(buf, 4);
  2688. SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_RCVBUF), buf, l));
  2689. Result := System.BitConverter.ToInt32(buf,0);
  2690. {$ELSE}
  2691. l := SizeOf(Result);
  2692. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_RCVBUF, @Result, l));
  2693. if FLastError <> 0 then
  2694. Result := 1024;
  2695. ExceptCheck;
  2696. {$ENDIF}
  2697. end;
  2698. procedure TBlockSocket.SetSizeRecvBuffer(Size: Integer);
  2699. var
  2700. d: TSynaOption;
  2701. begin
  2702. //d := TSynaOption.Create;
  2703. d.Option := SOT_RecvBuff;
  2704. d.Value := Size;
  2705. DelayedOption(d);
  2706. end;
  2707. function TBlockSocket.GetSizeSendBuffer: Integer;
  2708. var
  2709. l: Integer;
  2710. {$IFDEF CIL}
  2711. buf: TMemory;
  2712. {$ENDIF}
  2713. begin
  2714. {$IFDEF CIL}
  2715. setlength(buf, 4);
  2716. SockCheck(synsock.GetSockOpt(FSocket, integer(SOL_SOCKET), integer(SO_SNDBUF), buf, l));
  2717. Result := System.BitConverter.ToInt32(buf,0);
  2718. {$ELSE}
  2719. l := SizeOf(Result);
  2720. SockCheck(synsock.GetSockOpt(FSocket, SOL_SOCKET, SO_SNDBUF, @Result, l));
  2721. if FLastError <> 0 then
  2722. Result := 1024;
  2723. ExceptCheck;
  2724. {$ENDIF}
  2725. end;
  2726. procedure TBlockSocket.SetSizeSendBuffer(Size: Integer);
  2727. var
  2728. d: TSynaOption;
  2729. begin
  2730. //d := TSynaOption.Create;
  2731. d.Option := SOT_SendBuff;
  2732. d.Value := Size;
  2733. DelayedOption(d);
  2734. end;
  2735. procedure TBlockSocket.SetNagleMode(Value: Boolean);
  2736. var
  2737. d: TSynaOption;
  2738. begin
  2739. //d := TSynaOption.Create;
  2740. d.Option := SOT_NoDelay;
  2741. d.Enabled := Value;
  2742. DelayedOption(d);
  2743. end;
  2744. procedure TBlockSocket.SetNonBlockMode(Value: Boolean);
  2745. var
  2746. d: TSynaOption;
  2747. begin
  2748. //d := TSynaOption.Create;
  2749. d.Option := SOT_nonblock;
  2750. d.Enabled := Value;
  2751. DelayedOption(d);
  2752. end;
  2753. procedure TBlockSocket.SetTimeout(Timeout: Integer);
  2754. begin
  2755. SetSendTimeout(Timeout);
  2756. SetRecvTimeout(Timeout);
  2757. end;
  2758. procedure TBlockSocket.SetSendTimeout(Timeout: Integer);
  2759. var
  2760. d: TSynaOption;
  2761. begin
  2762. //d := TSynaOption.Create;
  2763. d.Option := SOT_sendtimeout;
  2764. d.Value := Timeout;
  2765. DelayedOption(d);
  2766. end;
  2767. procedure TBlockSocket.SetRecvTimeout(Timeout: Integer);
  2768. var
  2769. d: TSynaOption;
  2770. begin
  2771. //d := TSynaOption.Create;
  2772. d.Option := SOT_recvtimeout;
  2773. d.Value := Timeout;
  2774. DelayedOption(d);
  2775. end;
  2776. {$IFNDEF CIL}
  2777. function TBlockSocket.GroupCanRead(const SocketList: TSocketList; Timeout: Integer;
  2778. const CanReadList: TSocketList): boolean;
  2779. var
  2780. FDSet: TFDSet;
  2781. TimeVal: PTimeVal;
  2782. TimeV: TTimeVal;
  2783. x, n: Integer;
  2784. Max: Integer;
  2785. begin
  2786. TimeV.tv_usec := (Timeout mod 1000) * 1000;
  2787. TimeV.tv_sec := Timeout div 1000;
  2788. TimeVal := @TimeV;
  2789. if Timeout = -1 then
  2790. TimeVal := nil;
  2791. FD_ZERO(FDSet);
  2792. Max := 0;
  2793. for n := 0 to SocketList.Count - 1 do
  2794. if TObject(SocketList.Items[n]) is TBlockSocket then
  2795. begin
  2796. if TBlockSocket(SocketList.Items[n]).Socket > Max then
  2797. Max := TBlockSocket(SocketList.Items[n]).Socket;
  2798. FD_SET(TBlockSocket(SocketList.Items[n]).Socket, FDSet);
  2799. end;
  2800. x := synsock.Select(Max + 1, @FDSet, nil, nil, TimeVal);
  2801. SockCheck(x);
  2802. ExceptCheck;
  2803. if FLastError <> 0 then
  2804. x := 0;
  2805. Result := x > 0;
  2806. CanReadList.Clear;
  2807. if Result then
  2808. for n := 0 to SocketList.Count - 1 do
  2809. if TObject(SocketList.Items[n]) is TBlockSocket then
  2810. if FD_ISSET(TBlockSocket(SocketList.Items[n]).Socket, FDSet) then
  2811. CanReadList.Add(TBlockSocket(SocketList.Items[n]));
  2812. end;
  2813. {$ENDIF}
  2814. procedure TBlockSocket.EnableReuse(Value: Boolean);
  2815. var
  2816. d: TSynaOption;
  2817. begin
  2818. //d := TSynaOption.Create;
  2819. d.Option := SOT_reuse;
  2820. d.Enabled := Value;
  2821. DelayedOption(d);
  2822. end;
  2823. procedure TBlockSocket.SetTTL(TTL: integer);
  2824. var
  2825. d: TSynaOption;
  2826. begin
  2827. //d := TSynaOption.Create;
  2828. d.Option := SOT_TTL;
  2829. d.Value := TTL;
  2830. DelayedOption(d);
  2831. end;
  2832. function TBlockSocket.GetTTL:integer;
  2833. var
  2834. l: Integer;
  2835. begin
  2836. {$IFNDEF CIL}
  2837. l := SizeOf(Result);
  2838. if FIP6Used then
  2839. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, @Result, l))
  2840. else
  2841. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_TTL, @Result, l));
  2842. ExceptCheck;
  2843. {$ENDIF}
  2844. end;
  2845. procedure TBlockSocket.SetFamily(Value: TSocketFamily);
  2846. begin
  2847. FFamily := Value;
  2848. FFamilySave := Value;
  2849. end;
  2850. procedure TBlockSocket.SetSocket(Value: TSocket);
  2851. begin
  2852. FRecvCounter := 0;
  2853. FSendCounter := 0;
  2854. FSocket := Value;
  2855. {$IFNDEF CIL}
  2856. FD_ZERO(FFDSet);
  2857. FD_SET(FSocket, FFDSet);
  2858. {$ENDIF}
  2859. GetSins;
  2860. FIP6Used := FRemoteSin.AddressFamily = AF_INET6;
  2861. end;
  2862. function TBlockSocket.GetWsaData: TWSAData;
  2863. begin
  2864. {$IFDEF ONCEWINSOCK}
  2865. Result := WsaDataOnce;
  2866. {$ELSE}
  2867. Result := FWsaDataOnce;
  2868. {$ENDIF}
  2869. end;
  2870. function TBlockSocket.GetSocketType: integer;
  2871. begin
  2872. Result := 0;
  2873. end;
  2874. function TBlockSocket.GetSocketProtocol: integer;
  2875. begin
  2876. Result := integer(IPPROTO_IP);
  2877. end;
  2878. procedure TBlockSocket.DoStatus(Reason: THookSocketReason; const Value: string);
  2879. begin
  2880. if assigned(OnStatus) then
  2881. OnStatus(Self, Reason, Value);
  2882. if Reason = HR_SocketClose then
  2883. FDisconnected := True;
  2884. end;
  2885. procedure TBlockSocket.DoReadFilter(Buffer: TMemory; var Len: Integer);
  2886. var
  2887. s: string;
  2888. begin
  2889. if assigned(OnReadFilter) then
  2890. if Len > 0 then
  2891. begin
  2892. {$IFDEF CIL}
  2893. s := StringOf(Buffer);
  2894. {$ELSE}
  2895. SetLength(s, Len);
  2896. Move(Buffer^, Pointer(s)^, Len);
  2897. {$ENDIF}
  2898. OnReadFilter(Self, s);
  2899. if s.Length > Len then
  2900. SetLength(s, Len);
  2901. Len := s.Length;
  2902. {$IFDEF CIL}
  2903. Buffer := BytesOf(s);
  2904. {$ELSE}
  2905. Move(Pointer(s)^, Buffer^, Len);
  2906. {$ENDIF}
  2907. end;
  2908. end;
  2909. procedure TBlockSocket.DoCreateSocket;
  2910. begin
  2911. if assigned(OnCreateSocket) then
  2912. OnCreateSocket(Self);
  2913. end;
  2914. procedure TBlockSocket.DoMonitor(Writing: Boolean; const Buffer: TMemory; Len: Integer);
  2915. begin
  2916. if assigned(OnMonitor) then
  2917. begin
  2918. OnMonitor(Self, Writing, Buffer, Len);
  2919. end;
  2920. end;
  2921. procedure TBlockSocket.DoHeartbeat;
  2922. begin
  2923. if assigned(OnHeartbeat) and (FHeartbeatRate <> 0) then
  2924. begin
  2925. OnHeartbeat(Self);
  2926. end;
  2927. end;
  2928. function TBlockSocket.GetErrorDescEx: string;
  2929. begin
  2930. Result := GetErrorDesc(FLastError);
  2931. end;
  2932. class function TBlockSocket.GetErrorDesc(ErrorCode: Integer): string;
  2933. begin
  2934. {$IFDEF CIL}
  2935. if ErrorCode = 0 then
  2936. Result := ''
  2937. else
  2938. begin
  2939. Result := WSAGetLastErrorDesc;
  2940. if Result = '' then
  2941. Result := 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
  2942. end;
  2943. {$ELSE}
  2944. case ErrorCode of
  2945. 0:
  2946. Result := '';
  2947. WSAEINTR: {10004}
  2948. Result := 'Interrupted system call';
  2949. WSAEBADF: {10009}
  2950. Result := 'Bad file number';
  2951. WSAEACCES: {10013}
  2952. Result := 'Permission denied';
  2953. WSAEFAULT: {10014}
  2954. Result := 'Bad address';
  2955. WSAEINVAL: {10022}
  2956. Result := 'Invalid argument';
  2957. WSAEMFILE: {10024}
  2958. Result := 'Too many open files';
  2959. WSAEWOULDBLOCK: {10035}
  2960. Result := 'Operation would block';
  2961. WSAEINPROGRESS: {10036}
  2962. Result := 'Operation now in progress';
  2963. WSAEALREADY: {10037}
  2964. Result := 'Operation already in progress';
  2965. WSAENOTSOCK: {10038}
  2966. Result := 'Socket operation on nonsocket';
  2967. WSAEDESTADDRREQ: {10039}
  2968. Result := 'Destination address required';
  2969. WSAEMSGSIZE: {10040}
  2970. Result := 'Message too long';
  2971. WSAEPROTOTYPE: {10041}
  2972. Result := 'Protocol wrong type for Socket';
  2973. WSAENOPROTOOPT: {10042}
  2974. Result := 'Protocol not available';
  2975. WSAEPROTONOSUPPORT: {10043}
  2976. Result := 'Protocol not supported';
  2977. WSAESOCKTNOSUPPORT: {10044}
  2978. Result := 'Socket not supported';
  2979. WSAEOPNOTSUPP: {10045}
  2980. Result := 'Operation not supported on Socket';
  2981. WSAEPFNOSUPPORT: {10046}
  2982. Result := 'Protocol family not supported';
  2983. WSAEAFNOSUPPORT: {10047}
  2984. Result := 'Address family not supported';
  2985. WSAEADDRINUSE: {10048}
  2986. Result := 'Address already in use';
  2987. WSAEADDRNOTAVAIL: {10049}
  2988. Result := 'Can''t assign requested address';
  2989. WSAENETDOWN: {10050}
  2990. Result := 'Network is down';
  2991. WSAENETUNREACH: {10051}
  2992. Result := 'Network is unreachable';
  2993. WSAENETRESET: {10052}
  2994. Result := 'Network dropped connection on reset';
  2995. WSAECONNABORTED: {10053}
  2996. Result := 'Software caused connection abort';
  2997. WSAECONNRESET: {10054}
  2998. Result := 'Connection reset by peer';
  2999. WSAENOBUFS: {10055}
  3000. Result := 'No Buffer space available';
  3001. WSAEISCONN: {10056}
  3002. Result := 'Socket is already connected';
  3003. WSAENOTCONN: {10057}
  3004. Result := 'Socket is not connected';
  3005. WSAESHUTDOWN: {10058}
  3006. Result := 'Can''t send after Socket shutdown';
  3007. WSAETOOMANYREFS: {10059}
  3008. Result := 'Too many references:can''t splice';
  3009. WSAETIMEDOUT: {10060}
  3010. Result := 'Connection timed out';
  3011. WSAECONNREFUSED: {10061}
  3012. Result := 'Connection refused';
  3013. WSAELOOP: {10062}
  3014. Result := 'Too many levels of symbolic links';
  3015. WSAENAMETOOLONG: {10063}
  3016. Result := 'File name is too long';
  3017. WSAEHOSTDOWN: {10064}
  3018. Result := 'Host is down';
  3019. WSAEHOSTUNREACH: {10065}
  3020. Result := 'No route to host';
  3021. WSAENOTEMPTY: {10066}
  3022. Result := 'Directory is not empty';
  3023. WSAEPROCLIM: {10067}
  3024. Result := 'Too many processes';
  3025. WSAEUSERS: {10068}
  3026. Result := 'Too many users';
  3027. WSAEDQUOT: {10069}
  3028. Result := 'Disk quota exceeded';
  3029. WSAESTALE: {10070}
  3030. Result := 'Stale NFS file handle';
  3031. WSAEREMOTE: {10071}
  3032. Result := 'Too many levels of remote in path';
  3033. WSASYSNOTREADY: {10091}
  3034. Result := 'Network subsystem is unusable';
  3035. WSAVERNOTSUPPORTED: {10092}
  3036. Result := 'Winsock DLL cannot support this application';
  3037. WSANOTINITIALISED: {10093}
  3038. Result := 'Winsock not initialized';
  3039. WSAEDISCON: {10101}
  3040. Result := 'Disconnect';
  3041. WSAHOST_NOT_FOUND: {11001}
  3042. Result := 'Host not found';
  3043. WSATRY_AGAIN: {11002}
  3044. Result := 'Non authoritative - host not found';
  3045. WSANO_RECOVERY: {11003}
  3046. Result := 'Non recoverable error';
  3047. WSANO_DATA: {11004}
  3048. Result := 'Valid name, no data record of requested type'
  3049. else
  3050. Result := SysErrorMessage(ErrorCode) // 'Other Winsock error (' + IntToStr(ErrorCode) + ')';
  3051. end;
  3052. {$ENDIF}
  3053. end;
  3054. {======================================================================}
  3055. constructor TSocksBlockSocket.Create;
  3056. begin
  3057. inherited Create;
  3058. FSocksIP:= '';
  3059. FSocksPort:= '1080';
  3060. FSocksTimeout:= 60000;
  3061. FSocksUsername:= '';
  3062. FSocksPassword:= '';
  3063. FUsingSocks := False;
  3064. FSocksResolver := True;
  3065. FSocksLastError := 0;
  3066. FSocksResponseIP := '';
  3067. FSocksResponsePort := '';
  3068. FSocksLocalIP := '';
  3069. FSocksLocalPort := '';
  3070. FSocksRemoteIP := '';
  3071. FSocksRemotePort := '';
  3072. FBypassFlag := False;
  3073. FSocksType := ST_Socks5;
  3074. end;
  3075. function TSocksBlockSocket.SocksOpen: boolean;
  3076. var
  3077. Buf: string;
  3078. n: integer;
  3079. begin
  3080. Result := False;
  3081. FUsingSocks := False;
  3082. if FSocksType <> ST_Socks5 then
  3083. begin
  3084. FUsingSocks := True;
  3085. Result := True;
  3086. end
  3087. else
  3088. begin
  3089. FBypassFlag := True;
  3090. try
  3091. if FSocksUsername = '' then
  3092. Buf := #5 + #1 + #0
  3093. else
  3094. Buf := #5 + #2 + #2 +#0;
  3095. SendString(Buf);
  3096. Buf := RecvBufferStr(2, FSocksTimeout);
  3097. if Buf.Length < 2 then
  3098. Exit;
  3099. if Buf[1] <> #5 then
  3100. Exit;
  3101. n := Ord(Buf[2]);
  3102. case n of
  3103. 0: //not need authorisation
  3104. ;
  3105. 2:
  3106. begin
  3107. Buf := #1 + Char(Length(FSocksUsername)) + FSocksUsername +
  3108. Char(Length(FSocksPassword)) + FSocksPassword;
  3109. SendString(Buf);
  3110. Buf := RecvBufferStr(2, FSocksTimeout);
  3111. if Length(Buf) < 2 then
  3112. Exit;
  3113. if Buf[2] <> #0 then
  3114. Exit;
  3115. end;
  3116. else
  3117. //other authorisation is not supported!
  3118. Exit;
  3119. end;
  3120. FUsingSocks := True;
  3121. Result := True;
  3122. finally
  3123. FBypassFlag := False;
  3124. end;
  3125. end;
  3126. end;
  3127. function TSocksBlockSocket.SocksRequest(Cmd: Byte;
  3128. const IP, Port: string): Boolean;
  3129. var
  3130. Buf: string;
  3131. begin
  3132. FBypassFlag := True;
  3133. try
  3134. if FSocksType <> ST_Socks5 then
  3135. Buf := #4 + Char(Cmd) + SocksCode(IP, Port)
  3136. else
  3137. Buf := #5 + Char(Cmd) + #0 + SocksCode(IP, Port);
  3138. SendString(Buf);
  3139. Result := FLastError = 0;
  3140. finally
  3141. FBypassFlag := False;
  3142. end;
  3143. end;
  3144. function TSocksBlockSocket.SocksResponse: Boolean;
  3145. var
  3146. Buf, s, m, z: string;
  3147. x: integer;
  3148. begin
  3149. Result := False;
  3150. FBypassFlag := True;
  3151. try
  3152. FSocksResponseIP := '';
  3153. FSocksResponsePort := '';
  3154. FSocksLastError := -1;
  3155. if FSocksType <> ST_Socks5 then
  3156. begin
  3157. Buf := RecvBufferStr(8, FSocksTimeout);
  3158. if FLastError <> 0 then
  3159. Exit;
  3160. if Buf[1] <> #0 then
  3161. Exit;
  3162. FSocksLastError := Ord(Buf[2]);
  3163. end
  3164. else
  3165. begin
  3166. Buf := RecvBufferStr(4, FSocksTimeout);
  3167. if FLastError <> 0 then
  3168. Exit;
  3169. if Buf[1] <> #5 then
  3170. Exit;
  3171. case Ord(Buf[4]) of
  3172. 1:
  3173. s := RecvBufferStr(4, FSocksTimeout);
  3174. 3:
  3175. begin
  3176. x := RecvByte(FSocksTimeout);
  3177. if FLastError <> 0 then
  3178. Exit;
  3179. s := Char(x) + RecvBufferStr(x, FSocksTimeout);
  3180. end;
  3181. 4:
  3182. s := RecvBufferStr(16, FSocksTimeout);
  3183. else
  3184. Exit;
  3185. end;
  3186. Buf := Buf + s + RecvBufferStr(2, FSocksTimeout);
  3187. if FLastError <> 0 then
  3188. Exit;
  3189. FSocksLastError := Ord(Buf[2]);
  3190. end;
  3191. //---
  3192. if ((FSocksLastError <> 0) and (FSocksLastError <> $5A{90})) then
  3193. begin
  3194. case FSocksLastError of // http://en.wikipedia.org/wiki/SOCKS
  3195. // v4
  3196. $5a: m := 'request granted';
  3197. $5b: m := 'request rejected or failed';
  3198. $5c: m := 'request failed because client is not running identd (or not reachable from the server)';
  3199. $5d: m := 'request failed because client''s identd could not confirm the user ID string in the request';
  3200. // v5'
  3201. $00: m := 'request grant`ed';
  3202. $01: m := 'general failure';
  3203. $02: m := 'connection not allowed by ruleset';
  3204. $03: m := 'network unreachable';
  3205. $04: m := 'host unreachable';
  3206. $05: m := 'connection refused by destination host';
  3207. $06: m := 'TTL expired';
  3208. $07: m := 'command not supported / protocol error';
  3209. $08: m := 'address type not supported';
  3210. else
  3211. m := '';
  3212. end;
  3213. z := SysUtils.Format('Error 0x%x', [FSocksLastError]);
  3214. if m<>'' then
  3215. z := z + ' ' + m;
  3216. Exit;
  3217. end;
  3218. SocksDecode(Buf);
  3219. Result := True;
  3220. finally
  3221. FBypassFlag := False;
  3222. end;
  3223. end;
  3224. function TSocksBlockSocket.SocksCode(IP: string; const Port: string): string;
  3225. var
  3226. ip6: TIp6Bytes;
  3227. n: integer;
  3228. begin
  3229. if FSocksType <> ST_Socks5 then
  3230. begin
  3231. Result := CodeInt(ResolvePort(Port));
  3232. if not FSocksResolver then
  3233. IP := ResolveName(IP);
  3234. if IsIP(IP) then
  3235. begin
  3236. Result := Result + IPToID(IP);
  3237. Result := Result + FSocksUsername + #0;
  3238. end
  3239. else
  3240. begin
  3241. Result := Result + IPToID('0.0.0.1');
  3242. Result := Result + FSocksUsername + #0;
  3243. Result := Result + IP + #0;
  3244. end;
  3245. end
  3246. else
  3247. begin
  3248. if not FSocksResolver then
  3249. IP := ResolveName(IP);
  3250. if IsIP(IP) then
  3251. Result := #1 + IPToID(IP)
  3252. else
  3253. if IsIP6(IP) then
  3254. begin
  3255. ip6 := StrToIP6(IP);
  3256. Result := #4;
  3257. for n := 0 to 15 do
  3258. Result := Result + Char(ip6[n]);
  3259. end
  3260. else
  3261. Result := #3 + Char(Length(IP)) + IP;
  3262. Result := Result + CodeInt(ResolvePort(Port));
  3263. end;
  3264. end;
  3265. function TSocksBlockSocket.SocksDecode(const Value: string): integer;
  3266. var
  3267. Atyp: Byte;
  3268. y, n: integer;
  3269. w: Word;
  3270. ip6: TIp6Bytes;
  3271. begin
  3272. FSocksResponsePort := '0';
  3273. Result := 0;
  3274. if FSocksType <> ST_Socks5 then
  3275. begin
  3276. if Length(Value) < 8 then
  3277. Exit;
  3278. Result := 3;
  3279. w := DecodeInt(Value, Result);
  3280. FSocksResponsePort := IntToStr(w);
  3281. FSocksResponseIP := Format('%d.%d.%d.%d',
  3282. [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  3283. Result := 9;
  3284. end
  3285. else
  3286. begin
  3287. if Length(Value) < 4 then
  3288. Exit;
  3289. Atyp := Ord(Value[4]);
  3290. Result := 5;
  3291. case Atyp of
  3292. 1:
  3293. begin
  3294. if Length(Value) < 10 then
  3295. Exit;
  3296. FSocksResponseIP := Format('%d.%d.%d.%d',
  3297. [Ord(Value[5]), Ord(Value[6]), Ord(Value[7]), Ord(Value[8])]);
  3298. Result := 9;
  3299. end;
  3300. 3:
  3301. begin
  3302. y := Ord(Value[5]);
  3303. if Length(Value) < (5 + y + 2) then
  3304. Exit;
  3305. for n := 6 to 6 + y - 1 do
  3306. FSocksResponseIP := FSocksResponseIP + Value[n];
  3307. Result := 5 + y + 1;
  3308. end;
  3309. 4:
  3310. begin
  3311. if Length(Value) < 22 then
  3312. Exit;
  3313. for n := 0 to 15 do
  3314. ip6[n] := ord(Value[n + 5]);
  3315. FSocksResponseIP := IP6ToStr(ip6);
  3316. Result := 21;
  3317. end;
  3318. else
  3319. Exit;
  3320. end;
  3321. w := DecodeInt(Value, Result);
  3322. FSocksResponsePort := IntToStr(w);
  3323. Result := Result + 2;
  3324. end;
  3325. end;
  3326. {======================================================================}
  3327. procedure TDgramBlockSocket.Connect(const IP, Port: string);
  3328. begin
  3329. SetRemoteSin(IP, Port);
  3330. InternalCreateSocket(FRemoteSin);
  3331. if UseConnect then
  3332. begin
  3333. SockCheck(synsock.Connect(FSocket, FRemoteSin));
  3334. if FLastError = 0 then
  3335. GetSins;
  3336. end;
  3337. FBuffer := '';
  3338. DoStatus(HR_Connect, IP + ':' + Port);
  3339. end;
  3340. function TDgramBlockSocket.RecvBuffer(Buffer: TMemory; Length: Integer): Integer;
  3341. begin
  3342. Result := RecvBufferFrom(Buffer, Length);
  3343. end;
  3344. function TDgramBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  3345. begin
  3346. Result := SendBufferTo(Buffer, Length);
  3347. end;
  3348. {======================================================================}
  3349. destructor TUDPBlockSocket.Destroy;
  3350. begin
  3351. if Assigned(FSocksControlSock) then
  3352. FreeAndNil(FSocksControlSock);
  3353. inherited;
  3354. end;
  3355. procedure TUDPBlockSocket.EnableBroadcast(Value: Boolean);
  3356. var
  3357. d: TSynaOption;
  3358. begin
  3359. //d := TSynaOption.Create;
  3360. d.Option := SOT_Broadcast;
  3361. d.Enabled := Value;
  3362. DelayedOption(d);
  3363. end;
  3364. function TUDPBlockSocket.UdpAssociation: Boolean;
  3365. var
  3366. b: Boolean;
  3367. begin
  3368. Result := True;
  3369. FUsingSocks := False;
  3370. if FSocksIP <> '' then
  3371. begin
  3372. Result := False;
  3373. if not Assigned(FSocksControlSock) then
  3374. FSocksControlSock := TTCPBlockSocket.Create;
  3375. FSocksControlSock.CloseSocket;
  3376. FSocksControlSock.CreateSocketByName(FSocksIP);
  3377. FSocksControlSock.Connect(FSocksIP, FSocksPort);
  3378. if FSocksControlSock.LastError <> 0 then
  3379. Exit;
  3380. // if not assigned local port, assign it!
  3381. if not FBinded then
  3382. Bind(cAnyHost, cAnyPort);
  3383. //open control TCP connection to SOCKS
  3384. FSocksControlSock.FSocksUsername := FSocksUsername;
  3385. FSocksControlSock.FSocksPassword := FSocksPassword;
  3386. b := FSocksControlSock.SocksOpen;
  3387. if b then
  3388. b := FSocksControlSock.SocksRequest(3, GetLocalSinIP, IntToStr(GetLocalSinPort));
  3389. if b then
  3390. b := FSocksControlSock.SocksResponse;
  3391. if not b and (FLastError = 0) then
  3392. FLastError := WSANO_RECOVERY;
  3393. FUsingSocks :=FSocksControlSock.UsingSocks;
  3394. FSocksRemoteIP := FSocksControlSock.FSocksResponseIP;
  3395. FSocksRemotePort := FSocksControlSock.FSocksResponsePort;
  3396. Result := b and (FLastError = 0);
  3397. end;
  3398. end;
  3399. function TUDPBlockSocket.SendBufferTo(const Buffer: TMemory; Length: Integer): Integer;
  3400. var
  3401. SIp: string;
  3402. SPort: integer;
  3403. Buf: string;
  3404. begin
  3405. Result := 0;
  3406. FUsingSocks := False;
  3407. if (FSocksIP <> '') and (not UdpAssociation) then
  3408. FLastError := WSANO_RECOVERY
  3409. else
  3410. begin
  3411. if FUsingSocks then
  3412. begin
  3413. {$IFNDEF CIL}
  3414. Sip := GetRemoteSinIp;
  3415. SPort := GetRemoteSinPort;
  3416. SetRemoteSin(FSocksRemoteIP, FSocksRemotePort);
  3417. SetLength(Buf,Length);
  3418. Move(Buffer^, Pointer(Buf)^, Length);
  3419. Buf := #0 + #0 + #0 + SocksCode(Sip, IntToStr(SPort)) + Buf;
  3420. Result := inherited SendBufferTo(Pointer(Buf), buf.Length);
  3421. SetRemoteSin(Sip, IntToStr(SPort));
  3422. {$ENDIF}
  3423. end
  3424. else
  3425. Result := inherited SendBufferTo(Buffer, Length);
  3426. end;
  3427. end;
  3428. function TUDPBlockSocket.RecvBufferFrom(Buffer: TMemory; Length: Integer): Integer;
  3429. var
  3430. Buf: string;
  3431. x: integer;
  3432. begin
  3433. Result := inherited RecvBufferFrom(Buffer, Length);
  3434. if FUsingSocks then
  3435. begin
  3436. {$IFNDEF CIL}
  3437. SetLength(Buf, Result);
  3438. Move(Buffer^, Pointer(Buf)^, Result);
  3439. x := SocksDecode(Buf);
  3440. Result := Result - x + 1;
  3441. Buf := Copy(Buf, x, Result);
  3442. Move(Pointer(Buf)^, Buffer^, Result);
  3443. SetRemoteSin(FSocksResponseIP, FSocksResponsePort);
  3444. {$ENDIF}
  3445. end;
  3446. end;
  3447. {$IFNDEF CIL}
  3448. procedure TUDPBlockSocket.AddMulticast(const MCastIP: string);
  3449. var
  3450. Multicast: TIP_mreq;
  3451. Multicast6: TIPv6_mreq;
  3452. n: integer;
  3453. ip6: Tip6bytes;
  3454. begin
  3455. if FIP6Used then
  3456. begin
  3457. ip6 := StrToIp6(MCastIP);
  3458. for n := 0 to 15 do
  3459. Multicast6.ipv6mr_multiaddr.{$IFDEF POSIX}s6_addr{$ELSE}u6_addr8{$ENDIF}[n] := Ip6[n];
  3460. Multicast6.ipv6mr_interface := 0;
  3461. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  3462. Pointer(@Multicast6), SizeOf(Multicast6)));
  3463. end
  3464. else
  3465. begin
  3466. Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
  3467. // Multicast.imr_interface.S_addr := INADDR_ANY;
  3468. Multicast.imr_interface.S_addr := FLocalSin.sin_addr.S_addr;
  3469. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  3470. Pointer(@Multicast), SizeOf(Multicast)));
  3471. end;
  3472. ExceptCheck;
  3473. end;
  3474. procedure TUDPBlockSocket.DropMulticast(const MCastIP: string);
  3475. var
  3476. Multicast: TIP_mreq;
  3477. Multicast6: TIPv6_mreq;
  3478. n: integer;
  3479. ip6: Tip6bytes;
  3480. begin
  3481. if FIP6Used then
  3482. begin
  3483. ip6 := StrToIp6(MCastIP);
  3484. for n := 0 to 15 do
  3485. Multicast6.ipv6mr_multiaddr.{$IFDEF POSIX}s6_addr{$ELSE}u6_addr8{$ENDIF}[n] := Ip6[n];
  3486. Multicast6.ipv6mr_interface := 0;
  3487. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  3488. Pointer(@Multicast6), SizeOf(Multicast6)));
  3489. end
  3490. else
  3491. begin
  3492. Multicast.imr_multiaddr.S_addr := swapbytes(strtoip(MCastIP));
  3493. // Multicast.imr_interface.S_addr := INADDR_ANY;
  3494. Multicast.imr_interface.S_addr := FLocalSin.sin_addr.S_addr;
  3495. SockCheck(synsock.SetSockOpt(FSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
  3496. Pointer(@Multicast), SizeOf(Multicast)));
  3497. end;
  3498. ExceptCheck;
  3499. end;
  3500. {$ENDIF}
  3501. procedure TUDPBlockSocket.SetMulticastTTL(TTL: integer);
  3502. var
  3503. d: TSynaOption;
  3504. begin
  3505. //d := TSynaOption.Create;
  3506. d.Option := SOT_MulticastTTL;
  3507. d.Value := TTL;
  3508. DelayedOption(d);
  3509. end;
  3510. function TUDPBlockSocket.GetMulticastTTL:integer;
  3511. var
  3512. l: Integer;
  3513. begin
  3514. {$IFNDEF CIL}
  3515. l := SizeOf(Result);
  3516. if FIP6Used then
  3517. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, @Result, l))
  3518. else
  3519. SockCheck(synsock.GetSockOpt(FSocket, IPPROTO_IP, IP_MULTICAST_TTL, @Result, l));
  3520. ExceptCheck;
  3521. {$ENDIF}
  3522. end;
  3523. procedure TUDPBlockSocket.EnableMulticastLoop(Value: Boolean);
  3524. var
  3525. d: TSynaOption;
  3526. begin
  3527. //d := TSynaOption.Create;
  3528. d.Option := SOT_MulticastLoop;
  3529. d.Enabled := Value;
  3530. DelayedOption(d);
  3531. end;
  3532. function TUDPBlockSocket.GetSocketType: integer;
  3533. begin
  3534. Result := integer(SOCK_DGRAM);
  3535. end;
  3536. function TUDPBlockSocket.GetSocketProtocol: integer;
  3537. begin
  3538. Result := integer(IPPROTO_UDP);
  3539. end;
  3540. {======================================================================}
  3541. constructor TTCPBlockSocket.CreateWithSSL(SSLPlugin: TSSLClass);
  3542. begin
  3543. inherited Create;
  3544. FSSL := SSLPlugin.Create(self);
  3545. FHTTPTunnelIP := '';
  3546. FHTTPTunnelPort := '';
  3547. FHTTPTunnel := False;
  3548. FHTTPTunnelRemoteIP := '';
  3549. FHTTPTunnelRemotePort := '';
  3550. FHTTPTunnelUser := '';
  3551. FHTTPTunnelPass := '';
  3552. FHTTPTunnelTimeout := 30000;
  3553. end;
  3554. constructor TTCPBlockSocket.Create;
  3555. begin
  3556. CreateWithSSL(SSLImplementation);
  3557. end;
  3558. destructor TTCPBlockSocket.Destroy;
  3559. begin
  3560. inherited Destroy;
  3561. FreeAndNil(FSSL);
  3562. end;
  3563. function TTCPBlockSocket.GetErrorDescEx: string;
  3564. begin
  3565. Result := inherited GetErrorDescEx;
  3566. if (FLastError = WSASYSNOTREADY) and (self.SSL.LastError <> 0) then
  3567. begin
  3568. Result := self.SSL.LastErrorDesc;
  3569. end;
  3570. end;
  3571. const
  3572. SHUT_RDWR = 2;
  3573. procedure TTCPBlockSocket.CloseSocket;
  3574. begin
  3575. if FSSL.SSLEnabled then
  3576. FSSL.Shutdown;
  3577. if (FSocket <> INVALID_SOCKET) and (FLastError = 0) then
  3578. begin
  3579. SockCheck(Synsock.Shutdown(FSocket, SHUT_RDWR));
  3580. //ExceptCheck;
  3581. Purge;
  3582. SetLinger(True, 0);
  3583. end;
  3584. inherited CloseSocket;
  3585. end;
  3586. procedure TTCPBlockSocket.DoAfterConnect;
  3587. begin
  3588. if Assigned(OnAfterConnect) then
  3589. begin
  3590. OnAfterConnect(Self);
  3591. end;
  3592. end;
  3593. function TTCPBlockSocket.WaitingData: Integer;
  3594. begin
  3595. Result := 0;
  3596. if FSSL.SSLEnabled and (FSocket <> INVALID_SOCKET) then
  3597. Result := FSSL.WaitingData;
  3598. if Result = 0 then
  3599. Result := inherited WaitingData;
  3600. end;
  3601. procedure TTCPBlockSocket.Listen;
  3602. var
  3603. b: Boolean;
  3604. Sip,SPort: string;
  3605. begin
  3606. if FSocksIP = '' then
  3607. begin
  3608. inherited Listen;
  3609. end
  3610. else
  3611. begin
  3612. Sip := GetLocalSinIP;
  3613. if Sip = cAnyHost then
  3614. Sip := LocalName;
  3615. SPort := IntToStr(GetLocalSinPort);
  3616. inherited Connect(FSocksIP, FSocksPort);
  3617. b := SocksOpen;
  3618. if b then
  3619. b := SocksRequest(2, Sip, SPort);
  3620. if b then
  3621. b := SocksResponse;
  3622. if not b and (FLastError = 0) then
  3623. FLastError := WSANO_RECOVERY;
  3624. FSocksLocalIP := FSocksResponseIP;
  3625. if FSocksLocalIP = cAnyHost then
  3626. FSocksLocalIP := FSocksIP;
  3627. FSocksLocalPort := FSocksResponsePort;
  3628. FSocksRemoteIP := '';
  3629. FSocksRemotePort := '';
  3630. ExceptCheck;
  3631. DoStatus(HR_Listen, '');
  3632. end;
  3633. end;
  3634. function TTCPBlockSocket.Accept: TSocket;
  3635. begin
  3636. if FUsingSocks then
  3637. begin
  3638. if not SocksResponse and (FLastError = 0) then
  3639. FLastError := WSANO_RECOVERY;
  3640. FSocksRemoteIP := FSocksResponseIP;
  3641. FSocksRemotePort := FSocksResponsePort;
  3642. Result := FSocket;
  3643. ExceptCheck;
  3644. DoStatus(HR_Accept, '');
  3645. end
  3646. else
  3647. begin
  3648. result := inherited Accept;
  3649. end;
  3650. end;
  3651. procedure TTCPBlockSocket.Connect(const IP, Port: string);
  3652. begin
  3653. FDisconnected := False;
  3654. if FSocksIP <> '' then
  3655. SocksDoConnect(IP, Port)
  3656. else
  3657. if FHTTPTunnelIP <> '' then
  3658. HTTPTunnelDoConnect(IP, Port)
  3659. else
  3660. inherited Connect(IP, Port);
  3661. if FLasterror = 0 then
  3662. DoAfterConnect;
  3663. end;
  3664. function TTCPBlockSocket.Connected: boolean;
  3665. begin
  3666. Result := (FSocket <> INVALID_SOCKET) and not FDisconnected;
  3667. {$IFNDEF UNIX}
  3668. if Result then
  3669. begin
  3670. CanRead(0);
  3671. Result := not FDisconnected;
  3672. end;
  3673. {$ENDIF}
  3674. end;
  3675. procedure TTCPBlockSocket.SocksDoConnect(const IP, Port: string);
  3676. var
  3677. b: Boolean;
  3678. begin
  3679. inherited Connect(FSocksIP, FSocksPort);
  3680. if FLastError = 0 then
  3681. begin
  3682. b := SocksOpen;
  3683. if b then
  3684. b := SocksRequest(1, IP, Port);
  3685. if b then
  3686. b := SocksResponse;
  3687. if not b and (FLastError = 0) then
  3688. FLastError := WSASYSNOTREADY;
  3689. FSocksLocalIP := FSocksResponseIP;
  3690. FSocksLocalPort := FSocksResponsePort;
  3691. FSocksRemoteIP := IP;
  3692. FSocksRemotePort := Port;
  3693. end;
  3694. ExceptCheck;
  3695. DoStatus(HR_Connect, IP + ':' + Port);
  3696. end;
  3697. procedure TTCPBlockSocket.HTTPTunnelDoConnect(IP, Port: string);
  3698. //bugfixed by Mike Green ([email protected])
  3699. var
  3700. s: string;
  3701. begin
  3702. Port := IntToStr(ResolvePort(Port));
  3703. inherited Connect(FHTTPTunnelIP, FHTTPTunnelPort);
  3704. if FLastError <> 0 then
  3705. Exit;
  3706. FHTTPTunnel := False;
  3707. if IsIP6(IP) then
  3708. IP := '[' + IP + ']';
  3709. SendString('CONNECT ' + IP + ':' + Port + ' HTTP/1.0' + CRLF);
  3710. if FHTTPTunnelUser <> '' then
  3711. Sendstring('Proxy-Authorization: Basic ' +
  3712. EncodeBase64(FHTTPTunnelUser + ':' + FHTTPTunnelPass) + CRLF);
  3713. SendString(CRLF);
  3714. repeat
  3715. s := RecvTerminated(FHTTPTunnelTimeout, #$0a);
  3716. if FLastError <> 0 then
  3717. Break;
  3718. if (Pos('HTTP/', s) = 1) and (Length(s) > 11) then
  3719. FHTTPTunnel := s[10] = '2';
  3720. until (s = '') or (s = #$0d);
  3721. if (FLasterror = 0) and not FHTTPTunnel then
  3722. FLastError := WSAECONNREFUSED;
  3723. FHTTPTunnelRemoteIP := IP;
  3724. FHTTPTunnelRemotePort := Port;
  3725. ExceptCheck;
  3726. end;
  3727. procedure TTCPBlockSocket.SSLDoConnect;
  3728. begin
  3729. ResetLastError;
  3730. if not FSSL.Connect then
  3731. FLastError := WSASYSNOTREADY;
  3732. ExceptCheck;
  3733. end;
  3734. procedure TTCPBlockSocket.SSLDoShutdown;
  3735. begin
  3736. ResetLastError;
  3737. FSSL.BiShutdown;
  3738. end;
  3739. function TTCPBlockSocket.GetLocalSinIP: string;
  3740. begin
  3741. if FUsingSocks then
  3742. Result := FSocksLocalIP
  3743. else
  3744. Result := inherited GetLocalSinIP;
  3745. end;
  3746. function TTCPBlockSocket.GetRemoteSinIP: string;
  3747. begin
  3748. if FUsingSocks then
  3749. Result := FSocksRemoteIP
  3750. else
  3751. if FHTTPTunnel then
  3752. Result := FHTTPTunnelRemoteIP
  3753. else
  3754. Result := inherited GetRemoteSinIP;
  3755. end;
  3756. function TTCPBlockSocket.GetLocalSinPort: Integer;
  3757. begin
  3758. if FUsingSocks then
  3759. Result := StrToIntDef(FSocksLocalPort, 0)
  3760. else
  3761. Result := inherited GetLocalSinPort;
  3762. end;
  3763. function TTCPBlockSocket.GetRemoteSinPort: Integer;
  3764. begin
  3765. if FUsingSocks then
  3766. Result := ResolvePort(FSocksRemotePort)
  3767. else
  3768. if FHTTPTunnel then
  3769. Result := StrToIntDef(FHTTPTunnelRemotePort, 0)
  3770. else
  3771. Result := inherited GetRemoteSinPort;
  3772. end;
  3773. function TTCPBlockSocket.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  3774. begin
  3775. if FSSL.SSLEnabled then
  3776. begin
  3777. Result := 0;
  3778. if TestStopFlag then
  3779. Exit;
  3780. ResetLastError;
  3781. LimitBandwidth(Len, FMaxRecvBandwidth, FNextRecv);
  3782. Result := FSSL.RecvBuffer(Buffer, Len);
  3783. if FSSL.LastError <> 0 then
  3784. FLastError := WSASYSNOTREADY;
  3785. ExceptCheck;
  3786. Inc(FRecvCounter, Result);
  3787. DoStatus(HR_ReadCount, IntToStr(Result));
  3788. DoMonitor(False, Buffer, Result);
  3789. DoReadFilter(Buffer, Result);
  3790. end
  3791. else
  3792. Result := inherited RecvBuffer(Buffer, Len);
  3793. end;
  3794. function TTCPBlockSocket.SendBuffer(const Buffer: TMemory; Length: Integer): Integer;
  3795. var
  3796. x, y: integer;
  3797. l, r: integer;
  3798. {$IFNDEF CIL}
  3799. p: Pointer;
  3800. {$ENDIF}
  3801. begin
  3802. if FSSL.SSLEnabled then
  3803. begin
  3804. Result := 0;
  3805. if TestStopFlag then
  3806. Exit;
  3807. ResetLastError;
  3808. DoMonitor(True, Buffer, Length);
  3809. {$IFDEF CIL}
  3810. Result := FSSL.SendBuffer(Buffer, Length);
  3811. if FSSL.LastError <> 0 then
  3812. FLastError := WSASYSNOTREADY;
  3813. Inc(FSendCounter, Result);
  3814. DoStatus(HR_WriteCount, IntToStr(Result));
  3815. {$ELSE}
  3816. l := Length;
  3817. x := 0;
  3818. while x < l do
  3819. begin
  3820. y := l - x;
  3821. if y > FSendMaxChunk then
  3822. y := FSendMaxChunk;
  3823. if y > 0 then
  3824. begin
  3825. LimitBandwidth(y, FMaxSendBandwidth, FNextsend);
  3826. p := IncPoint(Buffer, x);
  3827. r := FSSL.SendBuffer(p, y);
  3828. if FSSL.LastError <> 0 then
  3829. FLastError := WSASYSNOTREADY;
  3830. if Flasterror <> 0 then
  3831. Break;
  3832. Inc(x, r);
  3833. Inc(Result, r);
  3834. Inc(FSendCounter, r);
  3835. DoStatus(HR_WriteCount, IntToStr(r));
  3836. end
  3837. else
  3838. break;
  3839. end;
  3840. {$ENDIF}
  3841. ExceptCheck;
  3842. end
  3843. else
  3844. Result := inherited SendBuffer(Buffer, Length);
  3845. end;
  3846. function TTCPBlockSocket.SSLAcceptConnection: Boolean;
  3847. begin
  3848. ResetLastError;
  3849. if not FSSL.Accept then
  3850. FLastError := WSASYSNOTREADY;
  3851. ExceptCheck;
  3852. Result := FLastError = 0;
  3853. end;
  3854. function TTCPBlockSocket.GetSocketType: integer;
  3855. begin
  3856. Result := integer(SOCK_STREAM);
  3857. end;
  3858. function TTCPBlockSocket.GetSocketProtocol: integer;
  3859. begin
  3860. Result := integer(IPPROTO_TCP);
  3861. end;
  3862. {======================================================================}
  3863. function TICMPBlockSocket.GetSocketType: integer;
  3864. begin
  3865. Result := integer(SOCK_RAW);
  3866. end;
  3867. function TICMPBlockSocket.GetSocketProtocol: integer;
  3868. begin
  3869. if FIP6Used then
  3870. Result := integer(IPPROTO_ICMPV6)
  3871. else
  3872. Result := integer(IPPROTO_ICMP);
  3873. end;
  3874. {======================================================================}
  3875. function TRAWBlockSocket.GetSocketType: integer;
  3876. begin
  3877. Result := integer(SOCK_RAW);
  3878. end;
  3879. function TRAWBlockSocket.GetSocketProtocol: integer;
  3880. begin
  3881. Result := integer(IPPROTO_RAW);
  3882. end;
  3883. {======================================================================}
  3884. function TPGMmessageBlockSocket.GetSocketType: integer;
  3885. begin
  3886. Result := integer(SOCK_RDM);
  3887. end;
  3888. function TPGMmessageBlockSocket.GetSocketProtocol: integer;
  3889. begin
  3890. Result := integer(IPPROTO_RM);
  3891. end;
  3892. {======================================================================}
  3893. function TPGMstreamBlockSocket.GetSocketType: integer;
  3894. begin
  3895. Result := integer(SOCK_STREAM);
  3896. end;
  3897. function TPGMstreamBlockSocket.GetSocketProtocol: integer;
  3898. begin
  3899. Result := integer(IPPROTO_RM);
  3900. end;
  3901. {======================================================================}
  3902. constructor TSynaClient.Create;
  3903. begin
  3904. inherited Create;
  3905. FIPInterface := cAnyHost;
  3906. FTargetHost := cLocalhost;
  3907. FTargetPort := cAnyPort;
  3908. FTimeout := 5000;
  3909. FUsername := '';
  3910. FPassword := '';
  3911. end;
  3912. {======================================================================}
  3913. constructor TCustomSSL.Create(const Value: TTCPBlockSocket);
  3914. begin
  3915. inherited Create;
  3916. FSocket := Value;
  3917. FSSLEnabled := False;
  3918. FUsername := '';
  3919. FPassword := '';
  3920. FLastError := 0;
  3921. FLastErrorDesc := '';
  3922. FVerifyCert := False;
  3923. FSSLType := LT_all;
  3924. FKeyPassword := '';
  3925. FCiphers := '';
  3926. FCertificateFile := '';
  3927. FPrivateKeyFile := '';
  3928. FCertCAFile := '';
  3929. FCertCA := '';
  3930. FTrustCertificate := '';
  3931. FTrustCertificateFile := '';
  3932. FCertificate := '';
  3933. FPrivateKey := '';
  3934. FPFX := '';
  3935. FPFXfile := '';
  3936. FSSHChannelType := '';
  3937. FSSHChannelArg1 := '';
  3938. FSSHChannelArg2 := '';
  3939. FCertComplianceLevel := -1; //default
  3940. FSNIHost := '';
  3941. end;
  3942. procedure TCustomSSL.Assign(const Value: TCustomSSL);
  3943. begin
  3944. FUsername := Value.Username;
  3945. FPassword := Value.Password;
  3946. FVerifyCert := Value.VerifyCert;
  3947. FSSLType := Value.SSLType;
  3948. FKeyPassword := Value.KeyPassword;
  3949. FCiphers := Value.Ciphers;
  3950. FCertificateFile := Value.CertificateFile;
  3951. FPrivateKeyFile := Value.PrivateKeyFile;
  3952. FCertCAFile := Value.CertCAFile;
  3953. FCertCA := Value.CertCA;
  3954. FTrustCertificate := Value.TrustCertificate;
  3955. FTrustCertificateFile := Value.TrustCertificateFile;
  3956. FCertificate := Value.Certificate;
  3957. FPrivateKey := Value.PrivateKey;
  3958. FPFX := Value.PFX;
  3959. FPFXfile := Value.PFXfile;
  3960. FCertComplianceLevel := Value.CertComplianceLevel;
  3961. FSNIHost := Value.FSNIHost;
  3962. end;
  3963. procedure TCustomSSL.ReturnError;
  3964. begin
  3965. FLastError := -1;
  3966. FLastErrorDesc := 'SSL/TLS support is not compiled!';
  3967. end;
  3968. function TCustomSSL.LibVersion: string;
  3969. begin
  3970. Result := '';
  3971. end;
  3972. function TCustomSSL.LibName: string;
  3973. begin
  3974. Result := '';
  3975. end;
  3976. function TCustomSSL.CreateSelfSignedCert(Host: string): Boolean;
  3977. begin
  3978. Result := False;
  3979. end;
  3980. function TCustomSSL.Connect: boolean;
  3981. begin
  3982. ReturnError;
  3983. Result := False;
  3984. end;
  3985. function TCustomSSL.Accept: boolean;
  3986. begin
  3987. ReturnError;
  3988. Result := False;
  3989. end;
  3990. function TCustomSSL.Shutdown: boolean;
  3991. begin
  3992. ReturnError;
  3993. Result := False;
  3994. end;
  3995. function TCustomSSL.BiShutdown: boolean;
  3996. begin
  3997. ReturnError;
  3998. Result := False;
  3999. end;
  4000. function TCustomSSL.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
  4001. begin
  4002. ReturnError;
  4003. Result := integer(SOCKET_ERROR);
  4004. end;
  4005. procedure TCustomSSL.SetCertCAFile(const Value: string);
  4006. begin
  4007. FCertCAFile := Value;
  4008. end;
  4009. function TCustomSSL.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
  4010. begin
  4011. ReturnError;
  4012. Result := integer(SOCKET_ERROR);
  4013. end;
  4014. function TCustomSSL.WaitingData: Integer;
  4015. begin
  4016. ReturnError;
  4017. Result := 0;
  4018. end;
  4019. function TCustomSSL.GetSSLVersion: string;
  4020. begin
  4021. Result := '';
  4022. end;
  4023. function TCustomSSL.GetPeerSubject: string;
  4024. begin
  4025. Result := '';
  4026. end;
  4027. function TCustomSSL.GetPeerSerialNo: integer;
  4028. begin
  4029. Result := -1;
  4030. end;
  4031. function TCustomSSL.GetPeerName: string;
  4032. begin
  4033. Result := '';
  4034. end;
  4035. function TCustomSSL.GetPeerNameHash: cardinal;
  4036. begin
  4037. Result := 0;
  4038. end;
  4039. function TCustomSSL.GetPeerIssuer: string;
  4040. begin
  4041. Result := '';
  4042. end;
  4043. function TCustomSSL.GetPeerFingerprint: string;
  4044. begin
  4045. Result := '';
  4046. end;
  4047. function TCustomSSL.GetCertInfo: string;
  4048. begin
  4049. Result := '';
  4050. end;
  4051. function TCustomSSL.GetCipherName: string;
  4052. begin
  4053. Result := '';
  4054. end;
  4055. function TCustomSSL.GetCipherBits: integer;
  4056. begin
  4057. Result := 0;
  4058. end;
  4059. function TCustomSSL.GetCipherAlgBits: integer;
  4060. begin
  4061. Result := 0;
  4062. end;
  4063. function TCustomSSL.GetVerifyCert: integer;
  4064. begin
  4065. Result := 1;
  4066. end;
  4067. function TCustomSSL.DoVerifyCert:boolean;
  4068. begin
  4069. if assigned(OnVerifyCert) then
  4070. begin
  4071. result:=OnVerifyCert(Self);
  4072. end
  4073. else
  4074. result:=true;
  4075. end;
  4076. {======================================================================}
  4077. function TSSLNone.LibVersion: string;
  4078. begin
  4079. Result := 'Without SSL support';
  4080. end;
  4081. function TSSLNone.LibName: string;
  4082. begin
  4083. Result := 'ssl_none';
  4084. end;
  4085. {======================================================================}
  4086. initialization
  4087. begin
  4088. {$IFDEF ONCEWINSOCK}
  4089. if not InitSocketInterface(DLLStackName) then
  4090. begin
  4091. e := ESynapseError.Create('Error loading Socket interface (' + DLLStackName + ')!');
  4092. e.ErrorCode := 0;
  4093. e.ErrorMessage := 'Error loading Socket interface (' + DLLStackName + ')!';
  4094. raise e;
  4095. end;
  4096. synsock.WSAStartup(WinsockLevel, WsaDataOnce);
  4097. {$ENDIF}
  4098. end;
  4099. finalization
  4100. begin
  4101. {$IFDEF ONCEWINSOCK}
  4102. synsock.WSACleanup;
  4103. DestroySocketInterface;
  4104. {$ENDIF}
  4105. end;
  4106. end.