Socket.cs 105 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500
  1. // System.Net.Sockets.Socket.cs
  2. //
  3. // Authors:
  4. // Phillip Pearson ([email protected])
  5. // Dick Porter <[email protected]>
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Sridhar Kulkarni ([email protected])
  8. // Brian Nickel ([email protected])
  9. // Ludovic Henry ([email protected])
  10. //
  11. // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  12. // http://www.myelin.co.nz
  13. // (c) 2004-2011 Novell, Inc. (http://www.novell.com)
  14. //
  15. //
  16. // Permission is hereby granted, free of charge, to any person obtaining
  17. // a copy of this software and associated documentation files (the
  18. // "Software"), to deal in the Software without restriction, including
  19. // without limitation the rights to use, copy, modify, merge, publish,
  20. // distribute, sublicense, and/or sell copies of the Software, and to
  21. // permit persons to whom the Software is furnished to do so, subject to
  22. // the following conditions:
  23. //
  24. // The above copyright notice and this permission notice shall be
  25. // included in all copies or substantial portions of the Software.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  28. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  29. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  30. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  31. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  32. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  33. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34. //
  35. using System;
  36. using System.Net;
  37. using System.Collections;
  38. using System.Collections.Generic;
  39. using System.Runtime.CompilerServices;
  40. using System.Runtime.InteropServices;
  41. using System.Threading;
  42. using System.Reflection;
  43. using System.IO;
  44. using System.Net.Configuration;
  45. using System.Text;
  46. using System.Timers;
  47. using System.Net.NetworkInformation;
  48. namespace System.Net.Sockets
  49. {
  50. public partial class Socket : IDisposable
  51. {
  52. const int SOCKET_CLOSED_CODE = 10004;
  53. const string TIMEOUT_EXCEPTION_MSG = "A connection attempt failed because the connected party did not properly respond" +
  54. "after a period of time, or established connection failed because connected host has failed to respond";
  55. /*
  56. * These two fields are looked up by name by the runtime, don't change
  57. * their name without also updating the runtime code.
  58. */
  59. static int ipv4_supported = -1;
  60. static int ipv6_supported = -1;
  61. /* true if we called Close_internal */
  62. bool is_closed;
  63. bool is_listening;
  64. bool use_overlapped_io;
  65. int linger_timeout;
  66. AddressFamily address_family;
  67. SocketType socket_type;
  68. ProtocolType protocol_type;
  69. /* the field "safe_handle" is looked up by name by the runtime */
  70. internal SafeSocketHandle safe_handle;
  71. /*
  72. * This EndPoint is used when creating new endpoints. Because
  73. * there are many types of EndPoints possible,
  74. * seed_endpoint.Create(addr) is used for creating new ones.
  75. * As such, this value is set on Bind, SentTo, ReceiveFrom,
  76. * Connect, etc.
  77. */
  78. internal EndPoint seed_endpoint = null;
  79. internal Queue<KeyValuePair<IntPtr, IOSelectorJob>> readQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (2);
  80. internal Queue<KeyValuePair<IntPtr, IOSelectorJob>> writeQ = new Queue<KeyValuePair<IntPtr, IOSelectorJob>> (2);
  81. internal bool is_blocking = true;
  82. internal bool is_bound;
  83. /* When true, the socket was connected at the time of the last IO operation */
  84. internal bool is_connected;
  85. internal bool is_disposed;
  86. internal bool connect_in_progress;
  87. #region Constructors
  88. static Socket ()
  89. {
  90. if (ipv4_supported == -1) {
  91. try {
  92. Socket tmp = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  93. tmp.Close();
  94. ipv4_supported = 1;
  95. } catch {
  96. ipv4_supported = 0;
  97. }
  98. }
  99. if (ipv6_supported == -1) {
  100. // We need to put a try/catch around ConfigurationManager methods as will always throw an exception
  101. // when run in a mono embedded application. This occurs as embedded applications do not have a setup
  102. // for application config. The exception is not thrown when called from a normal .NET application.
  103. //
  104. // We, then, need to guard calls to the ConfigurationManager. If the config is not found or throws an
  105. // exception, will fall through to the existing Socket / API directly below in the code.
  106. //
  107. // Also note that catching ConfigurationErrorsException specifically would require library dependency
  108. // System.Configuration, and wanted to avoid that.
  109. #if !NET_2_1
  110. #if CONFIGURATION_DEP
  111. try {
  112. SettingsSection config;
  113. config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
  114. if (config != null)
  115. ipv6_supported = config.Ipv6.Enabled ? -1 : 0;
  116. } catch {
  117. ipv6_supported = -1;
  118. }
  119. #else
  120. try {
  121. NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
  122. if (config != null)
  123. ipv6_supported = config.ipv6Enabled ? -1 : 0;
  124. } catch {
  125. ipv6_supported = -1;
  126. }
  127. #endif
  128. #endif
  129. if (ipv6_supported != 0) {
  130. try {
  131. Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
  132. tmp.Close();
  133. ipv6_supported = 1;
  134. } catch {
  135. ipv6_supported = 0;
  136. }
  137. }
  138. }
  139. }
  140. //
  141. // This constructor is used by servers that want to listen for instance on both
  142. // ipv4 and ipv6. Mono has historically done that if you use InterNetworkV6 (at
  143. // least on Unix), because that is the default behavior unless the IPV6_V6ONLY
  144. // option is explicitly set by using setsockopt (sock, IPPROTO_IPV6, IPV6_ONLY)
  145. //
  146. public Socket (SocketType socketType, ProtocolType protocolType)
  147. : this (AddressFamily.InterNetworkV6, socketType, protocolType)
  148. {
  149. DualMode = true;
  150. }
  151. public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
  152. {
  153. #if NET_2_1 && !MOBILE
  154. switch (addressFamily) {
  155. case AddressFamily.InterNetwork: // ok
  156. case AddressFamily.InterNetworkV6: // ok
  157. case AddressFamily.Unknown: // SocketException will be thrown later (with right error #)
  158. break;
  159. // case AddressFamily.Unspecified:
  160. default:
  161. throw new ArgumentException ("addressFamily");
  162. }
  163. switch (socketType) {
  164. case SocketType.Stream: // ok
  165. case SocketType.Unknown: // SocketException will be thrown later (with right error #)
  166. break;
  167. default:
  168. throw new ArgumentException ("socketType");
  169. }
  170. switch (protocolType) {
  171. case ProtocolType.Tcp: // ok
  172. case ProtocolType.Unspecified: // ok
  173. case ProtocolType.Unknown: // SocketException will be thrown later (with right error #)
  174. break;
  175. default:
  176. throw new ArgumentException ("protocolType");
  177. }
  178. #endif
  179. this.address_family = addressFamily;
  180. this.socket_type = socketType;
  181. this.protocol_type = protocolType;
  182. int error;
  183. this.safe_handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
  184. if (error != 0)
  185. throw new SocketException (error);
  186. #if !NET_2_1 || MOBILE
  187. SocketDefaults ();
  188. #endif
  189. }
  190. #if !MOBILE
  191. public Socket (SocketInformation socketInformation)
  192. {
  193. this.is_listening = (socketInformation.Options & SocketInformationOptions.Listening) != 0;
  194. this.is_connected = (socketInformation.Options & SocketInformationOptions.Connected) != 0;
  195. this.is_blocking = (socketInformation.Options & SocketInformationOptions.NonBlocking) == 0;
  196. this.use_overlapped_io = (socketInformation.Options & SocketInformationOptions.UseOnlyOverlappedIO) != 0;
  197. var result = Mono.DataConverter.Unpack ("iiiil", socketInformation.ProtocolInformation, 0);
  198. this.address_family = (AddressFamily) (int) result [0];
  199. this.socket_type = (SocketType) (int) result [1];
  200. this.protocol_type = (ProtocolType) (int) result [2];
  201. this.is_bound = (ProtocolType) (int) result [3] != 0;
  202. this.safe_handle = new SafeSocketHandle ((IntPtr) (long) result [4], true);
  203. SocketDefaults ();
  204. }
  205. #endif
  206. /* private constructor used by Accept, which already has a socket handle to use */
  207. internal Socket(AddressFamily family, SocketType type, ProtocolType proto, SafeSocketHandle safe_handle)
  208. {
  209. this.address_family = family;
  210. this.socket_type = type;
  211. this.protocol_type = proto;
  212. this.safe_handle = safe_handle;
  213. this.is_connected = true;
  214. }
  215. ~Socket ()
  216. {
  217. Dispose (false);
  218. }
  219. void SocketDefaults ()
  220. {
  221. try {
  222. /* Need to test IPv6 further */
  223. if (address_family == AddressFamily.InterNetwork
  224. // || address_family == AddressFamily.InterNetworkV6
  225. ) {
  226. /* This is the default, but it probably has nasty side
  227. * effects on Linux, as the socket option is kludged by
  228. * turning on or off PMTU discovery... */
  229. this.DontFragment = false;
  230. }
  231. /* Microsoft sets these to 8192, but we are going to keep them
  232. * both to the OS defaults as these have a big performance impact.
  233. * on WebClient performance. */
  234. // this.ReceiveBufferSize = 8192;
  235. // this.SendBufferSize = 8192;
  236. } catch (SocketException) {
  237. }
  238. }
  239. /* Creates a new system socket, returning the handle */
  240. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  241. extern IntPtr Socket_internal (AddressFamily family, SocketType type, ProtocolType proto, out int error);
  242. #endregion
  243. #region Properties
  244. [ObsoleteAttribute ("Use OSSupportsIPv4 instead")]
  245. public static bool SupportsIPv4 {
  246. get { return ipv4_supported == 1; }
  247. }
  248. [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
  249. public static bool SupportsIPv6 {
  250. get { return ipv6_supported == 1; }
  251. }
  252. #if NET_2_1
  253. public static bool OSSupportsIPv4 {
  254. get { return ipv4_supported == 1; }
  255. }
  256. #else
  257. public static bool OSSupportsIPv4 {
  258. get {
  259. NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
  260. foreach (NetworkInterface adapter in nics) {
  261. if (adapter.Supports (NetworkInterfaceComponent.IPv4))
  262. return true;
  263. }
  264. return false;
  265. }
  266. }
  267. #endif
  268. #if NET_2_1
  269. public static bool OSSupportsIPv6 {
  270. get { return ipv6_supported == 1; }
  271. }
  272. #else
  273. public static bool OSSupportsIPv6 {
  274. get {
  275. NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
  276. foreach (NetworkInterface adapter in nics) {
  277. if (adapter.Supports (NetworkInterfaceComponent.IPv6))
  278. return true;
  279. }
  280. return false;
  281. }
  282. }
  283. #endif
  284. public int Available {
  285. get {
  286. ThrowIfDisposedAndClosed ();
  287. int ret, error;
  288. ret = Available_internal (safe_handle, out error);
  289. if (error != 0)
  290. throw new SocketException (error);
  291. return ret;
  292. }
  293. }
  294. static int Available_internal (SafeSocketHandle safeHandle, out int error)
  295. {
  296. bool release = false;
  297. try {
  298. safeHandle.DangerousAddRef (ref release);
  299. return Available_internal (safeHandle.DangerousGetHandle (), out error);
  300. } finally {
  301. if (release)
  302. safeHandle.DangerousRelease ();
  303. }
  304. }
  305. /* Returns the amount of data waiting to be read on socket */
  306. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  307. extern static int Available_internal (IntPtr socket, out int error);
  308. public bool DontFragment {
  309. get {
  310. ThrowIfDisposedAndClosed ();
  311. switch (address_family) {
  312. case AddressFamily.InterNetwork:
  313. return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
  314. case AddressFamily.InterNetworkV6:
  315. return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
  316. default:
  317. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  318. }
  319. }
  320. set {
  321. ThrowIfDisposedAndClosed ();
  322. switch (address_family) {
  323. case AddressFamily.InterNetwork:
  324. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value ? 1 : 0);
  325. break;
  326. case AddressFamily.InterNetworkV6:
  327. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value ? 1 : 0);
  328. break;
  329. default:
  330. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  331. }
  332. }
  333. }
  334. public bool EnableBroadcast {
  335. get {
  336. ThrowIfDisposedAndClosed ();
  337. if (protocol_type != ProtocolType.Udp)
  338. throw new SocketException ((int) SocketError.ProtocolOption);
  339. return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0;
  340. }
  341. set {
  342. ThrowIfDisposedAndClosed ();
  343. if (protocol_type != ProtocolType.Udp)
  344. throw new SocketException ((int) SocketError.ProtocolOption);
  345. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value ? 1 : 0);
  346. }
  347. }
  348. public bool ExclusiveAddressUse {
  349. get {
  350. ThrowIfDisposedAndClosed ();
  351. return ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0;
  352. }
  353. set {
  354. ThrowIfDisposedAndClosed ();
  355. if (is_bound)
  356. throw new InvalidOperationException ("Bind has already been called for this socket");
  357. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value ? 1 : 0);
  358. }
  359. }
  360. public bool IsBound {
  361. get {
  362. return is_bound;
  363. }
  364. }
  365. public LingerOption LingerState {
  366. get {
  367. ThrowIfDisposedAndClosed ();
  368. return (LingerOption) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger);
  369. }
  370. set {
  371. ThrowIfDisposedAndClosed ();
  372. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger, value);
  373. }
  374. }
  375. public bool MulticastLoopback {
  376. get {
  377. ThrowIfDisposedAndClosed ();
  378. /* Even though this option can be set for TCP sockets on Linux, throw
  379. * this exception anyway to be compatible (the MSDN docs say
  380. * "Setting this property on a Transmission Control Protocol (TCP)
  381. * socket will have no effect." but the MS runtime throws the
  382. * exception...) */
  383. if (protocol_type == ProtocolType.Tcp)
  384. throw new SocketException ((int)SocketError.ProtocolOption);
  385. switch (address_family) {
  386. case AddressFamily.InterNetwork:
  387. return ((int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
  388. case AddressFamily.InterNetworkV6:
  389. return ((int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
  390. default:
  391. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  392. }
  393. }
  394. set {
  395. ThrowIfDisposedAndClosed ();
  396. /* Even though this option can be set for TCP sockets on Linux, throw
  397. * this exception anyway to be compatible (the MSDN docs say
  398. * "Setting this property on a Transmission Control Protocol (TCP)
  399. * socket will have no effect." but the MS runtime throws the
  400. * exception...) */
  401. if (protocol_type == ProtocolType.Tcp)
  402. throw new SocketException ((int)SocketError.ProtocolOption);
  403. switch (address_family) {
  404. case AddressFamily.InterNetwork:
  405. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value ? 1 : 0);
  406. break;
  407. case AddressFamily.InterNetworkV6:
  408. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value ? 1 : 0);
  409. break;
  410. default:
  411. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  412. }
  413. }
  414. }
  415. public bool DualMode {
  416. get {
  417. if (AddressFamily != AddressFamily.InterNetworkV6)
  418. throw new NotSupportedException("This protocol version is not supported");
  419. return ((int)GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only) == 0);
  420. }
  421. set {
  422. if (AddressFamily != AddressFamily.InterNetworkV6)
  423. throw new NotSupportedException("This protocol version is not supported");
  424. SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, value ? 0 : 1);
  425. }
  426. }
  427. private bool IsDualMode {
  428. get {
  429. return AddressFamily == AddressFamily.InterNetworkV6 && DualMode;
  430. }
  431. }
  432. [MonoTODO ("This doesn't do anything on Mono yet")]
  433. public bool UseOnlyOverlappedIO {
  434. get { return use_overlapped_io; }
  435. set { use_overlapped_io = value; }
  436. }
  437. public IntPtr Handle {
  438. get { return safe_handle.DangerousGetHandle (); }
  439. }
  440. // Wish: support non-IP endpoints.
  441. public EndPoint LocalEndPoint {
  442. get {
  443. ThrowIfDisposedAndClosed ();
  444. /* If the seed EndPoint is null, Connect, Bind, etc has not yet
  445. * been called. MS returns null in this case. */
  446. if (seed_endpoint == null)
  447. return null;
  448. int error;
  449. SocketAddress sa = LocalEndPoint_internal (safe_handle, (int) address_family, out error);
  450. if (error != 0)
  451. throw new SocketException (error);
  452. return seed_endpoint.Create (sa);
  453. }
  454. }
  455. static SocketAddress LocalEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
  456. {
  457. bool release = false;
  458. try {
  459. safeHandle.DangerousAddRef (ref release);
  460. return LocalEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
  461. } finally {
  462. if (release)
  463. safeHandle.DangerousRelease ();
  464. }
  465. }
  466. /* Returns the local endpoint details in addr and port */
  467. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  468. extern static SocketAddress LocalEndPoint_internal (IntPtr socket, int family, out int error);
  469. public SocketType SocketType {
  470. get { return socket_type; }
  471. }
  472. public int SendTimeout {
  473. get {
  474. ThrowIfDisposedAndClosed ();
  475. return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendTimeout);
  476. }
  477. set {
  478. ThrowIfDisposedAndClosed ();
  479. if (value < -1)
  480. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
  481. /* According to the MSDN docs we should adjust values between 1 and
  482. * 499 to 500, but the MS runtime doesn't do this. */
  483. if (value == -1)
  484. value = 0;
  485. SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, value);
  486. }
  487. }
  488. public int ReceiveTimeout {
  489. get {
  490. ThrowIfDisposedAndClosed ();
  491. return (int) GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout);
  492. }
  493. set {
  494. ThrowIfDisposedAndClosed ();
  495. if (value < -1)
  496. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
  497. if (value == -1)
  498. value = 0;
  499. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, value);
  500. }
  501. }
  502. public AddressFamily AddressFamily {
  503. get { return address_family; }
  504. }
  505. public bool Blocking {
  506. get { return is_blocking; }
  507. set {
  508. ThrowIfDisposedAndClosed ();
  509. int error;
  510. Blocking_internal (safe_handle, value, out error);
  511. if (error != 0)
  512. throw new SocketException (error);
  513. is_blocking = value;
  514. }
  515. }
  516. static void Blocking_internal (SafeSocketHandle safeHandle, bool block, out int error)
  517. {
  518. bool release = false;
  519. try {
  520. safeHandle.DangerousAddRef (ref release);
  521. Blocking_internal (safeHandle.DangerousGetHandle (), block, out error);
  522. } finally {
  523. if (release)
  524. safeHandle.DangerousRelease ();
  525. }
  526. }
  527. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  528. internal extern static void Blocking_internal(IntPtr socket, bool block, out int error);
  529. public bool Connected {
  530. get { return is_connected; }
  531. internal set { is_connected = value; }
  532. }
  533. public ProtocolType ProtocolType {
  534. get { return protocol_type; }
  535. }
  536. public bool NoDelay {
  537. get {
  538. ThrowIfDisposedAndClosed ();
  539. ThrowIfUdp ();
  540. return ((int) GetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay)) != 0;
  541. }
  542. set {
  543. ThrowIfDisposedAndClosed ();
  544. ThrowIfUdp ();
  545. SetSocketOption (SocketOptionLevel.Tcp, SocketOptionName.NoDelay, value ? 1 : 0);
  546. }
  547. }
  548. public int ReceiveBufferSize {
  549. get {
  550. ThrowIfDisposedAndClosed ();
  551. return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
  552. }
  553. set {
  554. ThrowIfDisposedAndClosed ();
  555. if (value < 0)
  556. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
  557. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
  558. }
  559. }
  560. public int SendBufferSize {
  561. get {
  562. ThrowIfDisposedAndClosed ();
  563. return (int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
  564. }
  565. set {
  566. ThrowIfDisposedAndClosed ();
  567. if (value < 0)
  568. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
  569. SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer, value);
  570. }
  571. }
  572. public short Ttl {
  573. get {
  574. ThrowIfDisposedAndClosed ();
  575. switch (address_family) {
  576. case AddressFamily.InterNetwork:
  577. return (short) (int) GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive);
  578. case AddressFamily.InterNetworkV6:
  579. return (short) (int) GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
  580. default:
  581. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  582. }
  583. }
  584. set {
  585. ThrowIfDisposedAndClosed ();
  586. if (value < 0 || value > 255)
  587. throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero or greater than 255.");
  588. switch (address_family) {
  589. case AddressFamily.InterNetwork:
  590. SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
  591. break;
  592. case AddressFamily.InterNetworkV6:
  593. SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
  594. break;
  595. default:
  596. throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
  597. }
  598. }
  599. }
  600. public EndPoint RemoteEndPoint {
  601. get {
  602. ThrowIfDisposedAndClosed ();
  603. /* If the seed EndPoint is null, Connect, Bind, etc has
  604. * not yet been called. MS returns null in this case. */
  605. if (!is_connected || seed_endpoint == null)
  606. return null;
  607. int error;
  608. SocketAddress sa = RemoteEndPoint_internal (safe_handle, (int) address_family, out error);
  609. if (error != 0)
  610. throw new SocketException (error);
  611. return seed_endpoint.Create (sa);
  612. }
  613. }
  614. static SocketAddress RemoteEndPoint_internal (SafeSocketHandle safeHandle, int family, out int error)
  615. {
  616. bool release = false;
  617. try {
  618. safeHandle.DangerousAddRef (ref release);
  619. return RemoteEndPoint_internal (safeHandle.DangerousGetHandle (), family, out error);
  620. } finally {
  621. if (release)
  622. safeHandle.DangerousRelease ();
  623. }
  624. }
  625. /* Returns the remote endpoint details in addr and port */
  626. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  627. extern static SocketAddress RemoteEndPoint_internal (IntPtr socket, int family, out int error);
  628. #endregion
  629. #region Select
  630. public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
  631. {
  632. var list = new List<Socket> ();
  633. AddSockets (list, checkRead, "checkRead");
  634. AddSockets (list, checkWrite, "checkWrite");
  635. AddSockets (list, checkError, "checkError");
  636. if (list.Count == 3)
  637. throw new ArgumentNullException ("checkRead, checkWrite, checkError", "All the lists are null or empty.");
  638. /* The 'sockets' array contains:
  639. * - READ socket 0-n, null,
  640. * - WRITE socket 0-n, null,
  641. * - ERROR socket 0-n, null */
  642. Socket [] sockets = list.ToArray ();
  643. int error;
  644. Select_internal (ref sockets, microSeconds, out error);
  645. if (error != 0)
  646. throw new SocketException (error);
  647. if (sockets == null) {
  648. if (checkRead != null)
  649. checkRead.Clear ();
  650. if (checkWrite != null)
  651. checkWrite.Clear ();
  652. if (checkError != null)
  653. checkError.Clear ();
  654. return;
  655. }
  656. int mode = 0;
  657. int count = sockets.Length;
  658. IList currentList = checkRead;
  659. int currentIdx = 0;
  660. for (int i = 0; i < count; i++) {
  661. Socket sock = sockets [i];
  662. if (sock == null) { // separator
  663. if (currentList != null) {
  664. // Remove non-signaled sockets after the current one
  665. int to_remove = currentList.Count - currentIdx;
  666. for (int k = 0; k < to_remove; k++)
  667. currentList.RemoveAt (currentIdx);
  668. }
  669. currentList = (mode == 0) ? checkWrite : checkError;
  670. currentIdx = 0;
  671. mode++;
  672. continue;
  673. }
  674. if (mode == 1 && currentList == checkWrite && !sock.is_connected) {
  675. if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
  676. sock.is_connected = true;
  677. }
  678. /* Remove non-signaled sockets before the current one */
  679. while (((Socket) currentList [currentIdx]) != sock)
  680. currentList.RemoveAt (currentIdx);
  681. currentIdx++;
  682. }
  683. }
  684. static void AddSockets (List<Socket> sockets, IList list, string name)
  685. {
  686. if (list != null) {
  687. foreach (Socket sock in list) {
  688. if (sock == null) // MS throws a NullRef
  689. throw new ArgumentNullException ("name", "Contains a null element");
  690. sockets.Add (sock);
  691. }
  692. }
  693. sockets.Add (null);
  694. }
  695. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  696. extern static void Select_internal (ref Socket [] sockets, int microSeconds, out int error);
  697. #endregion
  698. #region Poll
  699. public bool Poll (int time_us, SelectMode mode)
  700. {
  701. ThrowIfDisposedAndClosed ();
  702. if (mode != SelectMode.SelectRead && mode != SelectMode.SelectWrite && mode != SelectMode.SelectError)
  703. throw new NotSupportedException ("'mode' parameter is not valid.");
  704. int error;
  705. bool result = Poll_internal (safe_handle, mode, time_us, out error);
  706. if (error != 0)
  707. throw new SocketException (error);
  708. if (mode == SelectMode.SelectWrite && result && !is_connected) {
  709. /* Update the is_connected state; for non-blocking Connect()
  710. * this is when we can find out that the connect succeeded. */
  711. if ((int) GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
  712. is_connected = true;
  713. }
  714. return result;
  715. }
  716. static bool Poll_internal (SafeSocketHandle safeHandle, SelectMode mode, int timeout, out int error)
  717. {
  718. bool release = false;
  719. try {
  720. safeHandle.DangerousAddRef (ref release);
  721. return Poll_internal (safeHandle.DangerousGetHandle (), mode, timeout, out error);
  722. } finally {
  723. if (release)
  724. safeHandle.DangerousRelease ();
  725. }
  726. }
  727. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  728. extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);
  729. #endregion
  730. #region Accept
  731. public Socket Accept()
  732. {
  733. ThrowIfDisposedAndClosed ();
  734. int error = 0;
  735. SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
  736. if (error != 0) {
  737. if (is_closed)
  738. error = SOCKET_CLOSED_CODE;
  739. throw new SocketException(error);
  740. }
  741. Socket accepted = new Socket (this.AddressFamily, this.SocketType, this.ProtocolType, safe_handle) {
  742. seed_endpoint = this.seed_endpoint,
  743. Blocking = this.Blocking,
  744. };
  745. return accepted;
  746. }
  747. internal void Accept (Socket acceptSocket)
  748. {
  749. ThrowIfDisposedAndClosed ();
  750. int error = 0;
  751. SafeSocketHandle safe_handle = Accept_internal (this.safe_handle, out error, is_blocking);
  752. if (error != 0) {
  753. if (is_closed)
  754. error = SOCKET_CLOSED_CODE;
  755. throw new SocketException (error);
  756. }
  757. acceptSocket.address_family = this.AddressFamily;
  758. acceptSocket.socket_type = this.SocketType;
  759. acceptSocket.protocol_type = this.ProtocolType;
  760. acceptSocket.safe_handle = safe_handle;
  761. acceptSocket.is_connected = true;
  762. acceptSocket.seed_endpoint = this.seed_endpoint;
  763. acceptSocket.Blocking = this.Blocking;
  764. // FIXME: figure out what if anything else needs to be reset
  765. }
  766. public bool AcceptAsync (SocketAsyncEventArgs e)
  767. {
  768. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  769. ThrowIfDisposedAndClosed ();
  770. if (!is_bound)
  771. throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
  772. if (!is_listening)
  773. throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
  774. if (e.BufferList != null)
  775. throw new ArgumentException ("Multiple buffers cannot be used with this method.");
  776. if (e.Count < 0)
  777. throw new ArgumentOutOfRangeException ("e.Count");
  778. Socket acceptSocket = e.AcceptSocket;
  779. if (acceptSocket != null) {
  780. if (acceptSocket.is_bound || acceptSocket.is_connected)
  781. throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
  782. }
  783. InitSocketAsyncEventArgs (e, AcceptAsyncCallback, e, SocketOperation.Accept);
  784. QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
  785. return true;
  786. }
  787. static AsyncCallback AcceptAsyncCallback = new AsyncCallback (ares => {
  788. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  789. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  790. throw new InvalidOperationException ("No operation in progress");
  791. try {
  792. e.AcceptSocket = e.current_socket.EndAccept (ares);
  793. } catch (SocketException ex) {
  794. e.SocketError = ex.SocketErrorCode;
  795. } catch (ObjectDisposedException) {
  796. e.SocketError = SocketError.OperationAborted;
  797. } finally {
  798. if (e.AcceptSocket == null)
  799. e.AcceptSocket = new Socket (e.current_socket.AddressFamily, e.current_socket.SocketType, e.current_socket.ProtocolType, null);
  800. e.Complete ();
  801. }
  802. });
  803. public IAsyncResult BeginAccept(AsyncCallback callback, object state)
  804. {
  805. ThrowIfDisposedAndClosed ();
  806. if (!is_bound || !is_listening)
  807. throw new InvalidOperationException ();
  808. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
  809. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
  810. return sockares;
  811. }
  812. static IOAsyncCallback BeginAcceptCallback = new IOAsyncCallback (ares => {
  813. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  814. Socket acc_socket = null;
  815. try {
  816. if (sockares.AcceptSocket == null) {
  817. acc_socket = sockares.socket.Accept ();
  818. } else {
  819. acc_socket = sockares.AcceptSocket;
  820. sockares.socket.Accept (acc_socket);
  821. }
  822. } catch (Exception e) {
  823. sockares.Complete (e);
  824. return;
  825. }
  826. sockares.Complete (acc_socket);
  827. });
  828. public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
  829. {
  830. ThrowIfDisposedAndClosed ();
  831. if (receiveSize < 0)
  832. throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
  833. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
  834. Buffer = new byte [receiveSize],
  835. Offset = 0,
  836. Size = receiveSize,
  837. SockFlags = SocketFlags.None,
  838. };
  839. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
  840. return sockares;
  841. }
  842. public IAsyncResult BeginAccept (Socket acceptSocket, int receiveSize, AsyncCallback callback, object state)
  843. {
  844. ThrowIfDisposedAndClosed ();
  845. if (receiveSize < 0)
  846. throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
  847. if (acceptSocket != null) {
  848. ThrowIfDisposedAndClosed (acceptSocket);
  849. if (acceptSocket.IsBound)
  850. throw new InvalidOperationException ();
  851. /* For some reason the MS runtime
  852. * barfs if the new socket is not TCP,
  853. * even though it's just about to blow
  854. * away all those parameters
  855. */
  856. if (acceptSocket.ProtocolType != ProtocolType.Tcp)
  857. throw new SocketException ((int)SocketError.InvalidArgument);
  858. }
  859. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.AcceptReceive) {
  860. Buffer = new byte [receiveSize],
  861. Offset = 0,
  862. Size = receiveSize,
  863. SockFlags = SocketFlags.None,
  864. AcceptSocket = acceptSocket,
  865. };
  866. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
  867. return sockares;
  868. }
  869. static IOAsyncCallback BeginAcceptReceiveCallback = new IOAsyncCallback (ares => {
  870. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  871. Socket acc_socket = null;
  872. try {
  873. if (sockares.AcceptSocket == null) {
  874. acc_socket = sockares.socket.Accept ();
  875. } else {
  876. acc_socket = sockares.AcceptSocket;
  877. sockares.socket.Accept (acc_socket);
  878. }
  879. } catch (Exception e) {
  880. sockares.Complete (e);
  881. return;
  882. }
  883. /* It seems the MS runtime special-cases 0-length requested receive data. See bug 464201. */
  884. int total = 0;
  885. if (sockares.Size > 0) {
  886. try {
  887. SocketError error;
  888. total = acc_socket.Receive_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out error);
  889. if (error != 0) {
  890. sockares.Complete (new SocketException ((int) error));
  891. return;
  892. }
  893. } catch (Exception e) {
  894. sockares.Complete (e);
  895. return;
  896. }
  897. }
  898. sockares.Complete (acc_socket, total);
  899. });
  900. public Socket EndAccept (IAsyncResult result)
  901. {
  902. int bytes;
  903. byte[] buffer;
  904. return EndAccept (out buffer, out bytes, result);
  905. }
  906. public Socket EndAccept (out byte[] buffer, IAsyncResult asyncResult)
  907. {
  908. int bytes;
  909. return EndAccept (out buffer, out bytes, asyncResult);
  910. }
  911. public Socket EndAccept (out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult)
  912. {
  913. ThrowIfDisposedAndClosed ();
  914. SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndAccept", "asyncResult");
  915. if (!sockares.IsCompleted)
  916. sockares.AsyncWaitHandle.WaitOne ();
  917. sockares.CheckIfThrowDelayedException ();
  918. buffer = sockares.Buffer;
  919. bytesTransferred = sockares.Total;
  920. return sockares.AcceptedSocket;
  921. }
  922. static SafeSocketHandle Accept_internal (SafeSocketHandle safeHandle, out int error, bool blocking)
  923. {
  924. try {
  925. safeHandle.RegisterForBlockingSyscall ();
  926. var ret = Accept_internal (safeHandle.DangerousGetHandle (), out error, blocking);
  927. return new SafeSocketHandle (ret, true);
  928. } finally {
  929. safeHandle.UnRegisterForBlockingSyscall ();
  930. }
  931. }
  932. /* Creates a new system socket, returning the handle */
  933. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  934. extern static IntPtr Accept_internal (IntPtr sock, out int error, bool blocking);
  935. #endregion
  936. #region Bind
  937. public void Bind (EndPoint local_end)
  938. {
  939. ThrowIfDisposedAndClosed ();
  940. if (local_end == null)
  941. throw new ArgumentNullException("local_end");
  942. var ipEndPoint = local_end as IPEndPoint;
  943. if (ipEndPoint != null) {
  944. local_end = RemapIPEndPoint (ipEndPoint);
  945. }
  946. int error;
  947. Bind_internal (safe_handle, local_end.Serialize(), out error);
  948. if (error != 0)
  949. throw new SocketException (error);
  950. if (error == 0)
  951. is_bound = true;
  952. seed_endpoint = local_end;
  953. }
  954. private static void Bind_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
  955. {
  956. bool release = false;
  957. try {
  958. safeHandle.DangerousAddRef (ref release);
  959. Bind_internal (safeHandle.DangerousGetHandle (), sa, out error);
  960. } finally {
  961. if (release)
  962. safeHandle.DangerousRelease ();
  963. }
  964. }
  965. // Creates a new system socket, returning the handle
  966. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  967. private extern static void Bind_internal(IntPtr sock, SocketAddress sa, out int error);
  968. #endregion
  969. #region Listen
  970. public void Listen (int backlog)
  971. {
  972. ThrowIfDisposedAndClosed ();
  973. if (!is_bound)
  974. throw new SocketException ((int) SocketError.InvalidArgument);
  975. int error;
  976. Listen_internal(safe_handle, backlog, out error);
  977. if (error != 0)
  978. throw new SocketException (error);
  979. is_listening = true;
  980. }
  981. static void Listen_internal (SafeSocketHandle safeHandle, int backlog, out int error)
  982. {
  983. bool release = false;
  984. try {
  985. safeHandle.DangerousAddRef (ref release);
  986. Listen_internal (safeHandle.DangerousGetHandle (), backlog, out error);
  987. } finally {
  988. if (release)
  989. safeHandle.DangerousRelease ();
  990. }
  991. }
  992. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  993. extern static void Listen_internal (IntPtr sock, int backlog, out int error);
  994. #endregion
  995. #region Connect
  996. public void Connect (IPAddress address, int port)
  997. {
  998. Connect (new IPEndPoint (address, port));
  999. }
  1000. public void Connect (string host, int port)
  1001. {
  1002. Connect (Dns.GetHostAddresses (host), port);
  1003. }
  1004. public void Connect (IPAddress[] addresses, int port)
  1005. {
  1006. ThrowIfDisposedAndClosed ();
  1007. if (addresses == null)
  1008. throw new ArgumentNullException ("addresses");
  1009. if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
  1010. throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
  1011. if (is_listening)
  1012. throw new InvalidOperationException ();
  1013. // FIXME: do non-blocking sockets Poll here?
  1014. int error = 0;
  1015. foreach (IPAddress address in addresses) {
  1016. IPEndPoint iep = new IPEndPoint (address, port);
  1017. iep = RemapIPEndPoint (iep);
  1018. Connect_internal (safe_handle, iep.Serialize (), out error);
  1019. if (error == 0) {
  1020. is_connected = true;
  1021. is_bound = true;
  1022. seed_endpoint = iep;
  1023. return;
  1024. }
  1025. if (error != (int)SocketError.InProgress && error != (int)SocketError.WouldBlock)
  1026. continue;
  1027. if (!is_blocking) {
  1028. Poll (-1, SelectMode.SelectWrite);
  1029. error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
  1030. if (error == 0) {
  1031. is_connected = true;
  1032. is_bound = true;
  1033. seed_endpoint = iep;
  1034. return;
  1035. }
  1036. }
  1037. }
  1038. if (error != 0)
  1039. throw new SocketException (error);
  1040. }
  1041. public void Connect (EndPoint remoteEP)
  1042. {
  1043. ThrowIfDisposedAndClosed ();
  1044. if (remoteEP == null)
  1045. throw new ArgumentNullException ("remoteEP");
  1046. IPEndPoint ep = remoteEP as IPEndPoint;
  1047. /* Dgram uses Any to 'disconnect' */
  1048. if (ep != null && socket_type != SocketType.Dgram) {
  1049. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
  1050. throw new SocketException ((int) SocketError.AddressNotAvailable);
  1051. }
  1052. if (is_listening)
  1053. throw new InvalidOperationException ();
  1054. if (ep != null) {
  1055. remoteEP = RemapIPEndPoint (ep);
  1056. }
  1057. SocketAddress serial = remoteEP.Serialize ();
  1058. int error = 0;
  1059. Connect_internal (safe_handle, serial, out error);
  1060. if (error == 0 || error == 10035)
  1061. seed_endpoint = remoteEP; // Keep the ep around for non-blocking sockets
  1062. if (error != 0) {
  1063. if (is_closed)
  1064. error = SOCKET_CLOSED_CODE;
  1065. throw new SocketException (error);
  1066. }
  1067. is_connected = !(socket_type == SocketType.Dgram && ep != null && (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)));
  1068. is_bound = true;
  1069. }
  1070. public bool ConnectAsync (SocketAsyncEventArgs e)
  1071. {
  1072. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  1073. ThrowIfDisposedAndClosed ();
  1074. if (is_listening)
  1075. throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
  1076. if (e.RemoteEndPoint == null)
  1077. throw new ArgumentNullException ("remoteEP");
  1078. InitSocketAsyncEventArgs (e, null, e, SocketOperation.Connect);
  1079. try {
  1080. IPAddress [] addresses;
  1081. SocketAsyncResult ares;
  1082. if (!GetCheckedIPs (e, out addresses)) {
  1083. e.socket_async_result.EndPoint = e.RemoteEndPoint;
  1084. ares = (SocketAsyncResult) BeginConnect (e.RemoteEndPoint, ConnectAsyncCallback, e);
  1085. } else {
  1086. DnsEndPoint dep = (e.RemoteEndPoint as DnsEndPoint);
  1087. e.socket_async_result.Addresses = addresses;
  1088. e.socket_async_result.Port = dep.Port;
  1089. ares = (SocketAsyncResult) BeginConnect (addresses, dep.Port, ConnectAsyncCallback, e);
  1090. }
  1091. if (ares.IsCompleted && ares.CompletedSynchronously) {
  1092. ares.CheckIfThrowDelayedException ();
  1093. return false;
  1094. }
  1095. } catch (Exception exc) {
  1096. e.socket_async_result.Complete (exc, true);
  1097. return false;
  1098. }
  1099. return true;
  1100. }
  1101. public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
  1102. {
  1103. var sock = new Socket (e.RemoteEndPoint.AddressFamily, socketType, protocolType);
  1104. return sock.ConnectAsync (e);
  1105. }
  1106. public static void CancelConnectAsync (SocketAsyncEventArgs e)
  1107. {
  1108. if (e == null)
  1109. throw new ArgumentNullException("e");
  1110. if (e.in_progress != 0 && e.LastOperation == SocketAsyncOperation.Connect)
  1111. e.current_socket.Close();
  1112. }
  1113. static AsyncCallback ConnectAsyncCallback = new AsyncCallback (ares => {
  1114. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  1115. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  1116. throw new InvalidOperationException ("No operation in progress");
  1117. try {
  1118. e.current_socket.EndConnect (ares);
  1119. } catch (SocketException se) {
  1120. e.SocketError = se.SocketErrorCode;
  1121. } catch (ObjectDisposedException) {
  1122. e.SocketError = SocketError.OperationAborted;
  1123. } finally {
  1124. e.Complete ();
  1125. }
  1126. });
  1127. public IAsyncResult BeginConnect (IPAddress address, int port, AsyncCallback callback, object state)
  1128. {
  1129. ThrowIfDisposedAndClosed ();
  1130. if (address == null)
  1131. throw new ArgumentNullException ("address");
  1132. if (address.ToString ().Length == 0)
  1133. throw new ArgumentException ("The length of the IP address is zero");
  1134. if (port <= 0 || port > 65535)
  1135. throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
  1136. if (is_listening)
  1137. throw new InvalidOperationException ();
  1138. return BeginConnect (new IPEndPoint (address, port), callback, state);
  1139. }
  1140. public IAsyncResult BeginConnect (string host, int port, AsyncCallback callback, object state)
  1141. {
  1142. ThrowIfDisposedAndClosed ();
  1143. if (host == null)
  1144. throw new ArgumentNullException ("host");
  1145. if (address_family != AddressFamily.InterNetwork && address_family != AddressFamily.InterNetworkV6)
  1146. throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
  1147. if (port <= 0 || port > 65535)
  1148. throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
  1149. if (is_listening)
  1150. throw new InvalidOperationException ();
  1151. return BeginConnect (Dns.GetHostAddresses (host), port, callback, state);
  1152. }
  1153. public IAsyncResult BeginConnect (EndPoint end_point, AsyncCallback callback, object state)
  1154. {
  1155. ThrowIfDisposedAndClosed ();
  1156. if (end_point == null)
  1157. throw new ArgumentNullException ("end_point");
  1158. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
  1159. EndPoint = end_point,
  1160. };
  1161. // Bug #75154: Connect() should not succeed for .Any addresses.
  1162. if (end_point is IPEndPoint) {
  1163. IPEndPoint ep = (IPEndPoint) end_point;
  1164. if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
  1165. sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
  1166. return sockares;
  1167. }
  1168. end_point = RemapIPEndPoint (ep);
  1169. }
  1170. int error = 0;
  1171. if (connect_in_progress) {
  1172. // This could happen when multiple IPs are used
  1173. // Calling connect() again will reset the connection attempt and cause
  1174. // an error. Better to just close the socket and move on.
  1175. connect_in_progress = false;
  1176. safe_handle.Dispose ();
  1177. safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
  1178. if (error != 0)
  1179. throw new SocketException (error);
  1180. }
  1181. bool blk = is_blocking;
  1182. if (blk)
  1183. Blocking = false;
  1184. Connect_internal (safe_handle, end_point.Serialize (), out error);
  1185. if (blk)
  1186. Blocking = true;
  1187. if (error == 0) {
  1188. // succeeded synch
  1189. is_connected = true;
  1190. is_bound = true;
  1191. sockares.Complete (true);
  1192. return sockares;
  1193. }
  1194. if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
  1195. // error synch
  1196. is_connected = false;
  1197. is_bound = false;
  1198. sockares.Complete (new SocketException (error), true);
  1199. return sockares;
  1200. }
  1201. // continue asynch
  1202. is_connected = false;
  1203. is_bound = false;
  1204. connect_in_progress = true;
  1205. IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
  1206. return sockares;
  1207. }
  1208. public IAsyncResult BeginConnect (IPAddress[] addresses, int port, AsyncCallback callback, object state)
  1209. {
  1210. ThrowIfDisposedAndClosed ();
  1211. if (addresses == null)
  1212. throw new ArgumentNullException ("addresses");
  1213. if (addresses.Length == 0)
  1214. throw new ArgumentException ("Empty addresses list");
  1215. if (this.AddressFamily != AddressFamily.InterNetwork && this.AddressFamily != AddressFamily.InterNetworkV6)
  1216. throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
  1217. if (port <= 0 || port > 65535)
  1218. throw new ArgumentOutOfRangeException ("port", "Must be > 0 and < 65536");
  1219. if (is_listening)
  1220. throw new InvalidOperationException ();
  1221. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Connect) {
  1222. Addresses = addresses,
  1223. Port = port,
  1224. };
  1225. is_connected = false;
  1226. return BeginMConnect (sockares);
  1227. }
  1228. internal IAsyncResult BeginMConnect (SocketAsyncResult sockares)
  1229. {
  1230. SocketAsyncResult ares = null;
  1231. Exception exc = null;
  1232. AsyncCallback callback;
  1233. for (int i = sockares.CurrentAddress; i < sockares.Addresses.Length; i++) {
  1234. try {
  1235. sockares.CurrentAddress++;
  1236. ares = (SocketAsyncResult) BeginConnect (new IPEndPoint (sockares.Addresses [i], sockares.Port), null, sockares);
  1237. if (ares.IsCompleted && ares.CompletedSynchronously) {
  1238. ares.CheckIfThrowDelayedException ();
  1239. callback = ares.AsyncCallback;
  1240. if (callback != null)
  1241. ThreadPool.UnsafeQueueUserWorkItem (_ => callback (ares), null);
  1242. }
  1243. break;
  1244. } catch (Exception e) {
  1245. exc = e;
  1246. ares = null;
  1247. }
  1248. }
  1249. if (ares == null)
  1250. throw exc;
  1251. return sockares;
  1252. }
  1253. static IOAsyncCallback BeginConnectCallback = new IOAsyncCallback (ares => {
  1254. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  1255. if (sockares.EndPoint == null) {
  1256. sockares.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
  1257. return;
  1258. }
  1259. SocketAsyncResult mconnect = sockares.AsyncState as SocketAsyncResult;
  1260. bool is_mconnect = mconnect != null && mconnect.Addresses != null;
  1261. try {
  1262. EndPoint ep = sockares.EndPoint;
  1263. int error_code = (int) sockares.socket.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
  1264. if (error_code == 0) {
  1265. if (is_mconnect)
  1266. sockares = mconnect;
  1267. sockares.socket.seed_endpoint = ep;
  1268. sockares.socket.is_connected = true;
  1269. sockares.socket.is_bound = true;
  1270. sockares.socket.connect_in_progress = false;
  1271. sockares.error = 0;
  1272. sockares.Complete ();
  1273. return;
  1274. }
  1275. if (!is_mconnect) {
  1276. sockares.socket.connect_in_progress = false;
  1277. sockares.Complete (new SocketException (error_code));
  1278. return;
  1279. }
  1280. if (mconnect.CurrentAddress >= mconnect.Addresses.Length) {
  1281. mconnect.Complete (new SocketException (error_code));
  1282. return;
  1283. }
  1284. mconnect.socket.BeginMConnect (mconnect);
  1285. } catch (Exception e) {
  1286. sockares.socket.connect_in_progress = false;
  1287. if (is_mconnect)
  1288. sockares = mconnect;
  1289. sockares.Complete (e);
  1290. return;
  1291. }
  1292. });
  1293. public void EndConnect (IAsyncResult result)
  1294. {
  1295. ThrowIfDisposedAndClosed ();
  1296. SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndConnect", "result");
  1297. if (!sockares.IsCompleted)
  1298. sockares.AsyncWaitHandle.WaitOne();
  1299. sockares.CheckIfThrowDelayedException();
  1300. }
  1301. static void Connect_internal (SafeSocketHandle safeHandle, SocketAddress sa, out int error)
  1302. {
  1303. try {
  1304. safeHandle.RegisterForBlockingSyscall ();
  1305. Connect_internal (safeHandle.DangerousGetHandle (), sa, out error);
  1306. } finally {
  1307. safeHandle.UnRegisterForBlockingSyscall ();
  1308. }
  1309. }
  1310. /* Connects to the remote address */
  1311. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1312. extern static void Connect_internal(IntPtr sock, SocketAddress sa, out int error);
  1313. /* Returns :
  1314. * - false when it is ok to use RemoteEndPoint
  1315. * - true when addresses must be used (and addresses could be null/empty) */
  1316. bool GetCheckedIPs (SocketAsyncEventArgs e, out IPAddress [] addresses)
  1317. {
  1318. addresses = null;
  1319. // Connect to the first address that match the host name, like:
  1320. // http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
  1321. // while skipping entries that do not match the address family
  1322. DnsEndPoint dep = e.RemoteEndPoint as DnsEndPoint;
  1323. if (dep != null) {
  1324. addresses = Dns.GetHostAddresses (dep.Host);
  1325. return true;
  1326. } else {
  1327. e.ConnectByNameError = null;
  1328. return false;
  1329. }
  1330. }
  1331. #endregion
  1332. #region Disconnect
  1333. /* According to the docs, the MS runtime will throw PlatformNotSupportedException
  1334. * if the platform is newer than w2k. We should be able to cope... */
  1335. public void Disconnect (bool reuseSocket)
  1336. {
  1337. ThrowIfDisposedAndClosed ();
  1338. int error = 0;
  1339. Disconnect_internal (safe_handle, reuseSocket, out error);
  1340. if (error != 0) {
  1341. if (error == 50) {
  1342. /* ERROR_NOT_SUPPORTED */
  1343. throw new PlatformNotSupportedException ();
  1344. } else {
  1345. throw new SocketException (error);
  1346. }
  1347. }
  1348. is_connected = false;
  1349. if (reuseSocket) {
  1350. /* Do managed housekeeping here... */
  1351. }
  1352. }
  1353. public bool DisconnectAsync (SocketAsyncEventArgs e)
  1354. {
  1355. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  1356. ThrowIfDisposedAndClosed ();
  1357. InitSocketAsyncEventArgs (e, DisconnectAsyncCallback, e, SocketOperation.Disconnect);
  1358. IOSelector.Add (e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
  1359. return true;
  1360. }
  1361. static AsyncCallback DisconnectAsyncCallback = new AsyncCallback (ares => {
  1362. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  1363. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  1364. throw new InvalidOperationException ("No operation in progress");
  1365. try {
  1366. e.current_socket.EndDisconnect (ares);
  1367. } catch (SocketException ex) {
  1368. e.SocketError = ex.SocketErrorCode;
  1369. } catch (ObjectDisposedException) {
  1370. e.SocketError = SocketError.OperationAborted;
  1371. } finally {
  1372. e.Complete ();
  1373. }
  1374. });
  1375. public IAsyncResult BeginDisconnect (bool reuseSocket, AsyncCallback callback, object state)
  1376. {
  1377. ThrowIfDisposedAndClosed ();
  1378. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Disconnect) {
  1379. ReuseSocket = reuseSocket,
  1380. };
  1381. IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
  1382. return sockares;
  1383. }
  1384. static IOAsyncCallback BeginDisconnectCallback = new IOAsyncCallback (ares => {
  1385. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  1386. try {
  1387. sockares.socket.Disconnect (sockares.ReuseSocket);
  1388. } catch (Exception e) {
  1389. sockares.Complete (e);
  1390. return;
  1391. }
  1392. sockares.Complete ();
  1393. });
  1394. public void EndDisconnect (IAsyncResult asyncResult)
  1395. {
  1396. ThrowIfDisposedAndClosed ();
  1397. SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndDisconnect", "asyncResult");
  1398. if (!sockares.IsCompleted)
  1399. sockares.AsyncWaitHandle.WaitOne ();
  1400. sockares.CheckIfThrowDelayedException ();
  1401. }
  1402. static void Disconnect_internal (SafeSocketHandle safeHandle, bool reuse, out int error)
  1403. {
  1404. bool release = false;
  1405. try {
  1406. safeHandle.DangerousAddRef (ref release);
  1407. Disconnect_internal (safeHandle.DangerousGetHandle (), reuse, out error);
  1408. } finally {
  1409. if (release)
  1410. safeHandle.DangerousRelease ();
  1411. }
  1412. }
  1413. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1414. extern static void Disconnect_internal (IntPtr sock, bool reuse, out int error);
  1415. #endregion
  1416. #region Receive
  1417. public int Receive (byte [] buffer)
  1418. {
  1419. return Receive (buffer, SocketFlags.None);
  1420. }
  1421. public int Receive (byte [] buffer, SocketFlags flags)
  1422. {
  1423. ThrowIfDisposedAndClosed ();
  1424. ThrowIfBufferNull (buffer);
  1425. ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
  1426. SocketError error;
  1427. int ret = Receive_nochecks (buffer, 0, buffer.Length, flags, out error);
  1428. if (error != SocketError.Success) {
  1429. if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
  1430. throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
  1431. throw new SocketException ((int) error);
  1432. }
  1433. return ret;
  1434. }
  1435. public int Receive (byte [] buffer, int size, SocketFlags flags)
  1436. {
  1437. ThrowIfDisposedAndClosed ();
  1438. ThrowIfBufferNull (buffer);
  1439. ThrowIfBufferOutOfRange (buffer, 0, size);
  1440. SocketError error;
  1441. int ret = Receive_nochecks (buffer, 0, size, flags, out error);
  1442. if (error != SocketError.Success) {
  1443. if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
  1444. throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
  1445. throw new SocketException ((int) error);
  1446. }
  1447. return ret;
  1448. }
  1449. public int Receive (byte [] buffer, int offset, int size, SocketFlags flags)
  1450. {
  1451. ThrowIfDisposedAndClosed ();
  1452. ThrowIfBufferNull (buffer);
  1453. ThrowIfBufferOutOfRange (buffer, offset, size);
  1454. SocketError error;
  1455. int ret = Receive_nochecks (buffer, offset, size, flags, out error);
  1456. if (error != SocketError.Success) {
  1457. if (error == SocketError.WouldBlock && is_blocking) // This might happen when ReceiveTimeout is set
  1458. throw new SocketException ((int) error, TIMEOUT_EXCEPTION_MSG);
  1459. throw new SocketException ((int) error);
  1460. }
  1461. return ret;
  1462. }
  1463. public int Receive (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
  1464. {
  1465. ThrowIfDisposedAndClosed ();
  1466. ThrowIfBufferNull (buffer);
  1467. ThrowIfBufferOutOfRange (buffer, offset, size);
  1468. return Receive_nochecks (buffer, offset, size, flags, out error);
  1469. }
  1470. public int Receive (IList<ArraySegment<byte>> buffers)
  1471. {
  1472. SocketError error;
  1473. int ret = Receive (buffers, SocketFlags.None, out error);
  1474. if (error != SocketError.Success)
  1475. throw new SocketException ((int) error);
  1476. return ret;
  1477. }
  1478. [CLSCompliant (false)]
  1479. public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
  1480. {
  1481. SocketError error;
  1482. int ret = Receive (buffers, socketFlags, out error);
  1483. if (error != SocketError.Success)
  1484. throw new SocketException ((int) error);
  1485. return(ret);
  1486. }
  1487. [CLSCompliant (false)]
  1488. public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
  1489. {
  1490. ThrowIfDisposedAndClosed ();
  1491. if (buffers == null || buffers.Count == 0)
  1492. throw new ArgumentNullException ("buffers");
  1493. int numsegments = buffers.Count;
  1494. int nativeError;
  1495. int ret;
  1496. /* Only example I can find of sending a byte array reference directly into an internal
  1497. * call is in System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeSocket.cs,
  1498. * so taking a lead from that... */
  1499. WSABUF[] bufarray = new WSABUF[numsegments];
  1500. GCHandle[] gch = new GCHandle[numsegments];
  1501. for (int i = 0; i < numsegments; i++) {
  1502. ArraySegment<byte> segment = buffers[i];
  1503. if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
  1504. throw new ArgumentOutOfRangeException ("segment");
  1505. gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
  1506. bufarray[i].len = segment.Count;
  1507. bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
  1508. }
  1509. try {
  1510. ret = Receive_internal (safe_handle, bufarray, socketFlags, out nativeError);
  1511. } finally {
  1512. for (int i = 0; i < numsegments; i++) {
  1513. if (gch[i].IsAllocated)
  1514. gch[i].Free ();
  1515. }
  1516. }
  1517. errorCode = (SocketError) nativeError;
  1518. return ret;
  1519. }
  1520. public bool ReceiveAsync (SocketAsyncEventArgs e)
  1521. {
  1522. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  1523. ThrowIfDisposedAndClosed ();
  1524. // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
  1525. // thrown when e.Buffer and e.BufferList are null (works fine when one is
  1526. // set to a valid object)
  1527. if (e.Buffer == null && e.BufferList == null)
  1528. throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
  1529. if (e.Buffer == null) {
  1530. InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.ReceiveGeneric);
  1531. e.socket_async_result.Buffers = e.BufferList;
  1532. QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
  1533. } else {
  1534. InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
  1535. e.socket_async_result.Buffer = e.Buffer;
  1536. e.socket_async_result.Offset = e.Offset;
  1537. e.socket_async_result.Size = e.Count;
  1538. QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
  1539. }
  1540. return true;
  1541. }
  1542. static AsyncCallback ReceiveAsyncCallback = new AsyncCallback (ares => {
  1543. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  1544. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  1545. throw new InvalidOperationException ("No operation in progress");
  1546. try {
  1547. e.BytesTransferred = e.current_socket.EndReceive (ares);
  1548. } catch (SocketException se){
  1549. e.SocketError = se.SocketErrorCode;
  1550. } catch (ObjectDisposedException) {
  1551. e.SocketError = SocketError.OperationAborted;
  1552. } finally {
  1553. e.Complete ();
  1554. }
  1555. });
  1556. public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
  1557. {
  1558. ThrowIfDisposedAndClosed ();
  1559. ThrowIfBufferNull (buffer);
  1560. ThrowIfBufferOutOfRange (buffer, offset, size);
  1561. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Receive) {
  1562. Buffer = buffer,
  1563. Offset = offset,
  1564. Size = size,
  1565. SockFlags = socket_flags,
  1566. };
  1567. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
  1568. return sockares;
  1569. }
  1570. public IAsyncResult BeginReceive (byte[] buffer, int offset, int size, SocketFlags flags, out SocketError error, AsyncCallback callback, object state)
  1571. {
  1572. /* As far as I can tell from the docs and from experimentation, a pointer to the
  1573. * SocketError parameter is not supposed to be saved for the async parts. And as we don't
  1574. * set any socket errors in the setup code, we just have to set it to Success. */
  1575. error = SocketError.Success;
  1576. return BeginReceive (buffer, offset, size, flags, callback, state);
  1577. }
  1578. static IOAsyncCallback BeginReceiveCallback = new IOAsyncCallback (ares => {
  1579. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  1580. int total = 0;
  1581. try {
  1582. total = Receive_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
  1583. } catch (Exception e) {
  1584. sockares.Complete (e);
  1585. return;
  1586. }
  1587. sockares.Complete (total);
  1588. });
  1589. [CLSCompliant (false)]
  1590. public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  1591. {
  1592. ThrowIfDisposedAndClosed ();
  1593. if (buffers == null)
  1594. throw new ArgumentNullException ("buffers");
  1595. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveGeneric) {
  1596. Buffers = buffers,
  1597. SockFlags = socketFlags,
  1598. };
  1599. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
  1600. return sockares;
  1601. }
  1602. [CLSCompliant (false)]
  1603. public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  1604. {
  1605. /* I assume the same SocketError semantics as above */
  1606. errorCode = SocketError.Success;
  1607. return BeginReceive (buffers, socketFlags, callback, state);
  1608. }
  1609. static IOAsyncCallback BeginReceiveGenericCallback = new IOAsyncCallback (ares => {
  1610. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  1611. int total = 0;
  1612. try {
  1613. total = sockares.socket.Receive (sockares.Buffers, sockares.SockFlags);
  1614. } catch (Exception e) {
  1615. sockares.Complete (e);
  1616. return;
  1617. }
  1618. sockares.Complete (total);
  1619. });
  1620. public int EndReceive (IAsyncResult result)
  1621. {
  1622. SocketError error;
  1623. int bytesReceived = EndReceive (result, out error);
  1624. if (error != SocketError.Success) {
  1625. if (error != SocketError.WouldBlock && error != SocketError.InProgress)
  1626. is_connected = false;
  1627. throw new SocketException ((int)error);
  1628. }
  1629. return bytesReceived;
  1630. }
  1631. public int EndReceive (IAsyncResult asyncResult, out SocketError errorCode)
  1632. {
  1633. ThrowIfDisposedAndClosed ();
  1634. SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceive", "asyncResult");
  1635. if (!sockares.IsCompleted)
  1636. sockares.AsyncWaitHandle.WaitOne ();
  1637. // If no socket error occurred, call CheckIfThrowDelayedException in case there are other
  1638. // kinds of exceptions that should be thrown.
  1639. if ((errorCode = sockares.ErrorCode) == SocketError.Success)
  1640. sockares.CheckIfThrowDelayedException();
  1641. return sockares.Total;
  1642. }
  1643. int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  1644. {
  1645. int nativeError;
  1646. int ret = Receive_internal (safe_handle, buf, offset, size, flags, out nativeError);
  1647. error = (SocketError) nativeError;
  1648. if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
  1649. is_connected = false;
  1650. is_bound = false;
  1651. } else {
  1652. is_connected = true;
  1653. }
  1654. return ret;
  1655. }
  1656. static int Receive_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
  1657. {
  1658. try {
  1659. safeHandle.RegisterForBlockingSyscall ();
  1660. return Receive_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
  1661. } finally {
  1662. safeHandle.UnRegisterForBlockingSyscall ();
  1663. }
  1664. }
  1665. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  1666. extern static int Receive_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
  1667. static int Receive_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, out int error)
  1668. {
  1669. try {
  1670. safeHandle.RegisterForBlockingSyscall ();
  1671. return Receive_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, out error);
  1672. } finally {
  1673. safeHandle.UnRegisterForBlockingSyscall ();
  1674. }
  1675. }
  1676. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1677. extern static int Receive_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, out int error);
  1678. #endregion
  1679. #region ReceiveFrom
  1680. public int ReceiveFrom (byte [] buffer, ref EndPoint remoteEP)
  1681. {
  1682. ThrowIfDisposedAndClosed ();
  1683. ThrowIfBufferNull (buffer);
  1684. return ReceiveFrom (buffer, 0, buffer.Length, SocketFlags.None, ref remoteEP);
  1685. }
  1686. public int ReceiveFrom (byte [] buffer, SocketFlags flags, ref EndPoint remoteEP)
  1687. {
  1688. ThrowIfDisposedAndClosed ();
  1689. ThrowIfBufferNull (buffer);
  1690. return ReceiveFrom (buffer, 0, buffer.Length, flags, ref remoteEP);
  1691. }
  1692. public int ReceiveFrom (byte [] buffer, int size, SocketFlags flags, ref EndPoint remoteEP)
  1693. {
  1694. ThrowIfDisposedAndClosed ();
  1695. ThrowIfBufferNull (buffer);
  1696. ThrowIfBufferOutOfRange (buffer, 0, size);
  1697. return ReceiveFrom (buffer, 0, size, flags, ref remoteEP);
  1698. }
  1699. public int ReceiveFrom (byte [] buffer, int offset, int size, SocketFlags flags, ref EndPoint remoteEP)
  1700. {
  1701. ThrowIfDisposedAndClosed ();
  1702. ThrowIfBufferNull (buffer);
  1703. ThrowIfBufferOutOfRange (buffer, offset, size);
  1704. if (remoteEP == null)
  1705. throw new ArgumentNullException ("remoteEP");
  1706. int error;
  1707. return ReceiveFrom_nochecks_exc (buffer, offset, size, flags, ref remoteEP, true, out error);
  1708. }
  1709. public bool ReceiveFromAsync (SocketAsyncEventArgs e)
  1710. {
  1711. ThrowIfDisposedAndClosed ();
  1712. // We do not support recv into multiple buffers yet
  1713. if (e.BufferList != null)
  1714. throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
  1715. if (e.RemoteEndPoint == null)
  1716. throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
  1717. InitSocketAsyncEventArgs (e, ReceiveFromAsyncCallback, e, SocketOperation.ReceiveFrom);
  1718. e.socket_async_result.Buffer = e.Buffer;
  1719. e.socket_async_result.Offset = e.Offset;
  1720. e.socket_async_result.Size = e.Count;
  1721. e.socket_async_result.EndPoint = e.RemoteEndPoint;
  1722. e.socket_async_result.SockFlags = e.SocketFlags;
  1723. QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
  1724. return true;
  1725. }
  1726. static AsyncCallback ReceiveFromAsyncCallback = new AsyncCallback (ares => {
  1727. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  1728. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  1729. throw new InvalidOperationException ("No operation in progress");
  1730. try {
  1731. e.BytesTransferred = e.current_socket.EndReceiveFrom (ares, ref e.remote_ep);
  1732. } catch (SocketException ex) {
  1733. e.SocketError = ex.SocketErrorCode;
  1734. } catch (ObjectDisposedException) {
  1735. e.SocketError = SocketError.OperationAborted;
  1736. } finally {
  1737. e.Complete ();
  1738. }
  1739. });
  1740. public IAsyncResult BeginReceiveFrom (byte[] buffer, int offset, int size, SocketFlags socket_flags, ref EndPoint remote_end, AsyncCallback callback, object state)
  1741. {
  1742. ThrowIfDisposedAndClosed ();
  1743. ThrowIfBufferNull (buffer);
  1744. ThrowIfBufferOutOfRange (buffer, offset, size);
  1745. if (remote_end == null)
  1746. throw new ArgumentNullException ("remote_end");
  1747. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.ReceiveFrom) {
  1748. Buffer = buffer,
  1749. Offset = offset,
  1750. Size = size,
  1751. SockFlags = socket_flags,
  1752. EndPoint = remote_end,
  1753. };
  1754. QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
  1755. return sockares;
  1756. }
  1757. static IOAsyncCallback BeginReceiveFromCallback = new IOAsyncCallback (ares => {
  1758. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  1759. int total = 0;
  1760. try {
  1761. int error;
  1762. total = sockares.socket.ReceiveFrom_nochecks_exc (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, ref sockares.EndPoint, true, out error);
  1763. } catch (Exception e) {
  1764. sockares.Complete (e);
  1765. return;
  1766. }
  1767. sockares.Complete (total);
  1768. });
  1769. public int EndReceiveFrom(IAsyncResult result, ref EndPoint end_point)
  1770. {
  1771. ThrowIfDisposedAndClosed ();
  1772. if (end_point == null)
  1773. throw new ArgumentNullException ("remote_end");
  1774. SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndReceiveFrom", "result");
  1775. if (!sockares.IsCompleted)
  1776. sockares.AsyncWaitHandle.WaitOne();
  1777. sockares.CheckIfThrowDelayedException();
  1778. end_point = sockares.EndPoint;
  1779. return sockares.Total;
  1780. }
  1781. internal int ReceiveFrom_nochecks_exc (byte [] buf, int offset, int size, SocketFlags flags, ref EndPoint remote_end, bool throwOnError, out int error)
  1782. {
  1783. SocketAddress sockaddr = remote_end.Serialize();
  1784. int cnt = ReceiveFrom_internal (safe_handle, buf, offset, size, flags, ref sockaddr, out error);
  1785. SocketError err = (SocketError) error;
  1786. if (err != 0) {
  1787. if (err != SocketError.WouldBlock && err != SocketError.InProgress) {
  1788. is_connected = false;
  1789. } else if (err == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set
  1790. if (throwOnError)
  1791. throw new SocketException ((int) SocketError.TimedOut, TIMEOUT_EXCEPTION_MSG);
  1792. error = (int) SocketError.TimedOut;
  1793. return 0;
  1794. }
  1795. if (throwOnError)
  1796. throw new SocketException (error);
  1797. return 0;
  1798. }
  1799. is_connected = true;
  1800. is_bound = true;
  1801. /* If sockaddr is null then we're a connection oriented protocol and should ignore the
  1802. * remote_end parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */
  1803. if (sockaddr != null) {
  1804. /* Stupidly, EndPoint.Create() is an instance method */
  1805. remote_end = remote_end.Create (sockaddr);
  1806. }
  1807. seed_endpoint = remote_end;
  1808. return cnt;
  1809. }
  1810. static int ReceiveFrom_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error)
  1811. {
  1812. try {
  1813. safeHandle.RegisterForBlockingSyscall ();
  1814. return ReceiveFrom_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, ref sockaddr, out error);
  1815. } finally {
  1816. safeHandle.UnRegisterForBlockingSyscall ();
  1817. }
  1818. }
  1819. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  1820. extern static int ReceiveFrom_internal(IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, ref SocketAddress sockaddr, out int error);
  1821. #endregion
  1822. #region ReceiveMessageFrom
  1823. [MonoTODO ("Not implemented")]
  1824. public int ReceiveMessageFrom (byte[] buffer, int offset, int size, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation)
  1825. {
  1826. ThrowIfDisposedAndClosed ();
  1827. ThrowIfBufferNull (buffer);
  1828. ThrowIfBufferOutOfRange (buffer, offset, size);
  1829. if (remoteEP == null)
  1830. throw new ArgumentNullException ("remoteEP");
  1831. // FIXME: figure out how we get hold of the IPPacketInformation
  1832. throw new NotImplementedException ();
  1833. }
  1834. [MonoTODO ("Not implemented")]
  1835. public bool ReceiveMessageFromAsync (SocketAsyncEventArgs e)
  1836. {
  1837. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  1838. ThrowIfDisposedAndClosed ();
  1839. throw new NotImplementedException ();
  1840. }
  1841. [MonoTODO]
  1842. public IAsyncResult BeginReceiveMessageFrom (byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, AsyncCallback callback, object state)
  1843. {
  1844. ThrowIfDisposedAndClosed ();
  1845. ThrowIfBufferNull (buffer);
  1846. ThrowIfBufferOutOfRange (buffer, offset, size);
  1847. if (remoteEP == null)
  1848. throw new ArgumentNullException ("remoteEP");
  1849. throw new NotImplementedException ();
  1850. }
  1851. [MonoTODO]
  1852. public int EndReceiveMessageFrom (IAsyncResult asyncResult, ref SocketFlags socketFlags, ref EndPoint endPoint, out IPPacketInformation ipPacketInformation)
  1853. {
  1854. ThrowIfDisposedAndClosed ();
  1855. if (endPoint == null)
  1856. throw new ArgumentNullException ("endPoint");
  1857. SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndReceiveMessageFrom", "asyncResult");
  1858. throw new NotImplementedException ();
  1859. }
  1860. #endregion
  1861. #region Send
  1862. public int Send (byte [] buffer)
  1863. {
  1864. ThrowIfDisposedAndClosed ();
  1865. ThrowIfBufferNull (buffer);
  1866. ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
  1867. SocketError error;
  1868. int ret = Send_nochecks (buffer, 0, buffer.Length, SocketFlags.None, out error);
  1869. if (error != SocketError.Success)
  1870. throw new SocketException ((int) error);
  1871. return ret;
  1872. }
  1873. public int Send (byte [] buffer, SocketFlags flags)
  1874. {
  1875. ThrowIfDisposedAndClosed ();
  1876. ThrowIfBufferNull (buffer);
  1877. ThrowIfBufferOutOfRange (buffer, 0, buffer.Length);
  1878. SocketError error;
  1879. int ret = Send_nochecks (buffer, 0, buffer.Length, flags, out error);
  1880. if (error != SocketError.Success)
  1881. throw new SocketException ((int) error);
  1882. return ret;
  1883. }
  1884. public int Send (byte [] buffer, int size, SocketFlags flags)
  1885. {
  1886. ThrowIfDisposedAndClosed ();
  1887. ThrowIfBufferNull (buffer);
  1888. ThrowIfBufferOutOfRange (buffer, 0, size);
  1889. SocketError error;
  1890. int ret = Send_nochecks (buffer, 0, size, flags, out error);
  1891. if (error != SocketError.Success)
  1892. throw new SocketException ((int) error);
  1893. return ret;
  1894. }
  1895. public int Send (byte [] buffer, int offset, int size, SocketFlags flags)
  1896. {
  1897. ThrowIfDisposedAndClosed ();
  1898. ThrowIfBufferNull (buffer);
  1899. ThrowIfBufferOutOfRange (buffer, offset, size);
  1900. SocketError error;
  1901. int ret = Send_nochecks (buffer, offset, size, flags, out error);
  1902. if (error != SocketError.Success)
  1903. throw new SocketException ((int) error);
  1904. return ret;
  1905. }
  1906. public int Send (byte [] buffer, int offset, int size, SocketFlags flags, out SocketError error)
  1907. {
  1908. ThrowIfDisposedAndClosed ();
  1909. ThrowIfBufferNull (buffer);
  1910. ThrowIfBufferOutOfRange (buffer, offset, size);
  1911. return Send_nochecks (buffer, offset, size, flags, out error);
  1912. }
  1913. public
  1914. int Send (IList<ArraySegment<byte>> buffers)
  1915. {
  1916. SocketError error;
  1917. int ret = Send (buffers, SocketFlags.None, out error);
  1918. if (error != SocketError.Success)
  1919. throw new SocketException ((int) error);
  1920. return ret;
  1921. }
  1922. public
  1923. int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
  1924. {
  1925. SocketError error;
  1926. int ret = Send (buffers, socketFlags, out error);
  1927. if (error != SocketError.Success)
  1928. throw new SocketException ((int) error);
  1929. return ret;
  1930. }
  1931. [CLSCompliant (false)]
  1932. public int Send (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode)
  1933. {
  1934. ThrowIfDisposedAndClosed ();
  1935. if (buffers == null)
  1936. throw new ArgumentNullException ("buffers");
  1937. if (buffers.Count == 0)
  1938. throw new ArgumentException ("Buffer is empty", "buffers");
  1939. int numsegments = buffers.Count;
  1940. int nativeError;
  1941. int ret;
  1942. WSABUF[] bufarray = new WSABUF[numsegments];
  1943. GCHandle[] gch = new GCHandle[numsegments];
  1944. for(int i = 0; i < numsegments; i++) {
  1945. ArraySegment<byte> segment = buffers[i];
  1946. if (segment.Offset < 0 || segment.Count < 0 || segment.Count > segment.Array.Length - segment.Offset)
  1947. throw new ArgumentOutOfRangeException ("segment");
  1948. gch[i] = GCHandle.Alloc (segment.Array, GCHandleType.Pinned);
  1949. bufarray[i].len = segment.Count;
  1950. bufarray[i].buf = Marshal.UnsafeAddrOfPinnedArrayElement (segment.Array, segment.Offset);
  1951. }
  1952. try {
  1953. ret = Send_internal (safe_handle, bufarray, socketFlags, out nativeError);
  1954. } finally {
  1955. for(int i = 0; i < numsegments; i++) {
  1956. if (gch[i].IsAllocated) {
  1957. gch[i].Free ();
  1958. }
  1959. }
  1960. }
  1961. errorCode = (SocketError)nativeError;
  1962. return ret;
  1963. }
  1964. int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
  1965. {
  1966. if (size == 0) {
  1967. error = SocketError.Success;
  1968. return 0;
  1969. }
  1970. int nativeError;
  1971. int ret = Send_internal (safe_handle, buf, offset, size, flags, out nativeError);
  1972. error = (SocketError)nativeError;
  1973. if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress) {
  1974. is_connected = false;
  1975. is_bound = false;
  1976. } else {
  1977. is_connected = true;
  1978. }
  1979. return ret;
  1980. }
  1981. public bool SendAsync (SocketAsyncEventArgs e)
  1982. {
  1983. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  1984. ThrowIfDisposedAndClosed ();
  1985. if (e.Buffer == null && e.BufferList == null)
  1986. throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
  1987. if (e.Buffer == null) {
  1988. InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.SendGeneric);
  1989. e.socket_async_result.Buffers = e.BufferList;
  1990. QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
  1991. } else {
  1992. InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
  1993. e.socket_async_result.Buffer = e.Buffer;
  1994. e.socket_async_result.Offset = e.Offset;
  1995. e.socket_async_result.Size = e.Count;
  1996. QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
  1997. }
  1998. return true;
  1999. }
  2000. static AsyncCallback SendAsyncCallback = new AsyncCallback (ares => {
  2001. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  2002. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  2003. throw new InvalidOperationException ("No operation in progress");
  2004. try {
  2005. e.BytesTransferred = e.current_socket.EndSend (ares);
  2006. } catch (SocketException se){
  2007. e.SocketError = se.SocketErrorCode;
  2008. } catch (ObjectDisposedException) {
  2009. e.SocketError = SocketError.OperationAborted;
  2010. } finally {
  2011. e.Complete ();
  2012. }
  2013. });
  2014. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  2015. {
  2016. if (!is_connected) {
  2017. errorCode = SocketError.NotConnected;
  2018. throw new SocketException ((int) errorCode);
  2019. }
  2020. errorCode = SocketError.Success;
  2021. return BeginSend (buffer, offset, size, socketFlags, callback, state);
  2022. }
  2023. public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags, AsyncCallback callback, object state)
  2024. {
  2025. ThrowIfDisposedAndClosed ();
  2026. ThrowIfBufferNull (buffer);
  2027. ThrowIfBufferOutOfRange (buffer, offset, size);
  2028. if (!is_connected)
  2029. throw new SocketException ((int)SocketError.NotConnected);
  2030. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Send) {
  2031. Buffer = buffer,
  2032. Offset = offset,
  2033. Size = size,
  2034. SockFlags = socket_flags,
  2035. };
  2036. QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
  2037. return sockares;
  2038. }
  2039. static void BeginSendCallback (SocketAsyncResult sockares, int sent_so_far)
  2040. {
  2041. int total = 0;
  2042. try {
  2043. total = Socket.Send_internal (sockares.socket.safe_handle, sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, out sockares.error);
  2044. } catch (Exception e) {
  2045. sockares.Complete (e);
  2046. return;
  2047. }
  2048. if (sockares.error == 0) {
  2049. sent_so_far += total;
  2050. sockares.Offset += total;
  2051. sockares.Size -= total;
  2052. if (sockares.socket.is_disposed) {
  2053. sockares.Complete (total);
  2054. return;
  2055. }
  2056. if (sockares.Size > 0) {
  2057. IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
  2058. return; // Have to finish writing everything. See bug #74475.
  2059. }
  2060. sockares.Total = sent_so_far;
  2061. }
  2062. sockares.Complete (total);
  2063. }
  2064. public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, AsyncCallback callback, object state)
  2065. {
  2066. ThrowIfDisposedAndClosed ();
  2067. if (buffers == null)
  2068. throw new ArgumentNullException ("buffers");
  2069. if (!is_connected)
  2070. throw new SocketException ((int)SocketError.NotConnected);
  2071. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendGeneric) {
  2072. Buffers = buffers,
  2073. SockFlags = socketFlags,
  2074. };
  2075. QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
  2076. return sockares;
  2077. }
  2078. [CLSCompliant (false)]
  2079. public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode, AsyncCallback callback, object state)
  2080. {
  2081. if (!is_connected) {
  2082. errorCode = SocketError.NotConnected;
  2083. throw new SocketException ((int)errorCode);
  2084. }
  2085. errorCode = SocketError.Success;
  2086. return BeginSend (buffers, socketFlags, callback, state);
  2087. }
  2088. static IOAsyncCallback BeginSendGenericCallback = new IOAsyncCallback (ares => {
  2089. SocketAsyncResult sockares = (SocketAsyncResult) ares;
  2090. int total = 0;
  2091. try {
  2092. total = sockares.socket.Send (sockares.Buffers, sockares.SockFlags);
  2093. } catch (Exception e) {
  2094. sockares.Complete (e);
  2095. return;
  2096. }
  2097. sockares.Complete (total);
  2098. });
  2099. public int EndSend (IAsyncResult result)
  2100. {
  2101. SocketError error;
  2102. int bytesSent = EndSend (result, out error);
  2103. if (error != SocketError.Success) {
  2104. if (error != SocketError.WouldBlock && error != SocketError.InProgress)
  2105. is_connected = false;
  2106. throw new SocketException ((int)error);
  2107. }
  2108. return bytesSent;
  2109. }
  2110. public int EndSend (IAsyncResult asyncResult, out SocketError errorCode)
  2111. {
  2112. ThrowIfDisposedAndClosed ();
  2113. SocketAsyncResult sockares = ValidateEndIAsyncResult (asyncResult, "EndSend", "asyncResult");
  2114. if (!sockares.IsCompleted)
  2115. sockares.AsyncWaitHandle.WaitOne ();
  2116. /* If no socket error occurred, call CheckIfThrowDelayedException in
  2117. * case there are other kinds of exceptions that should be thrown.*/
  2118. if ((errorCode = sockares.ErrorCode) == SocketError.Success)
  2119. sockares.CheckIfThrowDelayedException ();
  2120. return sockares.Total;
  2121. }
  2122. static int Send_internal (SafeSocketHandle safeHandle, WSABUF[] bufarray, SocketFlags flags, out int error)
  2123. {
  2124. bool release = false;
  2125. try {
  2126. safeHandle.DangerousAddRef (ref release);
  2127. return Send_internal (safeHandle.DangerousGetHandle (), bufarray, flags, out error);
  2128. } finally {
  2129. if (release)
  2130. safeHandle.DangerousRelease ();
  2131. }
  2132. }
  2133. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  2134. extern static int Send_internal (IntPtr sock, WSABUF[] bufarray, SocketFlags flags, out int error);
  2135. static int Send_internal (SafeSocketHandle safeHandle, byte[] buf, int offset, int count, SocketFlags flags, out int error)
  2136. {
  2137. try {
  2138. safeHandle.RegisterForBlockingSyscall ();
  2139. return Send_internal (safeHandle.DangerousGetHandle (), buf, offset, count, flags, out error);
  2140. } finally {
  2141. safeHandle.UnRegisterForBlockingSyscall ();
  2142. }
  2143. }
  2144. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2145. extern static int Send_internal(IntPtr sock, byte[] buf, int offset, int count, SocketFlags flags, out int error);
  2146. #endregion
  2147. #region SendTo
  2148. public int SendTo (byte [] buffer, EndPoint remote_end)
  2149. {
  2150. ThrowIfDisposedAndClosed ();
  2151. ThrowIfBufferNull (buffer);
  2152. return SendTo (buffer, 0, buffer.Length, SocketFlags.None, remote_end);
  2153. }
  2154. public int SendTo (byte [] buffer, SocketFlags flags, EndPoint remote_end)
  2155. {
  2156. ThrowIfDisposedAndClosed ();
  2157. ThrowIfBufferNull (buffer);
  2158. return SendTo (buffer, 0, buffer.Length, flags, remote_end);
  2159. }
  2160. public int SendTo (byte [] buffer, int size, SocketFlags flags, EndPoint remote_end)
  2161. {
  2162. return SendTo (buffer, 0, size, flags, remote_end);
  2163. }
  2164. public int SendTo (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
  2165. {
  2166. ThrowIfDisposedAndClosed ();
  2167. ThrowIfBufferNull (buffer);
  2168. ThrowIfBufferOutOfRange (buffer, offset, size);
  2169. if (remote_end == null)
  2170. throw new ArgumentNullException("remote_end");
  2171. return SendTo_nochecks (buffer, offset, size, flags, remote_end);
  2172. }
  2173. public bool SendToAsync (SocketAsyncEventArgs e)
  2174. {
  2175. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  2176. ThrowIfDisposedAndClosed ();
  2177. if (e.BufferList != null)
  2178. throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
  2179. if (e.RemoteEndPoint == null)
  2180. throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
  2181. InitSocketAsyncEventArgs (e, SendToAsyncCallback, e, SocketOperation.SendTo);
  2182. e.socket_async_result.Buffer = e.Buffer;
  2183. e.socket_async_result.Offset = e.Offset;
  2184. e.socket_async_result.Size = e.Count;
  2185. e.socket_async_result.SockFlags = e.SocketFlags;
  2186. e.socket_async_result.EndPoint = e.RemoteEndPoint;
  2187. QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
  2188. return true;
  2189. }
  2190. static AsyncCallback SendToAsyncCallback = new AsyncCallback (ares => {
  2191. SocketAsyncEventArgs e = (SocketAsyncEventArgs) ((SocketAsyncResult) ares).AsyncState;
  2192. if (Interlocked.Exchange (ref e.in_progress, 0) != 1)
  2193. throw new InvalidOperationException ("No operation in progress");
  2194. try {
  2195. e.BytesTransferred = e.current_socket.EndSendTo (ares);
  2196. } catch (SocketException ex) {
  2197. e.SocketError = ex.SocketErrorCode;
  2198. } catch (ObjectDisposedException) {
  2199. e.SocketError = SocketError.OperationAborted;
  2200. } finally {
  2201. e.Complete ();
  2202. }
  2203. });
  2204. public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, SocketFlags socket_flags, EndPoint remote_end, AsyncCallback callback, object state)
  2205. {
  2206. ThrowIfDisposedAndClosed ();
  2207. ThrowIfBufferNull (buffer);
  2208. ThrowIfBufferOutOfRange (buffer, offset, size);
  2209. SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.SendTo) {
  2210. Buffer = buffer,
  2211. Offset = offset,
  2212. Size = size,
  2213. SockFlags = socket_flags,
  2214. EndPoint = remote_end,
  2215. };
  2216. QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
  2217. return sockares;
  2218. }
  2219. static void BeginSendToCallback (SocketAsyncResult sockares, int sent_so_far)
  2220. {
  2221. int total = 0;
  2222. try {
  2223. total = sockares.socket.SendTo_nochecks (sockares.Buffer, sockares.Offset, sockares.Size, sockares.SockFlags, sockares.EndPoint);
  2224. if (sockares.error == 0) {
  2225. sent_so_far += total;
  2226. sockares.Offset += total;
  2227. sockares.Size -= total;
  2228. }
  2229. if (sockares.Size > 0) {
  2230. IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
  2231. return; // Have to finish writing everything. See bug #74475.
  2232. }
  2233. sockares.Total = sent_so_far;
  2234. } catch (Exception e) {
  2235. sockares.Complete (e);
  2236. return;
  2237. }
  2238. sockares.Complete ();
  2239. }
  2240. public int EndSendTo (IAsyncResult result)
  2241. {
  2242. ThrowIfDisposedAndClosed ();
  2243. SocketAsyncResult sockares = ValidateEndIAsyncResult (result, "EndSendTo", "result");
  2244. if (!sockares.IsCompleted)
  2245. sockares.AsyncWaitHandle.WaitOne();
  2246. sockares.CheckIfThrowDelayedException();
  2247. return sockares.Total;
  2248. }
  2249. int SendTo_nochecks (byte [] buffer, int offset, int size, SocketFlags flags, EndPoint remote_end)
  2250. {
  2251. int error;
  2252. int ret = SendTo_internal (safe_handle, buffer, offset, size, flags, remote_end.Serialize (), out error);
  2253. SocketError err = (SocketError) error;
  2254. if (err != 0) {
  2255. if (err != SocketError.WouldBlock && err != SocketError.InProgress)
  2256. is_connected = false;
  2257. throw new SocketException (error);
  2258. }
  2259. is_connected = true;
  2260. is_bound = true;
  2261. seed_endpoint = remote_end;
  2262. return ret;
  2263. }
  2264. static int SendTo_internal (SafeSocketHandle safeHandle, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error)
  2265. {
  2266. try {
  2267. safeHandle.RegisterForBlockingSyscall ();
  2268. return SendTo_internal (safeHandle.DangerousGetHandle (), buffer, offset, count, flags, sa, out error);
  2269. } finally {
  2270. safeHandle.UnRegisterForBlockingSyscall ();
  2271. }
  2272. }
  2273. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2274. extern static int SendTo_internal (IntPtr sock, byte[] buffer, int offset, int count, SocketFlags flags, SocketAddress sa, out int error);
  2275. #endregion
  2276. #region SendFile
  2277. public void SendFile (string fileName)
  2278. {
  2279. ThrowIfDisposedAndClosed ();
  2280. if (!is_connected)
  2281. throw new NotSupportedException ();
  2282. if (!is_blocking)
  2283. throw new InvalidOperationException ();
  2284. SendFile (fileName, null, null, 0);
  2285. }
  2286. public void SendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags)
  2287. {
  2288. ThrowIfDisposedAndClosed ();
  2289. if (!is_connected)
  2290. throw new NotSupportedException ();
  2291. if (!is_blocking)
  2292. throw new InvalidOperationException ();
  2293. if (!SendFile_internal (safe_handle, fileName, preBuffer, postBuffer, flags)) {
  2294. SocketException exc = new SocketException ();
  2295. if (exc.ErrorCode == 2 || exc.ErrorCode == 3)
  2296. throw new FileNotFoundException ();
  2297. throw exc;
  2298. }
  2299. }
  2300. public IAsyncResult BeginSendFile (string fileName, AsyncCallback callback, object state)
  2301. {
  2302. ThrowIfDisposedAndClosed ();
  2303. if (!is_connected)
  2304. throw new NotSupportedException ();
  2305. if (!File.Exists (fileName))
  2306. throw new FileNotFoundException ();
  2307. return BeginSendFile (fileName, null, null, 0, callback, state);
  2308. }
  2309. public IAsyncResult BeginSendFile (string fileName, byte[] preBuffer, byte[] postBuffer, TransmitFileOptions flags, AsyncCallback callback, object state)
  2310. {
  2311. ThrowIfDisposedAndClosed ();
  2312. if (!is_connected)
  2313. throw new NotSupportedException ();
  2314. if (!File.Exists (fileName))
  2315. throw new FileNotFoundException ();
  2316. SendFileHandler handler = new SendFileHandler (SendFile);
  2317. return new SendFileAsyncResult (handler, handler.BeginInvoke (fileName, preBuffer, postBuffer, flags, ar => callback (new SendFileAsyncResult (handler, ar)), state));
  2318. }
  2319. public void EndSendFile (IAsyncResult asyncResult)
  2320. {
  2321. ThrowIfDisposedAndClosed ();
  2322. if (asyncResult == null)
  2323. throw new ArgumentNullException ("asyncResult");
  2324. SendFileAsyncResult ares = asyncResult as SendFileAsyncResult;
  2325. if (ares == null)
  2326. throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
  2327. ares.Delegate.EndInvoke (ares.Original);
  2328. }
  2329. static bool SendFile_internal (SafeSocketHandle safeHandle, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags)
  2330. {
  2331. try {
  2332. safeHandle.RegisterForBlockingSyscall ();
  2333. return SendFile_internal (safeHandle.DangerousGetHandle (), filename, pre_buffer, post_buffer, flags);
  2334. } finally {
  2335. safeHandle.UnRegisterForBlockingSyscall ();
  2336. }
  2337. }
  2338. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2339. extern static bool SendFile_internal (IntPtr sock, string filename, byte [] pre_buffer, byte [] post_buffer, TransmitFileOptions flags);
  2340. delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
  2341. sealed class SendFileAsyncResult : IAsyncResult {
  2342. IAsyncResult ares;
  2343. SendFileHandler d;
  2344. public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
  2345. {
  2346. this.d = d;
  2347. this.ares = ares;
  2348. }
  2349. public object AsyncState {
  2350. get { return ares.AsyncState; }
  2351. }
  2352. public WaitHandle AsyncWaitHandle {
  2353. get { return ares.AsyncWaitHandle; }
  2354. }
  2355. public bool CompletedSynchronously {
  2356. get { return ares.CompletedSynchronously; }
  2357. }
  2358. public bool IsCompleted {
  2359. get { return ares.IsCompleted; }
  2360. }
  2361. public SendFileHandler Delegate {
  2362. get { return d; }
  2363. }
  2364. public IAsyncResult Original {
  2365. get { return ares; }
  2366. }
  2367. }
  2368. #endregion
  2369. #region SendPackets
  2370. [MonoTODO ("Not implemented")]
  2371. public bool SendPacketsAsync (SocketAsyncEventArgs e)
  2372. {
  2373. // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
  2374. ThrowIfDisposedAndClosed ();
  2375. throw new NotImplementedException ();
  2376. }
  2377. #endregion
  2378. #region DuplicateAndClose
  2379. #if !MOBILE
  2380. [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
  2381. public SocketInformation DuplicateAndClose (int targetProcessId)
  2382. {
  2383. var si = new SocketInformation ();
  2384. si.Options =
  2385. (is_listening ? SocketInformationOptions.Listening : 0) |
  2386. (is_connected ? SocketInformationOptions.Connected : 0) |
  2387. (is_blocking ? 0 : SocketInformationOptions.NonBlocking) |
  2388. (use_overlapped_io ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
  2389. si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)address_family, (int)socket_type, (int)protocol_type, is_bound ? 1 : 0, (long)Handle);
  2390. safe_handle = null;
  2391. return si;
  2392. }
  2393. #endif
  2394. #endregion
  2395. #region GetSocketOption
  2396. public void GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
  2397. {
  2398. ThrowIfDisposedAndClosed ();
  2399. if (optionValue == null)
  2400. throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
  2401. int error;
  2402. GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref optionValue, out error);
  2403. if (error != 0)
  2404. throw new SocketException (error);
  2405. }
  2406. public byte [] GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int length)
  2407. {
  2408. ThrowIfDisposedAndClosed ();
  2409. int error;
  2410. byte[] byte_val = new byte [length];
  2411. GetSocketOption_arr_internal (safe_handle, optionLevel, optionName, ref byte_val, out error);
  2412. if (error != 0)
  2413. throw new SocketException (error);
  2414. return byte_val;
  2415. }
  2416. public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
  2417. {
  2418. ThrowIfDisposedAndClosed ();
  2419. int error;
  2420. object obj_val;
  2421. GetSocketOption_obj_internal (safe_handle, optionLevel, optionName, out obj_val, out error);
  2422. if (error != 0)
  2423. throw new SocketException (error);
  2424. if (optionName == SocketOptionName.Linger)
  2425. return (LingerOption) obj_val;
  2426. else if (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)
  2427. return (MulticastOption) obj_val;
  2428. else if (obj_val is int)
  2429. return (int) obj_val;
  2430. else
  2431. return obj_val;
  2432. }
  2433. static void GetSocketOption_arr_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error)
  2434. {
  2435. bool release = false;
  2436. try {
  2437. safeHandle.DangerousAddRef (ref release);
  2438. GetSocketOption_arr_internal (safeHandle.DangerousGetHandle (), level, name, ref byte_val, out error);
  2439. } finally {
  2440. if (release)
  2441. safeHandle.DangerousRelease ();
  2442. }
  2443. }
  2444. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2445. extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val, out int error);
  2446. static void GetSocketOption_obj_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error)
  2447. {
  2448. bool release = false;
  2449. try {
  2450. safeHandle.DangerousAddRef (ref release);
  2451. GetSocketOption_obj_internal (safeHandle.DangerousGetHandle (), level, name, out obj_val, out error);
  2452. } finally {
  2453. if (release)
  2454. safeHandle.DangerousRelease ();
  2455. }
  2456. }
  2457. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2458. extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val, out int error);
  2459. #endregion
  2460. #region SetSocketOption
  2461. public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, byte [] optionValue)
  2462. {
  2463. ThrowIfDisposedAndClosed ();
  2464. // I'd throw an ArgumentNullException, but this is what MS does.
  2465. if (optionValue == null)
  2466. throw new SocketException ((int) SocketError.Fault, "Error trying to dereference an invalid pointer");
  2467. int error;
  2468. SetSocketOption_internal (safe_handle, optionLevel, optionName, null, optionValue, 0, out error);
  2469. if (error != 0) {
  2470. if (error == (int) SocketError.InvalidArgument)
  2471. throw new ArgumentException ();
  2472. throw new SocketException (error);
  2473. }
  2474. }
  2475. public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, object optionValue)
  2476. {
  2477. ThrowIfDisposedAndClosed ();
  2478. // NOTE: if a null is passed, the byte[] overload is used instead...
  2479. if (optionValue == null)
  2480. throw new ArgumentNullException("optionValue");
  2481. int error;
  2482. if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.Linger) {
  2483. LingerOption linger = optionValue as LingerOption;
  2484. if (linger == null)
  2485. throw new ArgumentException ("A 'LingerOption' value must be specified.", "optionValue");
  2486. SetSocketOption_internal (safe_handle, optionLevel, optionName, linger, null, 0, out error);
  2487. } else if (optionLevel == SocketOptionLevel.IP && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  2488. MulticastOption multicast = optionValue as MulticastOption;
  2489. if (multicast == null)
  2490. throw new ArgumentException ("A 'MulticastOption' value must be specified.", "optionValue");
  2491. SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
  2492. } else if (optionLevel == SocketOptionLevel.IPv6 && (optionName == SocketOptionName.AddMembership || optionName == SocketOptionName.DropMembership)) {
  2493. IPv6MulticastOption multicast = optionValue as IPv6MulticastOption;
  2494. if (multicast == null)
  2495. throw new ArgumentException ("A 'IPv6MulticastOption' value must be specified.", "optionValue");
  2496. SetSocketOption_internal (safe_handle, optionLevel, optionName, multicast, null, 0, out error);
  2497. } else {
  2498. throw new ArgumentException ("Invalid value specified.", "optionValue");
  2499. }
  2500. if (error != 0) {
  2501. if (error == (int) SocketError.InvalidArgument)
  2502. throw new ArgumentException ();
  2503. throw new SocketException (error);
  2504. }
  2505. }
  2506. public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
  2507. {
  2508. int int_val = optionValue ? 1 : 0;
  2509. SetSocketOption (optionLevel, optionName, int_val);
  2510. }
  2511. public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
  2512. {
  2513. ThrowIfDisposedAndClosed ();
  2514. if (optionLevel == SocketOptionLevel.Socket && optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse (protocol_type))
  2515. throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
  2516. int error;
  2517. SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
  2518. if (error != 0) {
  2519. if (error == (int) SocketError.InvalidArgument)
  2520. throw new ArgumentException ();
  2521. throw new SocketException (error);
  2522. }
  2523. }
  2524. static void SetSocketOption_internal (SafeSocketHandle safeHandle, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error)
  2525. {
  2526. bool release = false;
  2527. try {
  2528. safeHandle.DangerousAddRef (ref release);
  2529. SetSocketOption_internal (safeHandle.DangerousGetHandle (), level, name, obj_val, byte_val, int_val, out error);
  2530. } finally {
  2531. if (release)
  2532. safeHandle.DangerousRelease ();
  2533. }
  2534. }
  2535. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2536. extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte [] byte_val, int int_val, out int error);
  2537. #endregion
  2538. #region IOControl
  2539. public int IOControl (int ioctl_code, byte [] in_value, byte [] out_value)
  2540. {
  2541. if (is_disposed)
  2542. throw new ObjectDisposedException (GetType ().ToString ());
  2543. int error;
  2544. int result = IOControl_internal (safe_handle, ioctl_code, in_value, out_value, out error);
  2545. if (error != 0)
  2546. throw new SocketException (error);
  2547. if (result == -1)
  2548. throw new InvalidOperationException ("Must use Blocking property instead.");
  2549. return result;
  2550. }
  2551. public int IOControl (IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue)
  2552. {
  2553. return IOControl ((int) ioControlCode, optionInValue, optionOutValue);
  2554. }
  2555. static int IOControl_internal (SafeSocketHandle safeHandle, int ioctl_code, byte [] input, byte [] output, out int error)
  2556. {
  2557. bool release = false;
  2558. try {
  2559. safeHandle.DangerousAddRef (ref release);
  2560. return IOControl_internal (safeHandle.DangerousGetHandle (), ioctl_code, input, output, out error);
  2561. } finally {
  2562. if (release)
  2563. safeHandle.DangerousRelease ();
  2564. }
  2565. }
  2566. /* See Socket.IOControl, WSAIoctl documentation in MSDN. The common options between UNIX
  2567. * and Winsock are FIONREAD, FIONBIO and SIOCATMARK. Anything else will depend on the system
  2568. * except SIO_KEEPALIVE_VALS which is properly handled on both windows and linux. */
  2569. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2570. extern static int IOControl_internal (IntPtr sock, int ioctl_code, byte [] input, byte [] output, out int error);
  2571. #endregion
  2572. #region Close
  2573. public void Close ()
  2574. {
  2575. linger_timeout = 0;
  2576. Dispose ();
  2577. }
  2578. public void Close (int timeout)
  2579. {
  2580. linger_timeout = timeout;
  2581. Dispose ();
  2582. }
  2583. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2584. internal extern static void Close_internal (IntPtr socket, out int error);
  2585. #endregion
  2586. #region Shutdown
  2587. public void Shutdown (SocketShutdown how)
  2588. {
  2589. ThrowIfDisposedAndClosed ();
  2590. if (!is_connected)
  2591. throw new SocketException (10057); // Not connected
  2592. int error;
  2593. Shutdown_internal (safe_handle, how, out error);
  2594. if (error != 0)
  2595. throw new SocketException (error);
  2596. }
  2597. static void Shutdown_internal (SafeSocketHandle safeHandle, SocketShutdown how, out int error)
  2598. {
  2599. bool release = false;
  2600. try {
  2601. safeHandle.DangerousAddRef (ref release);
  2602. Shutdown_internal (safeHandle.DangerousGetHandle (), how, out error);
  2603. } finally {
  2604. if (release)
  2605. safeHandle.DangerousRelease ();
  2606. }
  2607. }
  2608. [MethodImplAttribute (MethodImplOptions.InternalCall)]
  2609. internal extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
  2610. #endregion
  2611. #region Dispose
  2612. protected virtual void Dispose (bool disposing)
  2613. {
  2614. if (is_disposed)
  2615. return;
  2616. is_disposed = true;
  2617. bool was_connected = is_connected;
  2618. is_connected = false;
  2619. if (safe_handle != null) {
  2620. is_closed = true;
  2621. IntPtr x = Handle;
  2622. if (was_connected)
  2623. Linger (x);
  2624. safe_handle.Dispose ();
  2625. }
  2626. }
  2627. public void Dispose ()
  2628. {
  2629. Dispose (true);
  2630. GC.SuppressFinalize (this);
  2631. }
  2632. void Linger (IntPtr handle)
  2633. {
  2634. if (!is_connected || linger_timeout <= 0)
  2635. return;
  2636. /* We don't want to receive any more data */
  2637. int error;
  2638. Shutdown_internal (handle, SocketShutdown.Receive, out error);
  2639. if (error != 0)
  2640. return;
  2641. int seconds = linger_timeout / 1000;
  2642. int ms = linger_timeout % 1000;
  2643. if (ms > 0) {
  2644. /* If the other end closes, this will return 'true' with 'Available' == 0 */
  2645. Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
  2646. if (error != 0)
  2647. return;
  2648. }
  2649. if (seconds > 0) {
  2650. LingerOption linger = new LingerOption (true, seconds);
  2651. SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
  2652. /* Not needed, we're closing upon return */
  2653. //if (error != 0)
  2654. // return;
  2655. }
  2656. }
  2657. #endregion
  2658. void ThrowIfDisposedAndClosed (Socket socket)
  2659. {
  2660. if (socket.is_disposed && socket.is_closed)
  2661. throw new ObjectDisposedException (socket.GetType ().ToString ());
  2662. }
  2663. void ThrowIfDisposedAndClosed ()
  2664. {
  2665. if (is_disposed && is_closed)
  2666. throw new ObjectDisposedException (GetType ().ToString ());
  2667. }
  2668. void ThrowIfBufferNull (byte[] buffer)
  2669. {
  2670. if (buffer == null)
  2671. throw new ArgumentNullException ("buffer");
  2672. }
  2673. void ThrowIfBufferOutOfRange (byte[] buffer, int offset, int size)
  2674. {
  2675. if (offset < 0)
  2676. throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
  2677. if (offset > buffer.Length)
  2678. throw new ArgumentOutOfRangeException ("offset", "offset must be <= buffer.Length");
  2679. if (size < 0)
  2680. throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
  2681. if (size > buffer.Length - offset)
  2682. throw new ArgumentOutOfRangeException ("size", "size must be <= buffer.Length - offset");
  2683. }
  2684. void ThrowIfUdp ()
  2685. {
  2686. #if !NET_2_1 || MOBILE
  2687. if (protocol_type == ProtocolType.Udp)
  2688. throw new SocketException ((int)SocketError.ProtocolOption);
  2689. #endif
  2690. }
  2691. SocketAsyncResult ValidateEndIAsyncResult (IAsyncResult ares, string methodName, string argName)
  2692. {
  2693. if (ares == null)
  2694. throw new ArgumentNullException (argName);
  2695. SocketAsyncResult sockares = ares as SocketAsyncResult;
  2696. if (sockares == null)
  2697. throw new ArgumentException ("Invalid IAsyncResult", argName);
  2698. if (Interlocked.CompareExchange (ref sockares.EndCalled, 1, 0) == 1)
  2699. throw new InvalidOperationException (methodName + " can only be called once per asynchronous operation");
  2700. return sockares;
  2701. }
  2702. void QueueIOSelectorJob (Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue, IntPtr handle, IOSelectorJob job)
  2703. {
  2704. int count;
  2705. lock (queue) {
  2706. queue.Enqueue (new KeyValuePair<IntPtr, IOSelectorJob> (handle, job));
  2707. count = queue.Count;
  2708. }
  2709. if (count == 1)
  2710. IOSelector.Add (handle, job);
  2711. }
  2712. void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
  2713. {
  2714. e.socket_async_result.Init (this, callback, state, operation);
  2715. if (e.AcceptSocket != null) {
  2716. e.socket_async_result.AcceptSocket = e.AcceptSocket;
  2717. }
  2718. e.current_socket = this;
  2719. e.SetLastOperation (SocketOperationToSocketAsyncOperation (operation));
  2720. e.SocketError = SocketError.Success;
  2721. e.BytesTransferred = 0;
  2722. }
  2723. SocketAsyncOperation SocketOperationToSocketAsyncOperation (SocketOperation op)
  2724. {
  2725. switch (op) {
  2726. case SocketOperation.Connect:
  2727. return SocketAsyncOperation.Connect;
  2728. case SocketOperation.Accept:
  2729. return SocketAsyncOperation.Accept;
  2730. case SocketOperation.Disconnect:
  2731. return SocketAsyncOperation.Disconnect;
  2732. case SocketOperation.Receive:
  2733. case SocketOperation.ReceiveGeneric:
  2734. return SocketAsyncOperation.Receive;
  2735. case SocketOperation.ReceiveFrom:
  2736. return SocketAsyncOperation.ReceiveFrom;
  2737. case SocketOperation.Send:
  2738. case SocketOperation.SendGeneric:
  2739. return SocketAsyncOperation.Send;
  2740. case SocketOperation.SendTo:
  2741. return SocketAsyncOperation.SendTo;
  2742. default:
  2743. throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
  2744. }
  2745. }
  2746. IPEndPoint RemapIPEndPoint (IPEndPoint input) {
  2747. // If socket is DualMode ensure we automatically handle mapping IPv4 addresses to IPv6.
  2748. if (IsDualMode && input.AddressFamily == AddressFamily.InterNetwork)
  2749. return new IPEndPoint (input.Address.MapToIPv6 (), input.Port);
  2750. return input;
  2751. }
  2752. [StructLayout (LayoutKind.Sequential)]
  2753. struct WSABUF {
  2754. public int len;
  2755. public IntPtr buf;
  2756. }
  2757. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2758. internal static extern void cancel_blocking_socket_operation (Thread thread);
  2759. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  2760. internal static extern bool SupportsPortReuse (ProtocolType proto);
  2761. }
  2762. }