Socket.cs 89 KB

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